diff --git a/dictation_client/src/App.tsx b/dictation_client/src/App.tsx index f08dfd1..f730016 100644 --- a/dictation_client/src/App.tsx +++ b/dictation_client/src/App.tsx @@ -17,7 +17,16 @@ const App = (): JSX.Element => { 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 }>) => { diff --git a/dictation_server/src/app.module.ts b/dictation_server/src/app.module.ts index 667cde8..4022501 100644 --- a/dictation_server/src/app.module.ts +++ b/dictation_server/src/app.module.ts @@ -52,6 +52,7 @@ import { WorkflowsRepositoryModule } from './repositories/workflows/workflows.re import { TermsModule } from './features/terms/terms.module'; import { RedisModule } from './gateways/redis/redis.module'; import * as redisStore from 'cache-manager-redis-store'; +import { CheckHeaderMiddleware } from './common/check-header.middleware'; @Module({ imports: [ ServeStaticModule.forRootAsync({ @@ -164,6 +165,13 @@ import * as redisStore from 'cache-manager-redis-store'; }) export class AppModule { configure(consumer: MiddlewareConsumer) { - consumer.apply(LoggerMiddleware).forRoutes(''); + consumer + .apply(LoggerMiddleware) + .forRoutes(''); + // stage=localの場合はmiddlewareを適用しない + // ローカル環境ではサーバーから静的ファイルも返すため、APIリクエスト以外のリクエストにもmiddlewareが適用されてしまう + if (process.env.STAGE !== 'local') { + consumer.apply(CheckHeaderMiddleware).forRoutes(''); + } } } diff --git a/dictation_server/src/common/check-header.middleware.ts b/dictation_server/src/common/check-header.middleware.ts new file mode 100644 index 0000000..359b2e0 --- /dev/null +++ b/dictation_server/src/common/check-header.middleware.ts @@ -0,0 +1,32 @@ +import { + HttpException, + Injectable, + Logger, + NestMiddleware, +} from '@nestjs/common'; +import { Request, Response, NextFunction } from 'express'; + +/** + * CheckHeaderMiddleware + * リクエストヘッダのチェックを行うミドルウェア + * + * ローカル環境ではヘッダチェックを行わない + */ +@Injectable() +export class CheckHeaderMiddleware implements NestMiddleware { + private readonly logger = new Logger(CheckHeaderMiddleware.name); + use(req: Request, res: Response, next: NextFunction): void { + // /healthcheckはheaderチェックを行わない + if (req.url === '/health') { + next(); + return; + } + + if (req.headers['x-requested-with'] === 'XMLHttpRequest') { + next(); + } else { + this.logger.error('header check failed'); + throw new HttpException('header check failed', 400); + } + } +}