Skip to content

Add configurable Cache-Control header to command responses - #32

Merged
stixx merged 4 commits into
mainfrom
feature/cache-control-header
Jul 11, 2026
Merged

Add configurable Cache-Control header to command responses#32
stixx merged 4 commits into
mainfrom
feature/cache-control-header

Conversation

@stixx

@stixx stixx commented Jul 11, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds a cache_control configuration option (default: no-store) that sets Cache-Control on every command response, preventing browsers and intermediaries from caching sensitive API data.
  • Configurable per-app via stixx_openapi_command.cache_control; set to ~ (null) to disable.
  • Mirrors the approach used by API Platform (defaults.cache_headers).

Changed files

File Change
src/DependencyInjection/Configuration.php Added cache_control scalar node (default 'no-store')
src/DependencyInjection/StixxOpenApiCommandExtension.php Wires the parameter into the container
config/controller.php Passes $cacheControl arg to CommandController
src/Controller/CommandController.php Accepts ?string $cacheControl, sets Cache-Control header on responses
README.md Documents the new config option
tests/Unit/Controller/CommandControllerTest.php 3 new tests: default header, disabled (null), custom value
tests/Unit/DependencyInjection/ConfigurationTest.php Updated expected config arrays

Configuration

# Default — all command responses get Cache-Control: no-store
stixx_openapi_command: ~

# Disable
stixx_openapi_command:
    cache_control: ~

# Custom
stixx_openapi_command:
    cache_control: 'no-cache, private'

Test plan

  • Default: response includes no-store in Cache-Control
  • Disabled (null): controller does not override Symfony's computed default
  • Custom value: exact value lands on the response header
  • All 205 existing tests pass
  • PHPStan level max: 0 errors

Summary by CodeRabbit

  • New Features
    • Added configurable Cache-Control headers to command responses.
    • Responses default to no-store, with support for custom values or disabling the header.
  • Documentation
    • Updated the configuration example to include the new cache-control setting.
  • Tests
    • Added coverage for default, custom, and disabled cache-control behavior.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@stixx, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 53 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f0551cc3-846f-4c24-9f91-6adc2544aa35

📥 Commits

Reviewing files that changed from the base of the PR and between 5106143 and c92870a.

📒 Files selected for processing (10)
  • README.md
  • config/controller.php
  • src/Controller/CommandController.php
  • src/DependencyInjection/Configuration.php
  • src/DependencyInjection/StixxOpenApiCommandExtension.php
  • tests/Functional/Resources/config/cache_control_custom.php
  • tests/Functional/Resources/config/cache_control_disabled.php
  • tests/Functional/ScenarioTest.php
  • tests/Unit/Controller/CommandControllerTest.php
  • tests/Unit/DependencyInjection/ConfigurationTest.php

Walkthrough

Adds a configurable validation.cache_control setting with a no-store default. The value is passed through Symfony service wiring to CommandController, which conditionally sets the response header. Tests cover default, disabled, and custom values.

Changes

Cache-Control configuration and response handling

Layer / File(s) Summary
Cache-Control configuration and service wiring
src/DependencyInjection/Configuration.php, src/DependencyInjection/StixxOpenApiCommandExtension.php, config/controller.php, tests/Unit/DependencyInjection/ConfigurationTest.php, README.md
Defines validation.cache_control, exposes it as a container parameter, injects it into CommandController, updates configuration expectations, and documents the YAML setting.
Response header application and coverage
src/Controller/CommandController.php, tests/Unit/Controller/CommandControllerTest.php
Applies the configured Cache-Control value to responses unless disabled, with tests for the default, null, and custom values.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant BundleConfiguration
  participant StixxOpenApiCommandExtension
  participant CommandController
  participant Response
  BundleConfiguration->>StixxOpenApiCommandExtension: provide validation.cache_control
  StixxOpenApiCommandExtension->>CommandController: inject cache-control parameter
  CommandController->>Response: set Cache-Control header when enabled
Loading

Suggested labels: enhancement

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding a configurable Cache-Control header to command responses.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/cache-control-header

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

stixx added 2 commits July 11, 2026 13:09
Default every command response to Cache-Control: no-store to prevent
browsers and intermediaries from caching sensitive API data. The value
is configurable via stixx_openapi_command.cache_control and can be
set to null to disable.
@stixx
stixx force-pushed the feature/cache-control-header branch from 5e390ec to f342eae Compare July 11, 2026 11:09

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
tests/Unit/DependencyInjection/ConfigurationTest.php (1)

45-72: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add Configuration-level tests for custom and disabled cache_control values.

The controller tests cover default, custom, and null scenarios, but the Configuration tests only verify the default. Per path instructions, aim for 100% coverage of logical scenarios — add cases asserting that cache_control: ~ yields null and cache_control: 'no-cache, private' yields the custom string.

