Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(GraphQL): Pass on HTTP request headers for subscriptions (#7806) (#7807) #8574

Merged
merged 2 commits into from
Jan 5, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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