How can I log all requests and responses

1.8k Views Asked by At

Zend Expressive 2

I need all inputs and all outputs. My, pipeline.php

$app->pipe(\Zend\Stratigility\Middleware\ErrorHandler::class);
$app->pipe(\Zend\Expressive\Helper\ServerUrlMiddleware::class);
$app->pipe(\App\Middleware\LogRequestsMiddleware::class);
$app->pipeRoutingMiddleware();
$app->pipe(\Zend\Expressive\Middleware\ImplicitHeadMiddleware::class);
$app->pipe(\Zend\Expressive\Middleware\ImplicitOptionsMiddleware::class);
$app->pipe(\Zend\Expressive\Helper\UrlHelperMiddleware::class);
$app->pipeDispatchMiddleware();
$app->pipe(\App\Middleware\LogResponseMiddleware::class);
$app->pipe(\Zend\Expressive\Middleware\NotFoundHandler::class);

LogResponseMiddleware dont execute. If Error it need too.

2

There are 2 best solutions below

1
On

Correct order:

$app->pipe(\App\Middleware\LogResponseMiddleware::class);
$app->pipe(\Zend\Stratigility\Middleware\ErrorHandler::class);
$app->pipe(\Zend\Expressive\Helper\ServerUrlMiddleware::class);
$app->pipeRoutingMiddleware();
$app->pipe(\Zend\Expressive\Middleware\ImplicitHeadMiddleware::class);
$app->pipe(\Zend\Expressive\Middleware\ImplicitOptionsMiddleware::class);
$app->pipe(\Zend\Expressive\Helper\UrlHelperMiddleware::class);
$app->pipeDispatchMiddleware();
$app->pipe(\App\Middleware\LogRequestsMiddleware::class);
$app->pipe(\Zend\Expressive\Middleware\NotFoundHandler::class);

Details here: https://framework.zend.com/blog/2017-03-15-nested-middleware-in-expressive.html

0
On

You can log the request and response very easy, just create a middleware:

<?php
namespace Acme\Middleware;

use Psr\Log\LoggerInterface;
use Interop\Http\ServerMiddleware\DelegateInterface;
use Interop\Http\ServerMiddleware\MiddlewareInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

class LoggingMiddleware implements MiddlewareInterface
{
    /**
    * @var Psr\Log\LoggerInterface $logger
    */
    private $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    public function process(ServerRequestInterface $request, DelegateInterface $delegate) {
        // log the request
        $this->logger->log(Logger::INFO, 'Request', []);

        $response = $delegate->process($request);

        // log the response
        $this->logger->log(Logger::INFO, 'Response', []);

        return $response;
    }
}

In your factory you can use any PSR logger like monolog:

<?php
namespace Acme\Middleware;

use Interop\Container\ContainerInterface;
use Psr\Log\LoggerInterface;

class LoggingMiddlewareFactory
{
    public function __invoke(ContainerInterface $container)
    {
        $logger = $container->get(LoggerInterface::class);

        return new LoggingMiddleware($logger);
    }
}

Finally, the logging middleware must be added to the pipe exactly after ServerUrlMiddleware:

<?php
// config/pipeline.php
$app->pipe(ErrorHandler::class);
$app->pipe(ServerUrlMiddleware::class);

$app->pipe(LoggingMiddleware::class);

That's it.