Closed ChrisW-B closed 1 year ago
Shouldn't OPTIONS
be in your list of allowed methods? I'm not a lambda expert, is there some configuration at the lambda level you need to make in order to handle OPTIONS
requests? (@BlenderDude will know better than I)
@BlenderDude we should probably get a CORS example up in the README here.
haha my bad, I posted an old example- I've tried with '*' as well as 'GET, POST, OPTIONS' since, but let me retry just in case I changed something else since then
@trevor-scheer given how popular the CORS request is, I intent on providing a built-in middleware that handles it, and will be adding that to the README.
The issue here is that Chrome does not allow for the *
origin wildcard. Most middleware implementations get around this by substituting *
with req.origin
. For API gateway v1, you'll need to figure out what headers and environment are exposed from Netlify. If there is an Origin header available, I recommend using req.headers.Origin
. This isn't always available though. In my experience, a more robust and portable solution is to utilize req.headers.Host
. Methods can be safely updated to *
. The updated handler would look like the following:
import { ApolloServer } from '@apollo/server';
import { ApolloServerPluginLandingPageLocalDefault } from '@apollo/server/plugin/landingPage/default';
import { handlers, startServerAndCreateLambdaHandler } from '@as-integrations/aws-lambda';
import schema from './db/graphql';
const server = new ApolloServer({
schema,
introspection: true,
plugins: [ApolloServerPluginLandingPageLocalDefault()],
});
const apolloHandler = handlers.createAPIGatewayProxyEventRequestHandler();
export const handler = startServerAndCreateLambdaHandler(server, apolloHandler, {
middleware: [
async (event) => {
// Below is an untested example, but should get you on the right track
let origin = event.headers.Origin;
if (origin === undefined) {
const host = event.headers.Host;
// Assume localhost is insecure, and everything else is using https
const isSecure = !/^localhost:\d{1,5}$/.test(host);
origin = `${isSecure ? 'https' : 'http'}://${host}`;
}
return async (result) => {
result.headers = {
...result.headers,
'access-control-allow-headers': 'content-type',
'access-control-allow-methods': '*',
'access-control-allow-origin': origin,
};
};
},
],
});
@BlenderDude thank you! I'll look into what Netlify allows and give that a try
Sadly no luck, I rewrote the middleware to
async (event) => {
let origin = event.headers.Origin;
const host = event.headers.Host;
if (!origin && host) {
const isSecure = /^localhost:\d{1,5}$/.test(host);
origin = `${isSecure ? 'https' : 'http'}://${host}`;
} else if (!origin) {
origin = '*';
}
return async (result) => {
result.headers = {
...result.headers,
'Access-Control-Allow-Headers': '*',
'Access-Control-Allow-Methods': '*',
'Access-Control-Allow-Origin': origin ?? '*',
};
};
},
(I modified the Allowed Headers because they were breaking the apollo studio setup)
and it looks like netlify isn't passing the origin or host, as I get an *
for the value in the end:
I'll spend some more time looking through netlify's docs later; but for now I'm going to roll this release back and keep an eye out for your built in middleware.
Thanks again for the help!
Partial fix:
...
return async (result: APIGatewayProxyResult) => {
if (event.httpMethod.toUpperCase() === "OPTIONS") {
result.statusCode = 200;
result.body = "";
}
...
Not a proper fix as apollo server still process the request.
Inspiration https://stackoverflow.com/a/63888972/2790481
This may be a better question for a support channel, so please redirect me if there's a better place to ask!
I've recently updated from
apollo-server-core@3.12.0
andapollo-server-lambda@3.12.0
to@apollo/server@4.7.0
and@as-integrations/aws-lambda@2.0.1
. I've been running this server on Netlify. This worked pretty well with v3.12.0, but after updating both Chrome and Firefox fail with a 400 error on the OPTIONS preflight request, meaning no data loads. Using the API directly in the browser with Apollo Studio works perfectly, and data loads in Safari fine as well.My setup code for the server looks like the following:
Am I missing some extra CORS setup?
Thanks for any help!