diff --git a/src/DependencyInjection/M6WebGuzzleHttpExtension.php b/src/DependencyInjection/M6WebGuzzleHttpExtension.php index 5981689..ca1c13c 100644 --- a/src/DependencyInjection/M6WebGuzzleHttpExtension.php +++ b/src/DependencyInjection/M6WebGuzzleHttpExtension.php @@ -85,8 +85,14 @@ protected function loadClient(ContainerBuilder $container, string $clientId, arr $middlewareEventDispatcherDefinition->setArguments([new Reference('event_dispatcher'), $clientId]); $middlewareEventDispatcherDefinition->addMethodCall('push', [$handlerStackReference]); + $middlewareHostForwarderDefinition = new Definition('%m6web_guzzlehttp.middleware.hostforwarder.class%'); + $middlewareHostForwarderDefinition->setPublic(true); + $middlewareHostForwarderDefinition->setArguments([$config]); + $middlewareHostForwarderDefinition->addMethodCall('push', [$handlerStackReference]); + // we must assign middleware for build process $config['middleware'][] = $middlewareEventDispatcherDefinition; + $config['middleware'][] = $middlewareHostForwarderDefinition; $config['handler'] = $handlerStackReference; if ($config['redirect_handler'] == 'curl') { diff --git a/src/Middleware/HostForwarderMiddleware.php b/src/Middleware/HostForwarderMiddleware.php new file mode 100644 index 0000000..8f8196b --- /dev/null +++ b/src/Middleware/HostForwarderMiddleware.php @@ -0,0 +1,43 @@ +config = $config; + } + + /** + * Push function to middleware handler + */ + public function push(HandlerStack $stack): HandlerStack + { + $stack->push(function (callable $handler) { + return function ( + RequestInterface $request, + array $options + ) use ($handler) { + if (isset($this->config['headers'])) { + $lowercaseHeaders = array_change_key_case($this->config['headers']); + if (isset($lowercaseHeaders['host'])) { + $request = $request->withHeader('host', $lowercaseHeaders['host']); + } + } + + return $handler($request, $options); + }; + }, 'hostForwarder_forward'); + + return $stack; + } +} diff --git a/src/Resources/config/services.yml b/src/Resources/config/services.yml index 4bafbfe..34b736a 100644 --- a/src/Resources/config/services.yml +++ b/src/Resources/config/services.yml @@ -8,6 +8,7 @@ parameters: m6web_guzzlehttp.guzzle.client.class: 'GuzzleHttp\Client' m6web_guzzlehttp.middleware.eventdispatcher.class: 'M6Web\Bundle\GuzzleHttpBundle\Middleware\EventDispatcherMiddleware' + m6web_guzzlehttp.middleware.hostforwarder.class: 'M6Web\Bundle\GuzzleHttpBundle\Middleware\HostForwarderMiddleware' services: diff --git a/tests/Units/Middleware/HostForwarderMiddleware.php b/tests/Units/Middleware/HostForwarderMiddleware.php new file mode 100644 index 0000000..01deede --- /dev/null +++ b/tests/Units/Middleware/HostForwarderMiddleware.php @@ -0,0 +1,80 @@ +getMockController()->push = function ($callable, $str) use (&$eventCallable) { + if ($str == 'hostForwarder_forward') { + $eventCallable = $callable; + } + }; + + // Response & request + $requestMock = new \mock\Psr\Http\Message\RequestInterface(); + + // Handler for end of event + $handlerEvent = function () { + return new \mock\GuzzleHttp\Promise(); + }; + + $this + ->if($hostForwarderMiddleware = new Base($configuration)) + ->then + ->object($hostForwarderMiddleware->push($handlerStackMock)) + ->isEqualTo($handlerStackMock) + ->mock($handlerStackMock) + ->call('push') + ->once() + ->object($callableHandler = $eventCallable($handlerEvent)) + ->isCallable() + ->variable($callableHandler($requestMock, [])) + ->isNotNull() + ->mock($requestMock) + ->call('withHeader') + ->exactly($expectedNumberOfCalls) + ->withArguments('host', 'my_configured_host') + ; + } + + protected function pushHostForwarderDataProvider(): array + { + return [ + [ + 'configuration' => [ + 'headers' => [ + 'host' => 'my_configured_host', + ], + ], + 'expectedNumberOfCalls' => 1, + ], + [ + 'configuration' => [ + 'headers' => [ + 'HOST' => 'my_configured_host', + ], + ], + 'expectedNumberOfCalls' => 1, + ], + [ + 'configuration' => [ + 'headers' => [], + ], + 'expectedNumberOfCalls' => 0, + ], + ]; + } +}