CORS issue - API and web on different domains

Hey guys,

I’m trying to deploy a redwood app to AWS. Due to design reasons, I would like to have the api in api.mydomain.com and the web in mydomain.com or www.mydomain.com.

The thing is that when I fetch the graphql function from mydomain.com to api.mydomain.com I get a CORS error:

Access to fetch at 'https://mydomain.io/dev/functions/graphql' from origin 'https://www.mydomain.io' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

So, I need to add to the graphql Function response headers:

 `'Access-Control-Allow-Origin': '*'
 'Access-Control-Allow-Credentials': true`

But I didn’t found a way of adding the headers.

I found here that is posible to pass options to the createHandler method in apollo-server-lambda.

The questions to solve are:

  • Is there a way to pass these options in src/function/graphql.js file to createHandler?
  • Is there another strategy to handle cors on graphql.js?

Thanks!

1 Like

Hi @leoalbin.

If CORS is enabled per apollo-server-lambda’s instructions I confirmed that I did get the response headers … I just inspected http://localhost:8911/graphql for a quick check.

Before Change

Screenshot 2020-07-31 07.08.01

After Change

Screenshot 2020-07-31 07.11.53

The Change

In redwoodjs/redwood/packages/api/src/functions/graphql.ts, add cors options in createHandler:

createHandler({
    cors: {
      origin: '*',
      credentials: true,
    },
  })

I’ll tried to enable CORS via the createGraphQLHandler’s callback and options but no luck (but I may not be doing it correctly).

I wonder @peterp if CORS should be enabled as the default behavior? Or perhaps make it an option to set origin: true or origin: * and the credentials?

1 Like

Interesting, we’re just passing these values along to the apollo-server, but maybe there’s a bug:

1 Like

Ah, I see what it may be… we’re wrapping the Apollo handler in another handler so that we can catch the exceptions!

We should fix this!

1 Like

Fixed over here: https://github.com/redwoodjs/redwood/pull/1175

3 Likes

This is great! – and what I was trying to say about:

@Chris and I were chatting yesterday about this and should be what he needs.

1 Like

This has now been released, check the cors option in createGraphQLHandler

2 Likes

That’s great, thank you a lot! I solved it moving everything into the same domain (API and web), but it’s a great improvement because having the API and the web in different subdomains adds a lot of flexibility. Thanks!

2 Likes

I’m having similar issue, with api deployed on a different domain and a cors issue, I’ve added the settings to the handler as @dthyresson had suggested but am still getting the error but only for the currenty user query. I have a dev endpoint up still so this should be able to replicate.

This request has a response with access-control-allow-origin: * :

curl 'https://uk5gegwopd.execute-api.us-east-2.amazonaws.com/.netlify/functions/graphql' \
  -H 'authority: uk5gegwopd.execute-api.us-east-2.amazonaws.com' \
  -H 'pragma: no-cache' \
  -H 'cache-control: no-cache' \
  -H 'accept: */*' \
  -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36' \
  -H 'content-type: application/json' \
  -H 'sec-gpc: 1' \
  -H 'origin: http://localhost:8910' \
  -H 'sec-fetch-site: cross-site' \
  -H 'sec-fetch-mode: cors' \
  -H 'sec-fetch-dest: empty' \
  -H 'referer: http://localhost:8910/' \
  -H 'accept-language: en-GB,en-US;q=0.9,en;q=0.8' \
  --data-raw $'{"operationName":"FIND_PROJECT_BY_USERNAME_TITLE","variables":{"userName":"caterpillar","projectTitle":"moving_fish"},"query":"query FIND_PROJECT_BY_USERNAME_TITLE($userName: String\u0021, $projectTitle: String, $currentUserId: String) {\\n  userProject: userName(userName: $userName) {\\n    id\\n    name\\n    userName\\n    bio\\n    image\\n    Project(projectTitle: $projectTitle) {\\n      id\\n      title\\n      description\\n      code\\n      mainImage\\n      createdAt\\n      updatedAt\\n      cadPackage\\n      forkedFrom {\\n        id\\n        title\\n        user {\\n          id\\n          userName\\n          __typename\\n        }\\n        __typename\\n      }\\n      Reaction {\\n        emote\\n        __typename\\n      }\\n      userReactions: Reaction(userId: $currentUserId) {\\n        emote\\n        __typename\\n      }\\n      Comment {\\n        id\\n        text\\n        createdAt\\n        user {\\n          userName\\n          image\\n          __typename\\n        }\\n        __typename\\n      }\\n      __typename\\n    }\\n    __typename\\n  }\\n}\\n"}' \
  --compressed -v

while this request which is hitting the same endpoint does not

curl 'https://uk5gegwopd.execute-api.us-east-2.amazonaws.com/.netlify/functions/graphql' \
  -H 'pragma: no-cache' \
  -H 'cache-control: no-cache' \
  -H 'accept-language: en-GB,en-US;q=0.9,en;q=0.8' \
  -H 'authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2Mzc0NDkwNjEsInN1YiI6IjNjYTk2ZTM2LWVjNmQtNDQ5Yy04YTIyLTc3N2MwNGQxNzM1NiIsImVtYWlsIjoiay5odXR0ZW5AcHJvdG9ubWFpbC5jaCIsImFwcF9tZXRhZGF0YSI6eyJyb2xlcyI6WyJ1c2VyIiwiYWRtaW4iXX0sInVzZXJfbWV0YWRhdGEiOnsiZnVsbF9uYW1lIjoiS3VydCBIdXR0ZW4ifX0.xYQQ_tb9Jx0GsaWmUGHddgbHZ2-zKX6cAQmrUU7GPdg' \
  -H 'content-type: application/json' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36' \
  -H 'Referer: http://localhost:8910/' \
  -H 'auth-provider: goTrue' \
  --data-raw '{"query":"query __REDWOOD__AUTH_GET_CURRENT_USER { redwood { currentUser } }"}' \
  --compressed -v

Since the query redwood { currentUser }} is not part of the user defined graphql schema, could something funny/unique be happing with this particular query.

For reference this is branch I’ve deployed the above from using yarn rw deploy aws serverless