This component, made for Symfony, allows to set response headers defining them in configuration.
Open a command console, enter your project directory and execute:
$ composer require softspring/response-headers
Create a configuration file:
# config/packages/response_headers.yaml
parameters:
response_headers:
X-Frame-Options: "SAMEORIGIN"
X-Content-Type-Options: "nosniff"
services:
Softspring\Component\ResponseHeaders\EventListener\ResponseHeadersListener:
tags: ['kernel.event_subscriber']
arguments:
$headers: '%response_headers%'
You can set some conditions to match before applying response headers.
For this feature expression language component is required:
$ composer require symfony/expression-language
Then you must configure expression language service:
# config/packages/response_headers.yaml
parameters:
response_headers_global_conditions: []
response_headers:
...
services:
softspring.response_headers.expression_language:
class: Symfony\Component\ExpressionLanguage\ExpressionLanguage
arguments:
- '@?Psr\Cache\CacheItemPoolInterface'
Softspring\Component\ResponseHeaders\EventListener\ResponseHeadersListener:
tags: ['kernel.event_subscriber']
arguments:
$headers: '%response_headers%'
$expressionLanguage: '@softspring.response_headers.expression_language'
$globalConditions: '%response_headers_global_conditions%'
Now you can set a condition to be matched before applying a response header:
# config/packages/response_headers.yaml
parameters:
response_headers:
X-Frame-Options:
value: "SAMEORIGIN"
condition: "request.getPathInfo() matches '^/admin'"
Access-Control-Allow-Origin:
value: "*"
condition: "request.getPathInfo() matches '^/api'"
Also you can set global conditions to be matched for every headers:
# config/packages/response_headers.yaml
parameters:
response_headers_global_conditions:
- 'isMainRequest'
This global condition is recommended, to avoid setting headers for sub-requests, but it's not mandatory.
For the conditions, request and response objects are available. Also a isMainRequest variable is defined.
Check Symfony expression-language documentation.
There are several ways to define headers:
Single value header
# config/packages/response_headers.yaml
parameters:
response_headers:
X-Frame-Options: "SAMEORIGIN"
This code generates a x-frame-options: "SAMEORIGIN" header.
Multiple value header
Multiple value headers, will be merged to a single string delimited by semicolons
# config/packages/response_headers.yaml
parameters:
response_headers:
Feature-Policy:
- "geolocation 'self'"
- "vibrate 'none'"
This code generates a feature-policy: "geolocation 'self'; vibrate 'none'" header.
Value field
Also you can define the values into a value field:
# config/packages/response_headers.yaml
parameters:
response_headers:
X-Frame-Options:
value: "SAMEORIGIN"
Feature-Policy:
value:
- "geolocation 'self'"
- "vibrate 'none'"
This value field is mandatory if you want to set a condition or a replace behaviour.
Condition
As said before, headers could be restricted with conditions:
# config/packages/response_headers.yaml
parameters:
response_headers:
X-Frame-Options:
value: "SAMEORIGIN"
condition: "request.getHost() == 'api.mydomain.com"
Replace behaviour
Symfony response allows to define if a header must replace a previous defined header value.
By default, this replace behaviour is defined as true. But you can disable it using:
# config/packages/response_headers.yaml
parameters:
response_headers:
X-Frame-Options:
value: "SAMEORIGIN"
replace: false
This is an example witch defines common security headers:
# config/packages/response_headers.yaml
parameters:
response_headers_global_conditions:
- 'isMainRequest'
response_headers:
X-XSS-Protection:
- "1"
- "mode=block"
X-Frame-Options: "SAMEORIGIN"
X-Content-Type-Options: "nosniff"
Strict-Transport-Security:
- "max-age=31536000"
- "includeSubDomains"
Referrer-Policy: "same-origin"
Feature-Policy:
- "geolocation 'self'"
- "vibrate 'none'"
# ... include every feature the application uses.
Content-Security-Policy:
- "default-src 'none'"
- "img-src 'self'"
- "font-src 'self'"
- "manifest-src 'self'"
- "frame-src 'self'"
- "script-src 'self' 'unsafe-inline'"
- "style-src 'self' 'unsafe-inline'"
- "connect-src 'self'"
Check Content-Security-Policy to include every base urls with services you use. Also try to avoid unsafe-inline configuration, this is up to your project.
This bundle is under the MIT license. See the complete license in the bundle LICENSE file.