saito.k c059a2eabd Merged PR 815: XMLHttpRequestにてリクエストヘッダー「X-Requested-With: XMLHttpRequest」をコメントアウトしていればコメントアウトはずす
## 概要
[Task1806: XMLHttpRequestにてリクエストヘッダー「X-Requested-With: XMLHttpRequest」をコメントアウトしていればコメントアウトはずす](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/1806)

- 以下の開発規約に準拠するように修正
  - 可能な限り、JSONの場合(JSONPではない場合)は、XMLHttpRequestにてリクエストヘッダー「X-Requested-With: XMLHttpRequest」を設定し、サーバー側でチェックすること。

- Client
  - APIリクエスト時に、ヘッダーに「X-Requested-With: XMLHttpRequest」を付ける

- server
  - ヘッダーをチェックするミドルウェアを実装
    - /healthは画面からのリクエストではないので除外している
  - ミドルウェアをローカル環境以外で使用するように実装
    - ローカル環境ではサーバーから静的ファイルを配信しているから
       - APIリクエスト以外のリクエストにもmiddlewareが適用されてしまうのでローカル環境は除外している

## レビューポイント
- この修正で開発規約に準拠しているといえるか
- ローカル環境は除外したが、問題ないか
  - ローカルとdev,stg,prodで差異があることで、ローカルだけ発生しない問題が生じる可能性がある(その逆も)
  - 基本的に特定のヘッダーがあるかというチェックを追加しただけなので、大きな問題が発生するとは考えづらい

## UIの変更
- Before/Afterのスクショなど
- スクショ置き場

## クエリの変更
- Repositoryを変更し、クエリが変更された場合は変更内容を確認する
- Before/Afterのクエリ
- クエリ置き場

## 動作確認状況
- ローカルで確認、develop環境で確認
- 行った修正がデグレを発生させていないことを確認できるか
  - 事前にdev環境でAPI呼び出しができることを確認
  - すべてのAPIの呼び出しを確認したわけではないが、ログイン等の基本的な操作はできることを確認した

## 補足
- 相談、参考資料などがあれば
2024-03-11 07:26:01 +00:00

91 lines
2.7 KiB
TypeScript

import AppRouter from "AppRouter";
import { BrowserRouter } from "react-router-dom";
import { useMsal } from "@azure/msal-react";
import { useEffect, useLayoutEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import globalAxios, { AxiosError, AxiosResponse } from "axios";
import { clearToken } from "features/auth";
import { useTranslation } from "react-i18next";
import Snackbar from "components/snackbar";
import { selectSnackber } from "features/ui/selectors";
import { closeSnackbar } from "features/ui/uiSlice";
import { UNAUTHORIZED_TO_CONTINUE_ERROR_CODES } from "components/auth/constants";
import { clearUserInfo } from "features/login";
const App = (): JSX.Element => {
const dispatch = useDispatch();
const { instance } = useMsal();
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [t, i18n] = useTranslation();
useEffect(() => {
// すべてのリクエストのヘッダーにX-Requested-Withを追加
globalAxios.interceptors.request.use((config) => {
// headersがあれば追加、なければ新規作成
config.headers = config.headers || {};
// X-Requested-Withを追加
config.headers["X-Requested-With"] = "XMLHttpRequest";
return config;
});
const id = globalAxios.interceptors.response.use(
(response: AxiosResponse) => response,
(e: AxiosError<{ code?: string }>) => {
if (
e?.response?.status === 401 &&
e?.response?.data?.code &&
!UNAUTHORIZED_TO_CONTINUE_ERROR_CODES.includes(e.response.data.code)
) {
dispatch(clearToken());
dispatch(clearUserInfo());
instance.logoutRedirect({
postLogoutRedirectUri: "/?logout=true",
});
}
return Promise.reject(e);
}
);
const cleanup = () => {
globalAxios.interceptors.response.eject(id);
};
return cleanup;
}, [dispatch, instance]);
// Language読み取り
useLayoutEffect(() => {
const { cookie } = document;
if (cookie) {
const cookieArray = cookie.split(";");
const language = cookieArray.find((x) =>
// 先頭の空白を削除してから判定
x.trim().startsWith("language=")
);
if (language) {
i18n.changeLanguage(language.split("=")[1]);
}
}
}, [i18n]);
const snackbarInfo = useSelector(selectSnackber);
return (
<>
<Snackbar
isOpen={snackbarInfo.isOpen}
level={snackbarInfo.level}
message={t(snackbarInfo.message)}
duration={snackbarInfo.duration}
onClose={() => {
dispatch(closeSnackbar());
}}
/>
<BrowserRouter>
<AppRouter />
</BrowserRouter>
</>
);
};
export default App;