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

  1. Pick a finished pipeline. Note its database id (PIPELINE_ID), its iid, and the project full path.

  2. 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\"}"
  3. Repeat with -H "If-None-Match: <ETag from step 2>".

    • Before: 304 without X-Gitlab-From-Cache, produced by Rack::ETag after the resolvers ran.
    • After: 304 with X-Gitlab-From-Cache: true, produced by the ETag middleware before the app is called.
  4. Repeat with the bare header pipelines/id/$PIPELINE_ID: X-Gitlab-From-Cache: true before 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.

Edited by Laura Montemayor

Merge request reports

Loading
Loading