😄

ApolloError: Response not successful: Received status code 405

2023/11/09に公開

はじめに

Nextjs で @apollo/server を使って GraphQLを実行していたところ、ローカル環境だと正常に動作するが、Vercelで動かすと405エラーになる問題が起きた。

import { ApolloServer } from "@apollo/server";
import { startServerAndCreateNextHandler } from "@as-integrations/next";
import { PrismaClient } from "@prisma/client";
import { readFileSync } from 'fs';
import path from "path";

const prisma = new PrismaClient();
const resolvers = {
  Query: {
    products: () => prisma.products.findMany(),
  },
};
const typeDefs = readFileSync('src/graphql/schema.gql', { encoding: 'utf-8' });
const server = new ApolloServer({
  resolvers,
  typeDefs,
});

export default startServerAndCreateNextHandler(server);

コンソールだと詳細なエラーを確認できないため、VercelのLogsからログを確認したところ ↓のようなエラーが発生していることを確認できた。
どうやら readFileSync() でのGraphQLスキーマファイルの読み込みに失敗しているようだ。

⨯ Error: ENOENT: no such file or directory, open 'src/graphql/schema.gql'
    at Object.openSync

readFileSync() でのスキーマファイル読み込みは Appllo Server の公式ドキュメント(↓) でも紹介している手法なので他の可能性が考えられる。

https://www.apollographql.com/docs/apollo-server/workflow/generate-types/#setting-up-your-project

結論

ビルドされたファイルはVercel環境の別の場所に作られるため、指定したパスがずれてしまうようだった。そのため process.cwd() でカレントディレクトリを取得し、ディレクトリ構造が変わっても対応できるようにする必要がある。

const typeDefs = readFileSync(schemaPath, { encoding: 'utf-8' });

ファイルを読み込む時は process.cwd() 使おうねとVercel公式ガイドにしっかり記載されていた 😇
https://vercel.com/guides/loading-static-file-nextjs-api-route#step-3-read-the-file

最終的なコード

import { ApolloServer } from "@apollo/server";
import { startServerAndCreateNextHandler } from "@as-integrations/next";
import { PrismaClient } from "@prisma/client";
import { readFileSync } from 'fs';
import path from "path";

const prisma = new PrismaClient();
const resolvers = {
  Query: {
    products: () => prisma.products.findMany(),
  },
};
const schemaPath = path.join(process.cwd(), 'src/graphql/schema.gql');
const typeDefs = readFileSync(schemaPath, { encoding: 'utf-8' });
const server = new ApolloServer({
  resolvers,
  typeDefs,
});

export default startServerAndCreateNextHandler(server);

Discussion