diff options
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | config/app.php | 1 | ||||
-rw-r--r-- | config/config.default.php | 13 | ||||
-rw-r--r-- | src/Middleware/AddHeaders.php | 46 | ||||
-rw-r--r-- | tests/Unit/Middleware/AddHeadersTest.php | 43 |
5 files changed, 104 insertions, 1 deletions
@@ -45,7 +45,7 @@ To report bugs use [engelsystem/issues](https://github.com/engelsystem/engelsyst * Recommended: Directory Listing should be disabled. * There must a be MySQL database created with a user who has full rights to that database. * If necessary, create a ```config/config.php``` to override values from ```config/config.default.php```. - * To remove values from the `footer_items`, `available_themes`, `locales` or `tshirt_sizes` lists the config file has to be renamed. + * To remove values from the `footer_items`, `available_themes`, `locales`, `tshirt_sizes` or `headers` lists the config file has to be renamed. * To import the database the ```bin/migrate``` script has to be called. * In the browser, login with credentials ```admin```:```asdfasdf``` and change the password. diff --git a/config/app.php b/config/app.php index 77b1e874..7ba3509e 100644 --- a/config/app.php +++ b/config/app.php @@ -37,6 +37,7 @@ return [ // Changes of request/response parameters \Engelsystem\Middleware\SetLocale::class, + \Engelsystem\Middleware\AddHeaders::class, // The application code \Engelsystem\Middleware\ErrorHandler::class, diff --git a/config/config.default.php b/config/config.default.php index 879aa836..4ba6cdc1 100644 --- a/config/config.default.php +++ b/config/config.default.php @@ -150,4 +150,17 @@ return [ // IP addresses of reverse proxies that are trusted, can be an array or a comma separated list 'trusted_proxies' => env('TRUSTED_PROXIES', ['127.0.0.0/8', '::ffff:127.0.0.0/8', '::1/128']), + + // Add additional headers + 'add_headers' => (bool)env('ADD_HEADERS', true), + 'headers' => [ + 'X-Content-Type-Options' => 'nosniff', + 'X-Frame-Options' => 'sameorigin', + 'Referrer-Policy' => 'strict-origin-when-cross-origin', + 'Content-Security-Policy' => 'default-src \'self\' \'unsafe-inline\' \'unsafe-eval\'', + 'X-XSS-Protection' => '1; mode=block', + 'Feature-Policy' => 'autoplay \'none\'', + //'Strict-Transport-Security' => 'max-age=7776000', + //'Expect-CT' => 'max-age=7776000,enforce,report-uri="[uri]"', + ], ]; diff --git a/src/Middleware/AddHeaders.php b/src/Middleware/AddHeaders.php new file mode 100644 index 00000000..75383a90 --- /dev/null +++ b/src/Middleware/AddHeaders.php @@ -0,0 +1,46 @@ +<?php + +namespace Engelsystem\Middleware; + +use Engelsystem\Config\Config; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Server\MiddlewareInterface; +use Psr\Http\Server\RequestHandlerInterface; + +class AddHeaders implements MiddlewareInterface +{ + /** @var Config */ + protected $config; + + /** + * @param Config $config + */ + public function __construct(Config $config) + { + $this->config = $config; + } + + /** + * Process an incoming server request and setting the locale if required + * + * @param ServerRequestInterface $request + * @param RequestHandlerInterface $handler + * @return ResponseInterface + */ + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + $response = $handler->handle($request); + if (!$this->config->get('add_headers', true)) { + return $response; + } + + $headers = $this->config->get('headers', []); + + foreach ($headers as $name => $value) { + $response = $response->withAddedHeader($name, $value); + } + + return $response; + } +} diff --git a/tests/Unit/Middleware/AddHeadersTest.php b/tests/Unit/Middleware/AddHeadersTest.php new file mode 100644 index 00000000..1a1a9e71 --- /dev/null +++ b/tests/Unit/Middleware/AddHeadersTest.php @@ -0,0 +1,43 @@ +<?php + +namespace Engelsystem\Test\Unit\Middleware; + +use Engelsystem\Config\Config; +use Engelsystem\Http\Response; +use Engelsystem\Middleware\AddHeaders; +use PHPUnit\Framework\TestCase; +use PHPUnit_Framework_MockObject_MockObject as MockObject; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Server\RequestHandlerInterface; + +class AddHeadersTest extends TestCase +{ + /** + * @covers \Engelsystem\Middleware\AddHeaders::__construct + * @covers \Engelsystem\Middleware\AddHeaders::process + */ + public function testRegister() + { + /** @var ServerRequestInterface|MockObject $request */ + $request = $this->getMockForAbstractClass(ServerRequestInterface::class); + /** @var RequestHandlerInterface|MockObject $handler */ + $handler = $this->getMockForAbstractClass(RequestHandlerInterface::class); + $response = new Response(); + + $handler->expects($this->atLeastOnce()) + ->method('handle') + ->willReturn($response); + + $config = new Config(['add_headers' => false]); + + $middleware = new AddHeaders($config); + $this->assertEquals($response, $middleware->process($request, $handler)); + + $config->set('add_headers', true); + $config->set('headers', ['Foo-Header' => 'bar!']); + $return = $middleware->process($request, $handler); + + $this->assertNotEquals($response, $return); + $this->assertArraySubset(['Foo-Header' => ['bar!']], $return->getHeaders()); + } +} |