Hi there,
I am learning graphql and relay. here is an error that I came across:
Fetch API cannot load http://localhost:8080/graphql. 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:3000' is therefore not allowed access. The response had HTTP status code 400. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Any suggestion would be very appreciated.
Here is the main go function:
func main() {
http.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write(page)
}))
http.Handle("/graphql", &relay.Handler{Schema: schema})
log.Fatal(http.ListenAndServe(":8080", nil))
}
If you want to allow people to request your graphql api from another domain (from a browser) then you'll need to add the Access-Control-Allow-Origin header to your graphql handler.
One way you could do this is with a "middleware" approach.
func CorsMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// allow cross domain AJAX requests
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
next.ServeHTTP(w,r)
})
}
so that you could wrap your relay.Handler with this middleware:
http.Handle("/graphql", CorsMiddleware(&relay.Handler{Schema: schema}))
Please be aware that allowing Cross-Origin requests to your api could be a security vulnerability.
https://en.wikipedia.org/wiki/Cross-origin_resource_sharing serves as a good reference on the topic of CORS.
Thank you so much. Please close this issue.
if you are using apollo-boost in a react app, your browser might do a CORS preflight request, which is an OPTIONS request. the relay handler does not handle that properly, so I extended the CorsMiddleware function from https://github.com/graph-gophers/graphql-go/issues/74#issuecomment-289098639
to also respond to the preflight request:
func CorsMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST,OPTIONS")
if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}
next.ServeHTTP(w, r)
})
}
Most helpful comment
If you want to allow people to request your graphql api from another domain (from a browser) then you'll need to add the
Access-Control-Allow-Originheader to your graphql handler.One way you could do this is with a "middleware" approach.
so that you could wrap your
relay.Handlerwith this middleware:Please be aware that allowing Cross-Origin requests to your api could be a security vulnerability.