As per coding guidelines, "Aim for 100% coverage of logical scenarios" and "Use #[DataProvider] for multiple similar scenarios."

♻️ Suggested test additions
     public function testCustomConfig(): void
     {
         // ... existing code ...
     }

+    public function testCacheControlCanBeDisabled(): void
+    {
+        // Arrange
+        $configuration = new Configuration();
+        $processor = new Processor();
+        $customConfig = [
+            'cache_control' => null,
+        ];
+
+        // Act
+        $config = $processor->processConfiguration($configuration, [$customConfig]);
+
+        // Assert
+        self::assertNull($config['cache_control']);
+    }
+
+    public function testCacheControlAcceptsCustomValue(): void
+    {
+        // Arrange
+        $configuration = new Configuration();
+        $processor = new Processor();
+        $customConfig = [
+            'cache_control' => 'no-cache, private',
+        ];
+
+        // Act
+        $config = $processor->processConfiguration($configuration, [$customConfig]);
+
+        // Assert
+        self::assertSame('no-cache, private', $config['cache_control']);
+    }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/DependencyInjection/ConfigurationTest.php` around lines 45 - 72,
Add Configuration-level coverage for custom and null cache_control values
alongside testCustomConfig, using a #[DataProvider] for the similar scenarios.
Assert that 'no-cache, private' is preserved and a null (~) value resolves to
null, while retaining the existing defaults for other configuration keys.

Source: Path instructions

tests/Unit/Controller/CommandControllerTest.php (1)

154-245: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Reduce test setup duplication with a data provider or helper.

The three new cache-control tests share nearly identical arrange blocks (mock setup, envelope, bus, resolver, responder). Per path instructions, "Use #[DataProvider] for multiple similar scenarios." Extracting a shared factory or using #[DataProvider] would reduce maintenance burden and make adding future scenarios trivial.

As per coding guidelines, "Use #[DataProvider] for multiple similar scenarios."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Controller/CommandControllerTest.php` around lines 154 - 245,
Reduce duplication across testInvokeSetsDefaultCacheControlHeader,
testInvokeOmitsCacheControlHeaderWhenDisabled, and
testInvokeSetsCustomCacheControlHeader by extracting their shared command,
request, mock, envelope, bus, resolver, and responder setup into a reusable
helper or data provider. Prefer a PHPUnit #[DataProvider] to supply the
cacheControl value and expected assertion for each scenario, while preserving
the existing default, disabled, and custom header behaviors.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/Unit/Controller/CommandControllerTest.php`:
- Around line 212-213: Strengthen the disabled-cache-control assertion in the
relevant controller test by replacing the exact-value check with a substring
assertion that verifies the response Cache-Control header does not contain
“no-store”, including when Symfony adds other directives.

---

Nitpick comments:
In `@tests/Unit/Controller/CommandControllerTest.php`:
- Around line 154-245: Reduce duplication across
testInvokeSetsDefaultCacheControlHeader,
testInvokeOmitsCacheControlHeaderWhenDisabled, and
testInvokeSetsCustomCacheControlHeader by extracting their shared command,
request, mock, envelope, bus, resolver, and responder setup into a reusable
helper or data provider. Prefer a PHPUnit #[DataProvider] to supply the
cacheControl value and expected assertion for each scenario, while preserving
the existing default, disabled, and custom header behaviors.

In `@tests/Unit/DependencyInjection/ConfigurationTest.php`:
- Around line 45-72: Add Configuration-level coverage for custom and null
cache_control values alongside testCustomConfig, using a #[DataProvider] for the
similar scenarios. Assert that 'no-cache, private' is preserved and a null (~)
value resolves to null, while retaining the existing defaults for other
configuration keys.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 31e4b8ce-f2af-4770-84f7-5095c1414065

📥 Commits

Reviewing files that changed from the base of the PR and between 225ed40 and 5106143.

📒 Files selected for processing (7)
  • README.md
  • config/controller.php
  • src/Controller/CommandController.php
  • src/DependencyInjection/Configuration.php
  • src/DependencyInjection/StixxOpenApiCommandExtension.php
  • tests/Unit/Controller/CommandControllerTest.php
  • tests/Unit/DependencyInjection/ConfigurationTest.php

Comment thread tests/Unit/Controller/CommandControllerTest.php Outdated
stixx added 2 commits July 11, 2026 13:11
…ertion

Cover default, disabled, and custom cache_control values through the
full kernel request lifecycle. Replace assertNotSame with
assertStringNotContainsString in the disabled-cache unit test so it
holds even when Symfony appends extra directives.
@stixx
stixx merged commit 372afb9 into main Jul 11, 2026
6 checks passed
@stixx
stixx deleted the feature/cache-control-header branch July 11, 2026 11:15
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.

1 participant