How to enable cors for apollo-server-lambda - aws-lambda

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.
I'm at a loss with this. What do I need to change?

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);
});

Unlike an initial question, graphql.js is replaced to typescript as following.
// graphql.ts
exports.graphqlHandler = server.createHandler({
expressGetMiddlewareOptions: {
cors: {
origin: '*',
credentials: true,
},
},
});

Related

Route url with variable in apolloGateway

There are several services that process graphql-requests on relative URLs.
Example: http://service:8080/graphql/a3333333-b111-c111-d111-e00000000011.
And I don’t understand how to config apolloGateway that part of url is a variable.
Try config url as:
const test_service: string = 'http://service:8080/graphql/:project';
supergraphSdl: new IntrospectAndCompose({
subgraphs: [
{ name: 'test_service', url: test_service },
],
}),
So full service look like:
import { ApolloServer } from 'apollo-server'
import { ApolloGateway, IntrospectAndCompose, RemoteGraphQLDataSource } from '#apollo/gateway'
const test_service: string = 'http://service:8080/graphql/:project';
const gateway_main = new ApolloGateway({
supergraphSdl: new IntrospectAndCompose({
subgraphs: [
{ name: 'test_service', url: test_service },
],
}),
});
const server_main = new ApolloServer({
introspection: true,
gateway: gateway_main
});
server_main.listen(8060).then(({ url }) => {
console.log(`Server ready at ${url}`);
});
But if I send a request to url http://service:8060/graphql/a3333333-b111-c111-d111-e00000000011
test_service get it as http://service/graphql/:project
So test_service lose uuid-data

Remote schema stitching with latest versions of Apollo and GraphQL tools

i'm having a hard time figuring out the problem with my setup. I have been looking at the documentations but between apollo and graphql-tools the APIs changed frequently.
When i run this script, the console says "Error: Query root type must be provided."
import { ApolloServer } from "apollo-server";
import { loadSchema } from "#graphql-tools/load";
import { UrlLoader } from "#graphql-tools/url-loader";
import { stitchSchemas } from "#graphql-tools/stitch";
import fetch from "node-fetch";
import dotenv from "dotenv";
dotenv.config({ path: "../.env" });
async function startServer() {
const shopifySchema = await loadSchema(process.env.SHOPIFY_STOREFRONT_URL, {
loaders: [new UrlLoader()],
headers: {
"X-Shopify-Storefront-Access-Token":
process.env.SHOPIFY_STOREFRONT_API_TOKEN,
},
fetch,
});
const contentfulSchema = await loadSchema(process.env.CONTENTFUL_API_URL, {
loaders: [new UrlLoader()],
headers: {
Authorization: `Bearer ${process.env.CONTENTFUL_API_TOKEN}`,
},
fetch,
});
const gatewaySchema = stitchSchemas({
subschemas: [{ schema: shopifySchema }, { schema: contentfulSchema }],
});
const server = new ApolloServer({ schema: gatewaySchema });
return await server.listen();
}
startServer().then(({ url }) => {
console.log(`πŸš€ Server ready at ${url}`);
});
These are my dependencies:
{
"#graphql-tools/load": "^7.3.2",
"#graphql-tools/schema": "^8.2.0",
"#graphql-tools/stitch": "^8.3.1",
"#graphql-tools/url-loader": "^7.2.0",
"apollo-server": "^3.4.0",
"dotenv": "^10.0.0",
"graphql": "^15.6.1",
"node-fetch": "^3.0.0"
}
Anyone knows what could be wrong with this?
Ok, i have found out that my url endpoints were just incorrect.
I'll leave the question open in case might be useful to someone.

how can I config proxy with axios

I'm working with nuxt.
as the following you see I set config for axios and proxy in the nuxt.config.js but it dose not work and return http://localhost:3000/laravel/register 404 (Not Found)
but I need http://localhost:8000/register.
what is the problem?
nuxt.config.js
modules: [
'#nuxtjs/axios',
'#nuxtjs/auth-next',
'#nuxtjs/proxy',
],
axios: {
proxy:true,
// baseURL: 'http://localhost:8000',
},
proxy: {
'/laravel': {
target: 'http://localhost:8000',
pathRewrite: { '^/laravel': '/' }
}
},
example use axios
Register() {
try {
const response = this.$axios.$post('/laravel/register', {
data: this.form,
})
console.log(response)
} catch (error) {
console.log(error)
}
},

Apollo studio CORS error unable to reach server

I'm trying to setup apollo server in my NextJS project, I'm using apollo-server-micro and I ran into these issues:
the apollo studio sandbox is unable to reach the server due to CORS.
This is in pages/api/graphql
import { ApolloServer } from "apollo-server-micro";
import { typeDefs } from "./schemas";
import { resolvers } from "./resolvers/index";
import { createContext } from "./db/context";
const apolloServer = new ApolloServer({
typeDefs,
resolvers,
context: ({ res, req }) => createContext(res, req),
uploads: false,
introspection: true,
formatError: (error) => {
console.log(error);
return error;
},
});
export const config = {
api: {
bodyParser: false,
externalResolver: true,
},
};
module.exports = apolloServer
.start()
.then(() => apolloServer.createHandler({ path: "/api/graphql" }));
then I tried to enable cors but without success because I get this error:
API resolved without sending a response for /api/graphql, this may result in stalled requests.
import { ApolloServer } from "apollo-server-micro";
import { typeDefs } from "./schemas";
import { resolvers } from "./resolvers/index";
import { createContext } from "./db/context";
import { send } from "micro";
import cors from "micro-cors";
const apolloServer = new ApolloServer({
typeDefs,
resolvers,
context: ({ res, req }) => createContext(res, req),
uploads: false,
introspection: true,
formatError: (error) => {
console.log(error);
return error;
},
});
export const config = {
api: {
bodyParser: false,
externalResolver: true,
},
};
module.exports = apolloServer.start().then(() => {
const handler = apolloServer.createHandler({ path: "/api/graphql" });
return cors((req, res) => {
console.log(res);
return req.method === "OPTIONS" ? send(res, 200, 'ok') : handler(req, res);
});
});

