Skip to content

Commit

Permalink
fix(GraphQL): Pass on HTTP request headers for subscriptions (#7806) (#…
Browse files Browse the repository at this point in the history
…7807) (#8574)

Include headers from subscribe request and pass it along the downstream
for processing.

Co-authored-by: aman-bansal <[email protected]>

Co-authored-by: Abhimanyu Singh Gaur
<[email protected]>
(cherry picked from commit dbd5744)

Co-authored-by: aman bansal <[email protected]>
  • Loading branch information
all-seeing-code and aman-bansal authored Jan 5, 2023
1 parent 900a8b3 commit d3ed882
Showing 1 changed file with 25 additions and 8 deletions.
33 changes: 25 additions & 8 deletions graphql/admin/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand All @@ -175,15 +174,32 @@ 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,
Variables: variableValues,
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)
}
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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()

Expand Down

0 comments on commit d3ed882

Please sign in to comment.