Skip to content

Commit

Permalink
Configurable header names and pass-through
Browse files Browse the repository at this point in the history
  • Loading branch information
floriankraemer authored Mar 28, 2024
2 parents 0714470 + 6705f56 commit cb43dbc
Show file tree
Hide file tree
Showing 15 changed files with 251 additions and 45 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/vendor/
/tools/
/bin/
/tmp/
/.phpunit.cache/
composer.lock
5 changes: 4 additions & 1 deletion .phive/phars.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive">
<phar name="grumphp" version="^2.5.0" installed="2.5.0" location="./tools/grumphp" copy="false"/>
<phar name="grumphp" version="^2.5.0" installed="2.5.0" location="./bin/grumphp" copy="false"/>
<phar name="phpmd" version="^2.15.0" installed="2.15.0" location="./bin/phpmd" copy="false"/>
<phar name="phpcs" version="^3.7.1" installed="3.7.1" location="./bin/phpcs" copy="false"/>
<phar name="phpstan" version="^1.9.2" installed="1.9.2" location="./bin/phpstan" copy="false"/>
</phive>
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,29 @@ This is a Symfony bridge for the framework agnostic [Correlation ID library](htt
* [The value of a correlation ID](https://blog.rapid7.com/2016/12/23/the-value-of-correlation-ids/)
* [Identity Correlation on Wikipedia](https://en.wikipedia.org/wiki/Identity_correlation)

## Installation

```sh
composer require phauthentic/correlation-id-symfony-bundle
```

## Configuration

You can configure three different settings to control the behavior:

* `response_header_name` - The name of the response header for the ID.
* `request_header_name` - The name of the request header for the ID.
* `pass_through` - If the ID from the request should be passed to the response enable this. This is useful if you are dealing with a microservice that is not exposed to the public but gets further actions delegated from the entry point and must retain the original ID.

`config/correlation_id.yaml`:

```yaml
correlation_id:
response_header_name: 'X-Correlation-ID'
request_header_name: 'X-Correlation-ID'
pass_through: false
```
## Copyright & License
Licensed under the [MIT license](LICENSE).
Expand Down
30 changes: 15 additions & 15 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions config/correlation_id.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
correlation_id:
response_header_name: 'X-Correlation-ID'
request_header_name: 'X-Correlation-ID'
5 changes: 5 additions & 0 deletions config/services.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
services:
Phauthentic\CorrelationIdBundle\EventSubscriber\CorrelationIdSubscriber:
arguments:
$config:
response_header_name: '%correlation_id.response_header_name%'
request_header_name: '%correlation_id.request_header_name%'
pass_through: '%correlation_id.pass_through%'
tags:
- { name: 'kernel.event_subscriber' }
45 changes: 45 additions & 0 deletions grumphp.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
grumphp:
ascii:
failed: resources/grumphp-grumpy.txt
succeeded: resources/grumphp-happy.txt
fixer:
enabled: true
fix_by_default: true
tasks:
phpstan:
autoload_file: ~
configuration: phpstan.neon
level: null
force_patterns: []
ignore_patterns: []
triggered_by: ['php']
memory_limit: "-1"
use_grumphp_paths: true
phpmd:
whitelist_patterns: []
exclude: []
report_format: text
ruleset: ['cleancode', 'codesize', 'naming', 'design', 'unusedcode']
triggered_by: ['php']
phpcs:
standard: []
severity: ~
error_severity: ~
warning_severity: ~
tab_width: ~
report: full
report_width: ~
whitelist_patterns: []
encoding: ~
ignore_patterns: []
sniffs: []
triggered_by: [php]
exclude: []
show_sniffs_error_path: true
phpunit:
config_file: phpunit.xml.dist
testsuite: ~
group: []
exclude_group: []
always_execute: false
order: null
36 changes: 18 additions & 18 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- https://phpunit.readthedocs.io/en/latest/configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" backupGlobals="false" colors="true" bootstrap="tests/bootstrap.php" cacheDirectory=".phpunit.cache">
<php>
<ini name="display_errors" value="1"/>
<ini name="error_reporting" value="-1"/>
<server name="APP_ENV" value="test" force="true"/>
<server name="SHELL_VERBOSITY" value="-1"/>
<server name="SYMFONY_PHPUNIT_REMOVE" value=""/>
<server name="SYMFONY_PHPUNIT_VERSION" value="10.5.15"/>
</php>
<testsuites>
<testsuite name="Project Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<coverage>
<include>
<directory suffix=".php">src</directory>
</include>
</coverage>
<php>
<ini name="display_errors" value="1"/>
<ini name="error_reporting" value="-1"/>
<server name="APP_ENV" value="test" force="true"/>
<server name="SHELL_VERBOSITY" value="-1"/>
<server name="SYMFONY_PHPUNIT_REMOVE" value=""/>
<server name="SYMFONY_PHPUNIT_VERSION" value="10.5.15"/>
</php>
<testsuites>
<testsuite name="Project Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<source>
<include>
<directory suffix=".php">src</directory>
</include>
</source>
</phpunit>
Empty file added resources/grumphp-grumpy.txt
Empty file.
2 changes: 2 additions & 0 deletions resources/grumphp-happy.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

All good!
32 changes: 32 additions & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace Phauthentic\CorrelationIdBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

class Configuration implements ConfigurationInterface
{
public function getConfigTreeBuilder(): TreeBuilder
{
$treeBuilder = new TreeBuilder('correlation_id');

/* @phpstan-ignore-next-line */
$treeBuilder->getRootNode()
->children()
->booleanNode('pass_through')
->defaultValue(false)
->end()
->scalarNode('response_header_name')
->defaultValue('X-Correlation-ID')
->end()
->scalarNode('request_header_name')
->defaultValue('X-Correlation-ID')
->end()
->end();

return $treeBuilder;
}
}
13 changes: 12 additions & 1 deletion src/DependencyInjection/CorrelationIdExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,18 @@ class CorrelationIdExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container): void
{
$yamlLoader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../../config'));
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);

$container->setParameter('correlation_id.request_header_name', $config['response_header_name']);
$container->setParameter('correlation_id.response_header_name', $config['response_header_name']);
$container->setParameter('correlation_id.pass_through', $config['pass_through']);

$yamlLoader = new Loader\YamlFileLoader(
$container,
new FileLocator(__DIR__ . '/../../config')
);

$yamlLoader->load('services.yaml');
}
}
52 changes: 46 additions & 6 deletions src/EventSubscriber/CorrelationIdSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Phauthentic\CorrelationIdBundle\EventSubscriber;

