32

I am writing a graphql server component on AWS Lambda (NOT using graphql-server). On the client side I'm using apollo-client. On the response of the lambda function I'm setting

const response = {
    statusCode: 200,
    headers: {
        "Access-Control-Allow-Origin": "*" // Required for CORS support to work
    },
    body: JSON.stringify({
        result: 'mock data',
        input: event,
    }),
};
callback(null, response);

On the client side using ApolloClient I get the following error

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.

However when I execute the same request using something like axios then it works fine. Furthermore when I just execute the request over something like postman I see the "Access-Control-Allow-Origin" setting enabled on the response. Is this a known issue with apollo-client and how do I fix this?

tmp dev
  • 8,043
  • 16
  • 53
  • 108
  • No, this is more likely an issue of you not being aware what a _preflight_ request is ... For what HTTP method(s) did specify that response you have shown? – CBroe Feb 16 '18 at 12:09

5 Answers5

41

To workaround the CORS issue with Apollo you have to pass the no-cors option to the underlying fetch.

import ApolloClient from "apollo-boost";

const client = new ApolloClient({
  uri: "your client uri goes here",
  fetchOptions: {
    mode: 'no-cors',
  },
});

This is not a specific Apollo problem, rather a configuration that is meant to be tackled on the fetch side, see this for more information: https://developers.google.com/web/ilt/pwa/working-with-the-fetch-api#cross-origin_requests

I wonder why it does works with Axios for you, I'd expect you to have the no-cors mode set somewhere.

ivanalejandro0
  • 1,689
  • 13
  • 13
8

Ivan's answer is correct for Apollo client 2.x.x.

For Apollo client >= 3.0.0 you can use:

import { ApolloClient, HttpLink } from '@apollo/client';

const client = new ApolloClient({
  link: new HttpLink({
      uri: 'your client uri goes here',
      fetchOptions: {
        mode: 'no-cors'
      }
  }),
});
Mahdi Aryayi
  • 1,090
  • 7
  • 13
3

I'd assume you're using the AWS API Gateway.

One question for you is: have you enabled CORS for your gateway? See how

I believe that should solve your issues, if you're also sending cookies, you can also set the "Access-Control-Allow-Credentials" : true header as well. `

oreoluwa
  • 5,553
  • 2
  • 20
  • 27
  • 3
    I have enabled CORS in the API gateway as well. Plus when I do a simple Axios command from the same client app to the same endpoint it works fine. Its just when I try to go through apollo-client it fails. – tmp dev Feb 17 '18 at 20:21
1

the first, fault we are doing is importing ApolloClient from 'apollo-boost'. Actually we have to import ApolloClient from 'apollo-client'.

import ApolloClient from 'apollo-client';

Because, ApolloClient from apollo-boost only supports a smaller subset of configuration options. ApolloClient from apollo-client gives you all the configuration options.

then we can provide link and cache only to Apollo-client instance

import { InMemoryCache } from "apollo-cache-inmemory";
import { createHttpLink } from 'apollo-link-http';

const client = new ApolloClient({ 
    link: new createHttpLink(
        {
            uri: "Your QraphQL Link"
        }
    ),
    cache: new InMemoryCache(),
});
0

here is a working example. the server must have CORS enabled. that means the origin of your http request

origin: https://example.com

must match the access-control-allow-origin header of the response to your request.

access-control-allow-origin: https://example.com

Then on the Angular client you can use this module:

import {NgModule} from '@angular/core';
import {ApolloModule, APOLLO_OPTIONS} from 'apollo-angular';
import {HttpLinkModule, HttpLink} from 'apollo-angular-link-http';
import {InMemoryCache} from 'apollo-cache-inmemory';
import {environment} from 'src/environments/environment';
import {errorLink} from './dm-core/graphql/apollo-link-error';
import {concat} from 'apollo-link';

export function createApollo(httpLink: HttpLink) {
    return {
        link: concat(errorLink, httpLink.create({uri: environment.graphql, withCredentials: true})),
        cache: new InMemoryCache(),
        defaultOptions: {
            watchQuery: {
                errorPolicy: 'all'
            }
        }
    };
}

@NgModule({
    exports: [ApolloModule, HttpLinkModule],
    providers: [
        {
            provide: APOLLO_OPTIONS,
            useFactory: createApollo,
            deps: [HttpLink]
        }
    ]
})
export class GraphQLModule {}

Note the "withCredentials: true":

    link: concat(errorLink, httpLink.create({uri: environment.graphql, withCredentials: true})),
David Dehghan
  • 22,159
  • 10
  • 107
  • 95