0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[備忘録] LaravelでQueueを実装した際にReact側で発生したエラーについて

0
Posted at

概要

学習用のフォルダでQueueについて実装したところ、500と405のエラーが発生した。

実装パターン

Laravel(API)で「メモ一覧をテキストファイルに書き出す処理」を非同期ジョブとして実行し、React(SPA)で「ジョブの進捗と結果URL」を表示できる画面を作成していた。

発生したエラーの原因について

1. ログイン周りで発生したエラー(500)について

LaravelがHTTPS:443で待っていたにも関わらずVite proxyがHTTP(80相当)に投げていたためtargetのズレが発生していた
実際の原因はバックエンドの500ではなく、Viteのproxy転送失敗(socket hang up)だった。
ブラウザ上は 500 に見えるが、Laravelに到達する前に接続が切れていた。

2. エクスポート開始で405のエラー

フロント側のリクエストメソッドがLaravelのルート定義と一致していなかった。

エクスポート処理のためLaravel側で
Route::post('/memos/export',[MemoController::class, 'export']);
と記述したにも関わらず、React側でpost通信の実装がされていなかった

3. ファイルURLで ERR_EMPTY_RESPONSE / Empty reply が発生

Laravelはhttps:443で配信しているのに、APP_URL 由来で生成されたresult_urlがhttpになっており、ブラウザで`http側へアクセスしてしまった。

それぞれの解決方法

1. Vite の proxy 修正

下記のようにtargetをhttp:80からhttps:443に修正

vite.config.js
export default defineConfig({
// 省略
  server: {
    proxy: {
      "/api":{
        target: "https://localhost:443",
        changeOrigin: true,
        secure: false,
      },
    },
  },
// 省略

2. Reactの実装内容修正

sail artisan route:listコマンドを実行し確認することでLaravel側ではPOST通信されていることを確認
その後、React側で実装内容が誤っていたので下記のように修正した。
修正前ではmethodの指定がなかったためGET通信を行なっていたことが原因だった。

job.jsx
// 修正前 (method指定なしのためGET扱い)
return apiRequest('/memos/export');

// 修正後
export function startMemosExport() {
  return apiRequest('/memos/export', { method: 'POST' });
}

3. httpsで確認する

対象のページについてhttpで確認していたところを、httpsで開き無事ページを確認することができた。

その他の対応

APIクライアントに対して認証ヘッダを付与する対応

修正前のapiClient.jsxでは認証ヘッダが付与されていなかった。
そこでapiClient.jsxに対して実装内容を追加し修正した。

apiClient.jsx
import { getToken } from '../lib/api';

const BASE_URL = import.meta.env.VITE_API_BASE_URL;

export async function apiRequest(path, { method = 'GET', body, signal } = {}) {
  const url = `${BASE_URL}${path}`;

  const token = getToken();

  const headers = {
    'Content-Type': 'application/json',
  };
  if (token) headers.Authorization = `Bearer ${token}`;

  // 省略
}

この実装の目的は、ログインで取得したトークンを以降のAPI呼び出しに必ず付けて 「認証済みユーザー」として扱ってもらうためである

この実装を行わないことで、認証が必要なAPI全て失敗してしまうことや今回の実装においてジョブの監視が止まらない状態になってしまう。
これはLaravel側のAPIがauth:sanctum や Bearer トークン前提だとAuthorization が無いリクエストは401や403エラーが発生してしまい、ジョブを取得するAPIがずっと401で失敗しステータスが変わらないために発生してしまう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?