Skip to content

Conversation

kamilkisiela
Copy link
Contributor

@kamilkisiela kamilkisiela commented Sep 19, 2025

Implements #318

This is the flow the PR introduces:

Config -> Compile -> Plan -> Apply

Config gets Compiled into a Plan that is Applied when needed (when request occurs).

In the compilation step, we validate the config and produce an immutable plan.
Regexes are combined and compiled to have the matching more efficient.
In this step, we also produce a list of header manipulation operations, in order of their definition in the config.

The response headers are collected after every subgraph response. We don't hold them forever, we only keep the relevant ones, by aggregating them response by response.


Release note

Advanced Header Management: You can now declaratively control HTTP headers for both subgraph requests and client responses. The new headers configuration allows for fine-grained manipulation, including:

  • Global and Per-Subgraph Rules: Define rules that apply to all subgraphs or specify overrides for individual ones.
  • Propagation Control: Forward headers with the ability to rename them or provide default values if they are not present.
  • Header Insertion with Expressions: Insert or overwrite headers with static values or dynamic values generated using VRL expressions.
  • Response Header Aggregation: Control how response headers from multiple subgraphs are merged using first, last, or append strategies.
  • Flexible Matching: Apply rules to headers based on exact names, regular expressions, and exclusion patterns.
    headers:
      all:
        request:
          - propagate:
              named: Authorization
      subgraphs:
        accounts:
          request:
            - propagate:
                named: x-tenant-id
                rename: x-acct-tenant
                default: "default-tenant"
        users:
          request:
            - insert:
                name: x-user-id
                expression: .request.headers."x-user-id" || "anonymous"
    

Copy link

github-actions bot commented Sep 19, 2025

k6-benchmark results

     ✓ response code was 200
     ✓ no graphql errors
     ✓ valid response structure

     █ setup

     checks.........................: 100.00% ✓ 237936      ✗ 0    
     data_received..................: 7.0 GB  231 MB/s
     data_sent......................: 93 MB   3.1 MB/s
     http_req_blocked...............: avg=2.84µs   min=691ns   med=1.74µs  max=5.96ms   p(90)=2.43µs  p(95)=2.76µs 
     http_req_connecting............: avg=267ns    min=0s      med=0s      max=1.4ms    p(90)=0s      p(95)=0s     
     http_req_duration..............: avg=18.41ms  min=2.02ms  med=17.46ms max=157.45ms p(90)=25.47ms p(95)=28.63ms
       { expected_response:true }...: avg=18.41ms  min=2.02ms  med=17.46ms max=157.45ms p(90)=25.47ms p(95)=28.63ms
     http_req_failed................: 0.00%   ✓ 0           ✗ 79332
     http_req_receiving.............: avg=149.28µs min=24.81µs med=39.29µs max=124.43ms p(90)=88.74µs p(95)=363.6µs
     http_req_sending...............: avg=23.93µs  min=5.35µs  med=10.35µs max=24.38ms  p(90)=15.71µs p(95)=29.36µs
     http_req_tls_handshaking.......: avg=0s       min=0s      med=0s      max=0s       p(90)=0s      p(95)=0s     
     http_req_waiting...............: avg=18.24ms  min=1.96ms  med=17.34ms max=71.98ms  p(90)=25.23ms p(95)=28.34ms
     http_reqs......................: 79332   2637.678428/s
     iteration_duration.............: avg=18.91ms  min=4.87ms  med=17.83ms max=335.45ms p(90)=25.93ms p(95)=29.15ms
     iterations.....................: 79312   2637.013455/s
     vus............................: 50      min=50        max=50 
     vus_max........................: 50      min=50        max=50 

Copy link

github-actions bot commented Sep 19, 2025

🐋 This PR was built and pushed to the following Docker images:

Image Names: ghcr.io/graphql-hive/router

Platforms: linux/amd64,linux/arm64

Image Tags: ghcr.io/graphql-hive/router:pr-438 ghcr.io/graphql-hive/router:sha-d2345c7

