I use Apollo on top of Hapi 17 and I can't find a way to make file upload work in my project so I made a simple example based on documentation and find out that it's not working either. Here's the repository for reproduction of the bug: https://github.com/D34THWINGS/test-hapi-apollo-upload
From what i've found so far, Hapi has not yet processed the request when onRequest extension endpoint is called. So the request.mime is null and the processFileUploads is therefore not called (ref ApolloServer.ts#L20)
I then tried some modifications:
onPreHandler extension point. This make the mime.type set to multipart/form-data and making us going further but still not working.request.raw.req to processFileUploads. This allows the code to make it further but this time the request hangs forever and I can't seem to find why.EDIT: Also tried the following:
request.headers.slice(0, 19) instead of request.mimerequest.raw.req to processFileUploads. But now throws: Cannot assign to read only property 'payload' because Hapi is later trying to modify payload which has been marked as read only property within handleFileUploads.EDIT 2: After making some extensive changes to the lib I found out that the parsing of the payload should be disabled for 'POST' on the /graphql route so the apollo-upload-server can do it's own parsing. But I think it should be better to have an implementation for Hapi that we should call within the request handler.
So if anyone with a better understanding can help me going through this, I would be happy to make a PR.
I'm running into this exact same problem.
I'm surprised more people aren't reporting this problem, it's completely blocking.
Chances are this was fixed in latest graphql-upload module v 8.0. The apollo-server uses v5
From what I see, graphql-upload v8.0 doesn't even support Hapi.
https://github.com/jaydenseric/graphql-upload/tree/master/src
Or am I misunderstanding something?
Seems like it never supported Hapi: https://github.com/jaydenseric/graphql-upload/blob/v5.0.0/src/middleware.mjs
I am running into this issue big time as well, I did however get it to work by dynamically turning on and off payload parsing in combination with manual parsing for file uploads.
const { ApolloServer, gql } = require('apollo-server-hapi');
const Hapi = require('hapi');
const { processRequest } = require('apollo-upload-server');
async function StartServer() {
const server = new ApolloServer({ typeDefs, resolvers });
const app = new Hapi.server({
port: 4000
});
await server.applyMiddleware({
app,
route: {
cors: process.env.NODE_ENV === 'development',
auth: {
mode: 'try'
},
ext: {
onPreAuth: {
method: async (request, h) => {
if (
request.raw.req.headers['content-type'].indexOf(
'multipart/form-data'
) > -1 &&
request.path === server.graphqlPath &&
request.method === 'post'
) {
request.route.settings.payload.parse = false;
request.mime = 'multipart/form-data';
request.pre['payload'] = await processRequest(
request.raw.req,
request.raw.res
);
} else {
request.route.settings.payload.parse = true;
}
return h.continue;
}
},
onPostAuth: {
method: async (request, h) => {
if (request.pre['payload']) {
request.payload = request.pre['payload'];
}
return h.continue;
}
}
}
}
});
await server.installSubscriptionHandlers(app.listener);
await app.start();
}
StartServer().catch(error => console.log(error));
I am running into this issue big time as well, I did however get it to work by dynamically turning on and off payload parsing in combination with manual parsing for file uploads.
Thank you for the code, it does the job!
Glad to hear that workaround does the job. Closing this issue because we won't be directly maintaining integrations with specific frameworks in Apollo Server 3.
I am running into this issue big time as well, I did however get it to work by dynamically turning on and off payload parsing in combination with manual parsing for file uploads.
const { ApolloServer, gql } = require('apollo-server-hapi'); const Hapi = require('hapi'); const { processRequest } = require('apollo-upload-server'); async function StartServer() { const server = new ApolloServer({ typeDefs, resolvers }); const app = new Hapi.server({ port: 4000 }); await server.applyMiddleware({ app, route: { cors: process.env.NODE_ENV === 'development', auth: { mode: 'try' }, ext: { onPreAuth: { method: async (request, h) => { if ( request.raw.req.headers['content-type'].indexOf( 'multipart/form-data' ) > -1 && request.path === server.graphqlPath && request.method === 'post' ) { request.route.settings.payload.parse = false; request.mime = 'multipart/form-data'; request.pre['payload'] = await processRequest( request.raw.req, request.raw.res ); } else { request.route.settings.payload.parse = true; } return h.continue; } }, onPostAuth: { method: async (request, h) => { if (request.pre['payload']) { request.payload = request.pre['payload']; } return h.continue; } } } } }); await server.installSubscriptionHandlers(app.listener); await app.start(); } StartServer().catch(error => console.log(error));
Putting this work around in somewhere more visible for Hapi devs will be very helpful.
I have spent several hours trying to figure out why the upload direction from documentation is return error 400
Most helpful comment
I am running into this issue big time as well, I did however get it to work by dynamically turning on and off payload parsing in combination with manual parsing for file uploads.