use InvalidArgumentException;
use Exception;
use Phauthentic\Infrastructure\Utils\CorrelationID;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
Expand All @@ -12,25 +14,63 @@

class CorrelationIdSubscriber implements EventSubscriberInterface
{
private string $header = 'X-Correlation-ID';
private string $requestHeaderName = 'X-Correlation-ID';
private string $responseHeaderName = 'X-Correlation-ID';
private bool $passthrough = false;

/**
* @param array<string, mixed> $config
* @return void
*/
public function __construct(array $config = [])
{
if (isset($config['request_header_name'])) {
$this->requestHeaderName = (string)$config['request_header_name'];
}

if (isset($config['response_header_name'])) {
$this->responseHeaderName = (string)$config['response_header_name'];
}

if (isset($config['pass_through'])) {
$this->passthrough = (bool)$config['pass_through'];
}
}

/**
* @SuppressWarnings(PHPMD.StaticAccess)
*
* @param RequestEvent $event
* @return void
*/
public function onKernelRequest(RequestEvent $event): void
{
$event->getRequest()->attributes->set($this->header, CorrelationID::toString());
$event->getRequest()->attributes->set($this->requestHeaderName, CorrelationID::toString());
}

/**
* @SuppressWarnings(PHPMD.StaticAccess)
*
* @param ResponseEvent $event
* @return void
* @throws InvalidArgumentException
* @throws Exception
*/
public function onKernelResponse(ResponseEvent $event): void
{
if ($event->getRequest()->headers->has($this->header)) {
if (
$this->passthrough
&& $event->getRequest()->headers->has($this->requestHeaderName)
) {
$event->getResponse()->headers->set(
$this->header,
$event->getRequest()->headers->get($this->header)
$this->responseHeaderName,
$event->getRequest()->headers->get($this->requestHeaderName)
);

return;
}

$event->getResponse()->headers->set($this->header, CorrelationID::toString());
$event->getResponse()->headers->set($this->responseHeaderName, CorrelationID::toString());
}

public static function getSubscribedEvents(): array
Expand Down
4 changes: 0 additions & 4 deletions src/Resources/config/correlation_id.yaml

This file was deleted.

Loading

0 comments on commit cb43dbc

Please sign in to comment.