Docker metadata
{
"buildx.build.ref": "builder-240a2b89-08b2-406f-ba9b-0d456c189106/builder-240a2b89-08b2-406f-ba9b-0d456c1891060/koso7sni52haxum0ztsreji9l",
"containerimage.descriptor": {
  "mediaType": "application/vnd.oci.image.index.v1+json",
  "digest": "sha256:54c5ca3ed3ecb7826a643a61abb7f67c631f2694b91274b0c393b803ce323580",
  "size": 1609
},
"containerimage.digest": "sha256:54c5ca3ed3ecb7826a643a61abb7f67c631f2694b91274b0c393b803ce323580",
"image.name": "ghcr.io/graphql-hive/router:pr-438,ghcr.io/graphql-hive/router:sha-d2345c7"
}

@kamilkisiela kamilkisiela changed the title Add header configuration to the router config Add request and response headers manipulation Sep 23, 2025
@kamilkisiela

This comment was marked as outdated.

gemini-code-assist[bot]

This comment was marked as outdated.

@kamilkisiela

This comment was marked as outdated.

gemini-code-assist[bot]

This comment was marked as outdated.

@kamilkisiela kamilkisiela marked this pull request as ready for review September 24, 2025 13:50
@kamilkisiela kamilkisiela changed the title Add request and response headers manipulation feat(router): Advanced Header Management Sep 26, 2025
@kamilkisiela
Copy link
Contributor Author

/gemini review
/gemini summary

Copy link
Contributor

Hello @kamilkisiela, I received your commands /gemini review and /gemini summary. While I don't execute commands in that specific format, I understand you're looking for a review and a summary of this pull request. I've analyzed the changes and here's my feedback:

Overall Impression

This pull request introduces a significant and well-designed feature for advanced header management within the router. The approach of compiling header rules into an immutable plan and then applying them at runtime is robust and efficient. The use of VRL expressions for dynamic header values adds a powerful layer of flexibility, and the clear separation of concerns into dedicated modules for compilation, planning, and application is excellent for maintainability. The comprehensive documentation for the new configuration is also a major plus.

Review based on criteria:

Correctness

  • Header Management Flow: The PR correctly implements the "Config -> Compile -> Plan -> Apply" flow. Configuration is compiled into a HeaderRulesPlan during RouterSharedState initialization, and this plan is then used to modify headers for both outgoing subgraph requests and incoming client responses.
  • Error Handling: The RouterSharedState::new now returns a Result, allowing for proper error propagation if header rule compilation fails. New error types (HeaderRuleCompileError, HeaderRuleRuntimeError) are introduced, which is good practice.
  • Response Handling: The execute_plan function now returns PlanExecutionOutput which correctly encapsulates both the response body and headers, ensuring that header manipulation is integrated into the execution pipeline.
  • Deduplication Logic: The request_fingerprint function in dedupe.rs has been updated to consider all request headers (using BTreeMap for consistent hashing), which improves the correctness of request deduplication.

Efficiency

  • Pre-compilation: Header rules, including regexes and VRL expressions, are compiled once when the router state is initialized. This minimizes runtime overhead, as the compiled plan can be efficiently applied to each request/response.
  • Optimized Header Joining: The join_with_comma function in response.rs includes a capacity calculation for the Vec<u8>, which is a small but effective optimization for concatenating header values.
  • Targeted Application: Header rules are applied in a targeted manner (global then subgraph-specific), ensuring that only relevant rules are processed.

Maintainability

  • Modular Design: The new headers module is well-structured with submodules for compile, errors, expression, plan, request, response, and sanitizer. This promotes code organization and makes the feature easier to understand and extend.
  • Declarative Configuration: The YAML-based header configuration is declarative and intuitive, allowing users to define complex header manipulation rules without modifying router code.
  • VRL Expressions: The integration of VRL expressions provides a powerful and flexible mechanism for dynamic header values, reducing the need for custom code changes for common use cases.
  • Comprehensive Documentation: The docs/README.md file has been extensively updated with detailed explanations and examples of the new header configuration, which is crucial for user adoption and understanding.

Security

  • Header Sanitization: The sanitizer.rs module explicitly defines and enforces rules for HOP_BY_HOP_HEADERS (which are always stripped) and NEVER_JOIN_HEADERS (which are never comma-joined). This is a critical security measure to prevent header-related vulnerabilities and ensure correct HTTP behavior.

Summary

This pull request delivers a robust and highly configurable header management system. By introducing a clear

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants