Apollo-client: Access-Control-Allow-Origin ignored in response header

Created on 13 Apr 2018  路  7Comments  路  Source: apollographql/apollo-client

Intended outcome:
Apollo recognizes the received headers, sends query, processes response.

Actual outcome:
Apollo ignores received Access-Control-Allow-Origin header, pops error in console, sends the query to the server, ignores the response.

As per packet capture between server & localhost:

Apollo sends:

OPTIONS /graphql HTTP/1.1
Host: meselok.hu
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://localhost:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36
Access-Control-Request-Headers: content-type
Accept: /

Server responds:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://localhost:8080
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Max-Age: 86400
Access-Control-Allow-Headers: Content-Type
Content-Length: 0
Content-Type: application/octet-stream
Date: Fri, 13 Apr 2018 11:38:55 GMT
Server: Python/3.6 aiohttp/3.1.2
Error in browser console:
image

Failed to load http://meselok.hu/graphql: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled

Packet capture shows that Apollo sends the query:

{"operationName":null,"variables":{},"query":"{\n hello\n}\n"}
image

Server responds:

{"data":{"hello":"World"}}
image

Data does not load:
image

Full packet capture & filtered packet capture for the interesting packets attached in zip.
apollo_pcaps.zip

Tested server with a quick python script to make sure it is not the one with the issue:

import requests

headers = {'Origin': 'http://localhost',
           'Access-Control-Request-Method': 'POST',
           'Access-Control-Request-Headers': 'content-type'}

r = requests.options('http://meselok.hu/graphql', headers=headers)

for header, value in r.headers.items():
    print(f'Header: {header} --> {value}')

Outputs:

Header: Access-Control-Allow-Origin --> http://localhost
Header: Access-Control-Allow-Methods --> GET, POST, PUT, DELETE
Header: Access-Control-Allow-Headers --> content-type
Header: Access-Control-Max-Age --> 86400
Header: Content-Length --> 0
Header: Content-Type --> application/octet-stream
Header: Date --> Fri, 13 Apr 2018 14:50:01 GMT
Header: Server --> Python/3.6 aiohttp/3.1.2

As well the browser shows the headers being received:
image

How to reproduce the issue:
Simple hello-world example to test Apollo with Vue, following this tutorial:
https://www.howtographql.com/vue-apollo/2-queries-loading-links/

The graphql end point for meselok.hu (resolves to 10.0.2.101 in the packet capture) is reachable on http://kennyngston.no-ip.org:9999/graphql .. if needed, if not I'll turn it off.

Code in Vue:
graphql.js:

import gql from 'graphql-tag'

export const HELLO_WORLD = gql`
  query { hello }
`

Stuff.Vue:

<template>
  <div>
    <h4 v-if="loading">Loading...</h4>
    {{ stuff }}
  </div>
</template>
<script>
import { HELLO_WORLD } from '../constants/graphql'
export default {
  name: 'HelloStuff',
  data () {
    return {
      stuff: '',
      loading: 0
    }
  },
  apollo: {
    stuff: {
      query: HELLO_WORLD
    }
  }
}
</script>

App.Vue:

<template>
  <div id="app">
    <stuff></stuff>
  </div>
</template>

<script>
import Stuff from './components/Stuff'
export default {
  name: 'App',
  components: {Stuff}
}
</script>

main.js:

import Vue from 'vue'
import App from './App'

import { ApolloClient } from 'apollo-client'
import { HttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
import VueApollo from 'vue-apollo'

const httpLink = new HttpLink({
  uri: 'http://meselok.hu/graphql'
})

const apolloClient = new ApolloClient({
  link: httpLink,
  cache: new InMemoryCache(),
  connectToDevTools: true
})

Vue.config.productionTip = false

Vue.use(VueApollo)

const apolloProvider = new VueApollo({
  defaultClient: apolloClient,
  defaultOptions: {
    $loadingKey: 'loading'
  }
})

/* eslint-disable no-new */
new Vue({
  el: '#app',
  provide: apolloProvider.provide(),
  components: { App },
  template: '<App/>'
})

Version

Most helpful comment

@kennyngston what was the solution?

All 7 comments

@kennyngston what was the solution?

Tell us the solution please!

I "solved" it by passing an option:
const client = new ApolloClient({ uri: ..., fetchOptions: { mode: 'no-cors', }, });

If you're coming here because you're stuck in the Apollo Tutorial, this won't be enough to help you because the server they made you deploy with Zeit.now doesn't work (Zeit 2.0 has a new api).

Had a similar issue that was caused by my apollo-server-express configuration. I had added the cors package middleware which was being overridden by apollo-server-express's default cors feature. Had to disable it in the server's configuration with cors: false. Detailed explanation: https://github.com/expressjs/cors/issues/134#issuecomment-413543241

Had a similar issue that was caused by my apollo-server-express configuration. I had added the cors package middleware which was being overridden by apollo-server-express's default cors feature. Had to disable it in the server's configuration with cors: false. Detailed explanation: expressjs/cors#134 (comment)

This was really helpful. You can also specify the origin as opposed to turning the cors off

server.applyMiddleware({ app, cors: { origin: process.env.CLIENT_URL } });

Had a similar issue that was caused by my apollo-server-express configuration. I had added the cors package middleware which was being overridden by apollo-server-express's default cors feature. Had to disable it in the server's configuration with cors: false. Detailed explanation: expressjs/cors#134 (comment)

Thank you so much! cors:false FTW!

Was this page helpful?
0 / 5 - 0 ratings