📄

Hasura + Remote Schemas + graphql-upload はできない

2023/06/29に公開

概要

HasuraRemote SchemasApollo Server を繋げて開発していました。Apollo Server に graphql-upload を導入して、multipart file uploads を有効化しました。

そして、フロントエンド (React + Vite) に Apollo Clientapollo-upload-client を使っていつも通りファイルのアップロードを実装しようとしました。そして、いざ、ファイルをアップロードしようとしたら次のエラーが。。

ApolloError: Error in $: Failed reading: takeWhile1 at '-----WebKitFormBoundaryHOGEHOGE(ランダムな文字列)'
エラーが起こったセッティング

Remote Schemas: Apollo Server + graphql-upload

import { createServer } from 'http'

import { ApolloServer } from 'apollo-server-express'
import express from 'express'
import { graphqlUploadExpress } from 'graphql-upload'

 const app = async () => {
  const server = new ApolloServer({
    cors: {
      origin: ['http://localhost:28080'],
      credentials: true,
    },
    csrfPrevention: true,
    schema,
    context,
    plugins: [loggingPlugin],
  })
  const app = express()
  const httpServer = createServer(app)

  await server.start()

  app.use(graphqlUploadExpress({ maxFileSize: 1024 * 1024 * 25, maxFiles: 1 }))

  server.applyMiddleware({ app, path: server.graphqlPath })

  httpServer.listen({ port: 20000 }, () => {
    logger.info(`Server ready at http://localhost:20000${server.graphqlPath}`)
  })
}

app()

Frontend: React + Apollo Client + apollo-upload-client

import { createUploadLink } from 'apollo-upload-client'

const scalarsLink = ApolloLink.from([
  errorLink,
  createUploadLink({ uri }),
])
// 以下略

検索してもエラーはヒットせず、いくらフロントのコードやバックエンドのコードを見てもわからない状態がしばらく続きました。Apollo Server のロガーも見直していたところ、そもそも Apollo Server にファイルアップロードについてのアクセスログもないという状態でした。
途方に暮れていた時に、ある可能性に気づきました。

もしかして: Hasura が対応していない

その直感は正しく、検索すれば、Hasura が graphql-upload の採用している graphql-multipart-request-spec をサポートしていないことがわかりました。

https://github.com/hasura/graphql-engine/issues/2419

https://github.com/hasura/graphql-engine/issues/1326

などに書いてあります。

そのため、次の記事にあるような別の手段を取る必要があります。

https://zenn.dev/msorz/articles/47b47acedb3c5e

上記記事でも紹介されていますが、

https://hasura.io/blog/building-file-upload-downloads-for-your-hasura-app/

のように、Hasura とは別のエンドポイントを用意するなどの手段を推奨しているようです。
私も泣く泣く
https://zenn.dev/lincwell_inc/articles/97cc3e84c953d1
の方法を用いて、別のエンドポイントからファイルをアップロードするように変更しました。Hasura に graphql-multipart-request-spec サポートしてもらう方がベストですが。

エラーログから、この記事がヒットし、少しでも後の開発者が同じエラーに苦しむことがないようなことを願っています。

Discussion