From a1d7411d92abb2c6380abfd2b687bb9f36a712d3 Mon Sep 17 00:00:00 2001 From: aman bansal Date: Tue, 11 May 2021 21:32:31 +0530 Subject: [PATCH] fix(GraphQL): Pass on HTTP request headers for subscriptions (#7806) (#7807) * return as soon as error is encountered * fix comment * add more logs * fixing the http request header to be set in the subscription * fixing header type cast Co-authored-by: aman-bansal Co-authored-by: Abhimanyu Singh Gaur <12651351+abhimanyusinghgaur@users.noreply.github.com> (cherry picked from commit dbd57443992dd9f208f334095911069b3b3efa3f) --- graphql/admin/http.go | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/graphql/admin/http.go b/graphql/admin/http.go index 318ae7bd912..001d94001a3 100644 --- a/graphql/admin/http.go +++ b/graphql/admin/http.go @@ -158,10 +158,10 @@ func (gs *graphqlSubscription) Subscribe( variableValues map[string]interface{}) (payloads <-chan interface{}, err 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 { @@ -175,6 +175,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,7 +195,11 @@ func (gs *graphqlSubscription) Subscribe( Header: reqHeader, } namespace := x.ExtractNamespaceHTTP(&http.Request{Header: reqHeader}) - LazyLoadSchema(namespace) // first load the schema, then do anything else + 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 +237,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))