gbox icon indicating copy to clipboard operation
gbox copied to clipboard

Batch queries

Open ArturHarutunyan opened this issue 2 years ago • 0 comments

now is not possible to do batch queries. I suggest just small changes to give that possibility. that functionality is actively used by Apollo for optimizing the query execution time. the suggested changes are attached

        // router.go line 95
        gqlRequests, err := h.unmarshalHTTPRequest(r)
	if err != nil {
		h.logger.Debug("can not unmarshal graphql request from http request", zap.Error(err))
		reporter.error = writeResponseErrors(err, w)

		return
	}
	n := r.Context().Value(nextHandlerCtxKey).(caddyhttp.Handler)

	for _, gqlRequest := range *gqlRequests {
		if err = h.validateGraphqlRequest(&gqlRequest); err != nil {
			reporter.error = writeResponseErrors(err, w)

			return
		}

		h.addMetricsBeginRequest(&gqlRequest)
		defer func(startedAt time.Time) {
			h.addMetricsEndRequest(&gqlRequest, time.Since(startedAt))
		}(time.Now())

		if h.Caching != nil {
			cachingRequest := newCachingRequest(r, h.schemaDocument, h.schema, &gqlRequest)
			reverse := caddyhttp.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
				return h.ReverseProxy.ServeHTTP(w, r, n)
			})

			if err = h.Caching.HandleRequest(w, cachingRequest, reverse); err != nil {
				reporter.error = writeResponseErrors(err, w)

				return
			}

			return
		}
	}

	reporter.error = h.ReverseProxy.ServeHTTP(w, r, n)
}

func (h *Handler) unmarshalHTTPRequest(r *http.Request) (*[]graphql.Request, error) {
	gqlRequests := make([]graphql.Request, 0)
	rawBody, _ := ioutil.ReadAll(r.Body)
	r.Body = ioutil.NopCloser(bytes.NewBuffer(rawBody))
	copyHTTPRequest, err := http.NewRequest(r.Method, r.URL.String(), ioutil.NopCloser(bytes.NewBuffer(rawBody))) // nolint:noctx
	if err != nil {
		return nil, err
	}

	requestBytes, err := ioutil.ReadAll(copyHTTPRequest.Body)
	if err != nil {
		return nil, err
	}

	if len(requestBytes) == 0 {
		return nil, graphql.ErrEmptyRequest
	}

	if err = json.Unmarshal(requestBytes, &gqlRequests); err != nil {
		var gqlRequest graphql.Request
		if e := json.Unmarshal(requestBytes, &gqlRequest); e != nil {
			return nil, e
		}
		gqlRequests = append(gqlRequests, gqlRequest)
	}
	for index, request := range gqlRequests {
		if err = normalizeGraphqlRequest(h.schema, &request); err != nil {
			return nil, err
		}
		gqlRequests[index] = request
	}

	return &gqlRequests, nil
}

ArturHarutunyan avatar Jan 14 '23 20:01 ArturHarutunyan