diff --git a/graphql/admin/http.go b/graphql/admin/http.go index 318ae7bd912..56fdf51e0cc 100644 --- a/graphql/admin/http.go +++ b/graphql/admin/http.go @@ -155,16 +155,15 @@ func (gs *graphqlSubscription) Subscribe( ctx context.Context, document, operationName string, - variableValues map[string]interface{}) (payloads <-chan interface{}, - err error) { + variableValues map[string]interface{}) (<-chan interface{}, error) { + reqHeader := http.Header{} // library (graphql-transport-ws) passes the headers which are part of the INIT payload to us // in the context. We are extracting those headers and passing them along. headerPayload, _ := ctx.Value("Header").(json.RawMessage) - reqHeader := http.Header{} if len(headerPayload) > 0 { headers := make(map[string]interface{}) - if err = json.Unmarshal(headerPayload, &headers); err != nil { + if err := json.Unmarshal(headerPayload, &headers); err != nil { return nil, err } @@ -175,6 +174,19 @@ func (gs *graphqlSubscription) Subscribe( } } + // Earlier the graphql-transport-ws library was ignoring the http headers in the request. + // The library was relying upon the information present in the request payload. This was + // blocker for the cloud team because the only control cloud has is over the HTTP headers. + // This fix ensures that we are setting the request headers if not provided in the payload. + httpHeaders, _ := ctx.Value("RequestHeader").(http.Header) + if len(httpHeaders) > 0 { + for k := range httpHeaders { + if len(strings.TrimSpace(reqHeader.Get(k))) == 0 { + reqHeader.Set(k, httpHeaders.Get(k)) + } + } + } + req := &schema.Request{ OperationName: operationName, Query: document, @@ -182,8 +194,12 @@ func (gs *graphqlSubscription) Subscribe( Header: reqHeader, } namespace := x.ExtractNamespaceHTTP(&http.Request{Header: reqHeader}) - LazyLoadSchema(namespace) // first load the schema, then do anything else - if err = gs.isValid(namespace); err != nil { + glog.Infof("namespace: %d. Got GraphQL request over websocket.", namespace) + // first load the schema, then do anything else + if err := LazyLoadSchema(namespace); err != nil { + return nil, err + } + if err := gs.isValid(namespace); err != nil { glog.Errorf("namespace: %d. graphqlSubscription not initialized: %s", namespace, err) return nil, errors.New(resolve.ErrInternal) } @@ -220,6 +236,7 @@ func (gh *graphqlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { defer span.End() ns, _ := strconv.ParseUint(r.Header.Get("resolver"), 10, 64) + glog.Infof("namespace: %d. Got GraphQL request over HTTP.", ns) if err := gh.isValid(ns); err != nil { glog.Errorf("namespace: %d. graphqlHandler not initialised: %s", ns, err) WriteErrorResponse(w, r, errors.New(resolve.ErrInternal)) @@ -382,8 +399,8 @@ func recoveryHandler(next http.Handler) http.Handler { // addDynamicHeaders adds any headers which are stored in the schema to the HTTP response. // At present, it handles following headers: -// * Access-Control-Allow-Headers -// * Access-Control-Allow-Origin +// - Access-Control-Allow-Headers +// - Access-Control-Allow-Origin func addDynamicHeaders(reqResolver *resolve.RequestResolver, origin string, w http.ResponseWriter) { schemaMeta := reqResolver.Schema().Meta()