Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vercel base64 encoding empty body throws 'CORS' error from v0.37.0+ #3897

Closed
aaronvanston opened this issue Dec 13, 2021 · 6 comments · Fixed by #3939
Closed

Vercel base64 encoding empty body throws 'CORS' error from v0.37.0+ #3897

aaronvanston opened this issue Dec 13, 2021 · 6 comments · Fixed by #3939
Assignees
Labels
bug/confirmed We have confirmed this is a bug bug/repro-available A reproduction exists and needs to be confirmed

Comments

@aaronvanston
Copy link

aaronvanston commented Dec 13, 2021

Hey team,

I've come across an issue with base64 decoding of an empty event body, affecting Redwood instances deployed to Vercel on version 0.37.0 and up.

Overview

This issue is very similar to #3309 in which Vercel says the event body is encoded even if the event body is empty. This typically occurs when a preflight/ OPTIONS call happens from a remote server, the body is left empty. This check will fail and the browser will interpret this as failed CORS as the function exited before setting the correct response headers.

This affects any use of the GraphQL function from a remote server, despite correct CORS settings. Applies to instances with and without auth set-ups.

I believe it fails on the execution of this function:

https://github.com/redwoodjs/redwood/blob/main/packages/graphql-server/src/functions/graphql.ts#L50-L56

The server will return:

 {
  "data": {
    "errorMessage": "Unexpected end of JSON input",
    "errorType": "SyntaxError",
    "stack": [
      "SyntaxError: Unexpected end of JSON input",
      "    at JSON.parse (<anonymous>)",
      "    at parseEventBody (/var/task/node_modules/@redwoodjs/graphql-server/dist/functions/graphql.js:82:17)",
      "    at normalizeRequest (/var/task/node_modules/@redwoodjs/graphql-server/dist/functions/graphql.js:89:16)",
      "    at handlerFn (/var/task/node_modules/@redwoodjs/graphql-server/dist/functions/graphql.js:233:21)",
      "    at execFn (/var/task/node_modules/@redwoodjs/graphql-server/dist/functions/graphql.js:328:22)",
      "    at AsyncLocalStorage.run (async_hooks.js:314:14)",
      "    at Object.<anonymous> (/var/task/node_modules/@redwoodjs/graphql-server/dist/functions/graphql.js:337:58)",
      "    at Runtime.internal [as handler] (/var/task/___vc_launcher.js:33:25)",
      "    at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)"
    ]
  }
}

Steps to reproduce

  1. Create a new instance of RW from 0.37.0 and up. I've replicated this on 0.39.4
  2. Configure and deploy this to Vercel
  3. Try to call the graphQL server from a remote server in which a preflight check occurs. I've done this through a new install of nextJS and connected to the RW API via ApolloClient
  4. Optionally: Configure the CORS settings for your remote server. Regardless of these settings, it will exit early with the mentioned error

This should fail on the OPTIONS call to the server with chrome reporting a CORS error.

Vercel event body

I intercepted the failing Vercel event before it hit the GraphQL handler, and the event body consisted of:

{
  resource: '/{proxy+}',
  path: '/api/graphql',
  httpMethod: 'OPTIONS',
  body: undefined,
  isBase64Encoded: true,
  queryStringParameters: {},
  multiValueQueryStringParameters: [Object: null prototype] {},
  headers: {
    ...
  }
}

In this instance, you can see Vercel has marked it as base64 encoded at the same time it's undefined.

Extrapolating the parseEventBody function, and running this with an undefined body returns the same error:

Screen Shot 2021-12-13 at 9 40 01 pm

Public Example

I've created and publically hosted brand new instances of a Redwood API/Web (version 0.39.4) and a separate NextJS application calling the Redwood API.

Redwood:
Repo: https://github.com/aaronvanston/rw-vercel-test
URL: https://rw-vercel-test.vercel.app/

NextJS UI:
Repo: https://github.com/aaronvanston/nextjs-ui-rw-test
URL: https://nextjs-ui-rw-test.vercel.app/

If you visit the NextJS UI, I've set up a call to the Redwood API that triggers on page load. You can inspect your network and see it fails with a CORS error.

I believe the fix, is similar to that #3309 if I'm not mistaken? Users affected would be those deploying to Vercel and calling the Redwood API from an external source, potentially not a common use case?

Temporary fix

I've managed to put in a hacky fix that behaves like a middleware for the event and sends through an empty encoded object if the body is undefined.

export const handler = async (...all) => {
  const [event = {}, ...rest] = all

  const eventWithBody = {
    ...event,
    ...(event?.isBase64Encoded && { body: event?.body || 'e30=' }),
  }

  return rwGqlHandler(eventWithBody, rest)
}

Where rwGqlHandler is the original handler within the graphql.{ts|js} function file.

This fixes the issue but is quite hacky.

@aaronvanston
Copy link
Author

Please note, this error could have occurred on the previous version prior to 0.37.0, this just happens to be the version we upgraded to and the issue arose. We're currently stable on version 0.36.2 in production with no issue.

@thedavidprice
Copy link
Contributor

@viperfx I know you ran into this back in the day and we added support. Do you have any thoughts about this?

Here's an Issue and PR about this related to Auth specifically:

@viperfx
Copy link
Contributor

viperfx commented Dec 14, 2021

So because Vercel uses aws and this behavior is part of api gateway - the base64 encoding part I mean.

However, I've never seen it being undefined.

@dac09 dac09 added bug/repro-available A reproduction exists and needs to be confirmed bug/confirmed We have confirmed this is a bug v1/priority and removed triage/processing labels Dec 15, 2021
@dac09
Copy link
Collaborator

dac09 commented Dec 16, 2021

@dthyresson and I have confirmed this is an issue, specific to vercel deploys. Thank you very much for the reproduction. We will fix for next patch!

@dac09 dac09 added this to the next-release milestone Dec 17, 2021
@dac09 dac09 self-assigned this Dec 17, 2021
@dac09
Copy link
Collaborator

dac09 commented Dec 17, 2021

Confirming that this has been fixed!

e.g.

curl -X "OPTIONS" "https://cors-options-test-5rgrdffw2-redwoodjs.vercel.app/api/graphql"

@aaronvanston
Copy link
Author

Fantastic, thanks @dac09! 🎉

@jtoar jtoar removed this from the next-release milestone Jan 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug/confirmed We have confirmed this is a bug bug/repro-available A reproduction exists and needs to be confirmed
Projects
No open projects
Status: Archived
Status: Done
Development

Successfully merging a pull request may close this issue.

5 participants