Accept prefixed resource header in GraphQL ETag router
What does this MR do and why?
The graphql_etag_*_path helpers in Routing::GraphqlHelper return the full ETag cache key, for example /api/graphql:pipelines/id/123. Callers that use these helpers send that value in X-GITLAB-GRAPHQL-RESOURCE-ETAG. Gitlab::EtagCaching::Router::Graphql matches the header against anchored regexps that expect only the resource part (pipelines/id/123). As a result, no GraphQL ETag route matches a prefixed header.
The request then falls through to Rack::ETag. It still returns 304 Not Modified, but only after the resolvers have run. This affects pipelines_graph, project_pipelines, ci_editor and on_demand_scans. Reproduced on GitLab.com with pipeline 2830717842: the bare header returns X-Gitlab-From-Cache: true, and the prefixed header does not.
This MR strips the "#{graphql_api_path}:" prefix from the header in Router::Graphql, before route matching and before cache key construction. The bare form still matches. The cache key is unchanged (/api/graphql:pipelines/id/123), and it is the key that Ci::ExpirePipelineCacheService already touches. No frontend or regexp changes.
References
Closes #628512 (closed)
How to set up and validate locally
-
Pick a finished pipeline. Note its database id (
PIPELINE_ID), itsiid, and the project full path. -
Request the pipeline through GraphQL with the prefixed header:
curl -sD - -o /dev/null --get "http://gdk.test:3000/api/graphql" \ -H "PRIVATE-TOKEN: $TOKEN" \ -H "X-GITLAB-GRAPHQL-RESOURCE-ETAG: /api/graphql:pipelines/id/$PIPELINE_ID" \ --data-urlencode 'query=query($p: ID!, $i: ID!) { project(fullPath: $p) { pipeline(iid: $i) { id status } } }' \ --data-urlencode "variables={\"p\":\"$PROJECT\",\"i\":\"$IID\"}" -
Repeat with
-H "If-None-Match: <ETag from step 2>".- Before:
304withoutX-Gitlab-From-Cache, produced byRack::ETagafter the resolvers ran. - After:
304withX-Gitlab-From-Cache: true, produced by the ETag middleware before the app is called.
- Before:
-
Repeat with the bare header
pipelines/id/$PIPELINE_ID:X-Gitlab-From-Cache: truebefore and after.
Specs: bundle exec rspec spec/lib/gitlab/etag_caching/router/graphql_spec.rb spec/lib/gitlab/etag_caching/middleware_spec.rb.
MR acceptance checklist
Evaluated against the MR acceptance checklist. Backend only, no user-visible change, no schema or database change.