Apollo 2.0.0 Graphql cookie session

Can someone help me on this, My setup was as follows prior to Apollo 2.0, I had a server.js in which i used express and graphql-server-express
I had a http only cookie session, when a user logs in I set the jwt token as a cookie and it is set in browser as http only.
On subsequent request I validate the cookie that the browser passes back. It was all working fine and I could access
the token from req.session.token in any other resolver and validate the jwt token saved in the cookie session.
server.js
import express from 'express';
import { graphqlExpress, graphiqlExpress } from 'graphql-server-express';
import { ApolloEngine } from 'apollo-engine';
import bodyParser from 'body-parser';
import cors from 'cors';
import cookieSession from 'cookie-session';
import schema from './schema/';
​
const server = express();
​
server.use(
cookieSession({
name: 'session',
keys: 'k1,k2',
maxAge: 30 * 60 * 1000,
domain: '.mydomain.com',
path: '/',
}),
);
​
const corsOptions = {
origin: 'http://local.mydomain.com:3000',
credentials: true,
methods: ['GET', 'PUT', 'POST', 'OPTIONS'],
};
​
server.use(cors(corsOptions));
​
server.use(
'/graphql',
bodyParser.json(),
graphqlExpress(req => ({
schema,
tracing: true,
context: { req },
})),
);
​
if (process.env.NODE_ENV !== 'production') {
server.use('/graphiql',graphiqlExpress({endpointURL: '/graphql'}));
}
​
const engine = new ApolloEngine({
apiKey: engineConfig.apiKey,
});
​
engine.listen(
{
port: 3000,
graphqlPaths: ['/graphql'],
expressApp: server,
},
() => {console.log('GraphiQL is now running');},
);
authenticateResolver.js
const authenticateResolver = {
Query: {
authenticate: async (root, args, context) => {
const { req } = context;
​
const auth = `Basic ${Buffer.from(`${args.username}:${args.password}`).toString('base64')}`;
​
const axiosResponse = await axios.post("localhot:8080/login, 'true',
{
headers: {
Authorization: auth,
},
});
​
if (axiosResponse.status === 200 && axiosResponse.data.token) {
req.session.token = axiosResponse.data.token;
}
return {
status: 200,
};
},
But when I upgraded to Apollo 2.0 my server.js code changed, authenticateResolver was as is.
I am now unable to access req.session.token in any subsequent requests since the cookie session is not getting set.
When I open Developer tools in chrome I cannot see the cookie being set when Authentication is called.
What am I doing wrong here ?
server.js # After Apollo 2.0 upgrade
​
import express from 'express';
import { ApolloServer, gql } from 'apollo-server-express';
import cors from 'cors';
import cookieSession from 'cookie-session';
import { mergedTypes, resolvers } from './schema/';
​
const server = express();
​
server.use(
cookieSession({
name: 'session',
keys: 'k1,k2',
maxAge: 30 * 60 * 1000,
domain: '.mydomain.com',
path: '/',
}),
);
​
const corsOptions = {
origin: 'http://local.mydomain.com:3000',
credentials: true,
methods: ['GET', 'PUT', 'POST', 'OPTIONS'],
};
​
server.use(cors(corsOptions));
​
server.listen({ port: 3000 }, () => {
console.log('Server ready');
console.log('Try your health check at: .well-known/apollo/app-health');
});
​
const apollo = new ApolloServer({
typeDefs: gql`
${mergedTypes}
`,
resolvers,
engine: false,
context: ({ req }) => ({ req }),
});
​
apollo.applyMiddleware({
server
});
Yes, If you look at the graphql playground there is a settings option if you click on that you can observe few settings, one of them being
"request.credentials": "omit" just change it to
"request.credentials": "include" and save settings and it should now work.
My code looks as follows as well:
const app = express()
app.use(
cookieSession({
name: 'session',
keys: corsConfig.cookieSecret.split(','),
maxAge: 60 * 60 * 1000,
domain: corsConfig.cookieDomain,
path: '/',
})
)
const corsOptions = {
origin: corsConfig.corsWhitelist.split(','),
credentials: true,
methods: ['GET', 'PUT', 'POST', 'OPTIONS'],
}
app.use(cors(corsOptions))
const apollo = new ApolloServer({
typeDefs: gql`
${mergedTypes}
`,
resolvers,
engine: false,
context: ({ req }) => ({ req }),
tracing: true,
debug: !process.env.PRODUCTION,
introspection: !process.env.PRODUCTION,
})
apollo.applyMiddleware({
app,
path: '/',
cors: corsOptions,
})
app.listen({ port: engineConfig.port }, () => {
console.log('πŸš€ - Server ready')
console.log('Try your health check at: .well-known/apollo/app-health')
})

Resources