5

Ok so I see a lot of answers for how to enable cors for apollo-express, but I haven't found one really for apollo-server-lambda.

This is the error that I'm getting from chrome:

Access to XMLHttpRequest at 'https://5j3gae3086.execute-api.us-east-2.amazonaws.com/alpha/'
from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight
request doesn't pass access control check: The 'Access-Control-Allow-Origin' header
has a value 'https://example.com' that is not equal to the supplied origin.

I do not know how to change the value "https://example.com." Here is my code of how I'm trying to create the server:

const { ApolloServer } = require('apollo-server-lambda')
const typeDefs = require('./schema')
const resolvers = require ('./resolvers')

const server = new ApolloServer({
    typeDefs,
    resolvers,
    introspection: true,
    playground: {
        endpoint: "/alpha/graphql",
    },
  });

exports.graphqlHandler = server.createHandler({
    cors: {
        // origin: true,
        origin: "http://localhost:4200", // <-- This is not changing the header value. Do I need to do it from the frontend?
        credentials: true,
    },
  });

What else do I need to do here?

Edit I'm not sure if this is relevant, but here is my graphql.module.ts file. This is how I'm setting grahql in the frontend:

import { NgModule } from '@angular/core';
import { APOLLO_OPTIONS } from 'apollo-angular';
import { ApolloClientOptions, InMemoryCache } from '@apollo/client/core';
import { HttpLink } from 'apollo-angular/http';

const uri = 'https://5j3gae3086.execute-api.us-east-2.amazonaws.com/alpha/'; // <-- add the URL of the GraphQL server here
export function createApollo(httpLink: HttpLink): ApolloClientOptions<any> {
  return {
    link: httpLink.create({ uri,
      // these comments are things that I tried with no luck :(
      // fetchOptions: {
      //   mode: 'no-cors',
      // },
      //  headers: {
      // 'Access-Control-Allow-Origin': 'http://localhost:4200',
      // 'Access-Control-Allow-Methods': 'POST',
      // 'Access-Control-Allow-Headers': 'application/json'
      // "Access-Control-Allow-Credentials" : true
      // "X-CSRFToken": Cookies.get('csrftoken')
    // },
  }),
    cache: new InMemoryCache(),
  };
}



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

Also in case anyone is curious, I'm using AWS Api Gateway to use the lambda, but I believe I have the configuration for cors added correctly on that.

aws cors configuration

I'm at a loss with this. What do I need to change?

Felipe Centeno
  • 2,911
  • 1
  • 21
  • 39
  • The server responds with a 502 Bad Gateway error for requests to https://5j3gae3086.execute-api.us-east-2.amazonaws.com/alpha/. You can see the same error by opening that URL directly in a browser. So you don’t have a CORS problem. Fix the cause of the 502 error, and you’ll likely find your existing CORS config already works as expected. So check the logs on the `https://5j3gae3086.execute-api.us-east-2.amazonaws.com/alpha/` server; that 502 error would seem to mean it’s proxying in some way for another server, but failing to connect to that other server successfully. The logs will tell you. – sideshowbarker Sep 12 '20 at 00:38
  • Oh I was just playing with that trying to fix it. Let me revert that to a working state – Felipe Centeno Sep 12 '20 at 00:51
  • Ok, that's up and running. I can get queries from playground, but once I try to do an apollo query from my frontend I get the error described in the question. – Felipe Centeno Sep 12 '20 at 00:58
  • I just tried it on postman, and it works as expected. I'm suspecting my frontend now. – Felipe Centeno Sep 12 '20 at 01:24

2 Answers2

3

Following the CORS setup instructions here I can successfully use apollo-angular to return results for a simple query. No special headers etc. were needed.

https://www.apollographql.com/docs/apollo-server/deployment/lambda/

// serverless.yml
events:
  - http:
      path: graphql
      method: post
      cors: true
  - http:
      path: graphql
      method: get
      cors: true
// graphql.js
exports.graphqlHandler = server.createHandler({
  cors: {
    origin: '*',
    credentials: true,
  },
});
// graphql.module.ts
import {NgModule} from '@angular/core';
import {APOLLO_OPTIONS} from 'apollo-angular';
import {ApolloClientOptions, InMemoryCache} from '@apollo/client/core';
import {HttpLink} from 'apollo-angular/http';

const uri = 'https://xxx/dev/graphql';
export function createApollo(httpLink: HttpLink): ApolloClientOptions<any> {
  return {
    link: httpLink.create({uri}),
    cache: new InMemoryCache(),
  };
}

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

// In Angular 10
this.apollo
  .watchQuery({
    query: gql`
      {
        users {
          email
        }
      }
    `,
  })
  .valueChanges.subscribe(result => {
    console.log(result.data);
  });
zabumba
  • 12,172
  • 16
  • 72
  • 129
Matthew
  • 2,871
  • 5
  • 34
  • 59
2

Unlike an initial question, graphql.js is replaced to typescript as following.

// graphql.ts
exports.graphqlHandler = server.createHandler({
  expressGetMiddlewareOptions: {
    cors: {
      origin: '*',
      credentials: true,
    },
  },
});
Jack
  • 125
  • 1
  • 1
  • 10
  • I need to specify the route explicitly when using the credential flag. expressGetMiddlewareOptions: { cors: { origin: [ "https://example.com", "http://localhost:3000" ], credentials: true, }, } – Tobias Benkner Jun 06 '22 at 13:21
  • @TobiasBenkner So for tests, leave out `credentials` to not need to name the client domains? – Timo Jan 09 '23 at 21:33