{"id":23007260,"url":"https://github.com/garbetjie/http-request-logger","last_synced_at":"2025-08-14T03:31:34.263Z","repository":{"id":52231261,"uuid":"216597644","full_name":"garbetjie/http-request-logger","owner":"garbetjie","description":"Middleware for HTTP requests that logs incoming \u0026 outgoing requests \u0026 responses.","archived":false,"fork":false,"pushed_at":"2021-08-18T19:04:04.000Z","size":191,"stargazers_count":5,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-05-19T14:57:47.544Z","etag":null,"topics":["guzzle","laravel","logging","middleware","monolog-handler","psr-15","soap"],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/garbetjie.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-10-21T15:07:49.000Z","updated_at":"2024-09-11T08:22:35.000Z","dependencies_parsed_at":"2022-09-11T10:04:06.107Z","dependency_job_id":null,"html_url":"https://github.com/garbetjie/http-request-logger","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/garbetjie/http-request-logger","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garbetjie%2Fhttp-request-logger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garbetjie%2Fhttp-request-logger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garbetjie%2Fhttp-request-logger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garbetjie%2Fhttp-request-logger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/garbetjie","download_url":"https://codeload.github.com/garbetjie/http-request-logger/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garbetjie%2Fhttp-request-logger/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270357727,"owners_count":24570419,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-14T02:00:10.309Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["guzzle","laravel","logging","middleware","monolog-handler","psr-15","soap"],"created_at":"2024-12-15T08:15:03.267Z","updated_at":"2025-08-14T03:31:33.953Z","avatar_url":"https://github.com/garbetjie.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"HTTP Request Logger\n--------------------\n\nAn HTTP request logging library that makes it simple to  easy to implement the logging of all HTTP requests \u0026 responses.\n\nWorks with [Laravel](https://laravel.com/docs), [Guzzle](http://docs.guzzlephp.org) and PHP's `SoapServer` and\n`SoapClient` classes.\n\n![](https://github.com/garbetjie/http-request-logger/actions/workflows/tests.yaml/badge.svg)\n\n# Table of contents\n\n* [Introduction](#introduction)\n* [Installation](#installation)\n* [Usage](#usage)\n    * [Incoming requests: Laravel](#incoming-requests-in-laravel)\n    * [Incoming requests: PSR-15 compliant frameworks](#incoming-requests-in-psr-15-compliant-frameworks)\n    * [Incoming requests: SOAP server](#incoming-soap-requests)\n    * [Outgoing requests: Laravel](#outgoing-requests-in-laravel)\n    * [Outgoing requests: Guzzle](#outgoing-requests-through-guzzle)\n    * [Outgoing requests: SOAP](#outgoing-soap-requests)\n* [Customisation](#customisation)\n    * [Context](#logging-context)\n    * [Request \u0026 response IDs](#id-generation)\n    * [Toggling logging](#toggling-logging)\n* [Changelog](#changelog)\n\n# Introduction\n\nIt is often quite useful to be able to see all requests \u0026 responses generated by your application - especially whilst\nin development. This library makes it trivial to log all incoming \u0026 outgoing requests \u0026 responses using\n[Monolog](https://packagist.org/packages/monolog/monolog).\n\nBy default, all requests \u0026 responses are logged at the `debug` log level. Sensible defaults for logging context are used,\nand headers that may contain sensitive values (such as `Cookie`, `Set-Cookie` and `Authorization`) have their values\nobfuscated. Each request \u0026 corresponding response are linked together through a unique ID. This allows you to interrogate\nyour logs to find the matching response for any given request.\n\n# Installation\n\n```shell\ncomposer require garbetjie/http-request-logger\n```\n\n# Usage\n\n## Incoming requests in Laravel\n\nEnabling request logging in Laravel is as simple as adding the middleware to the `$middleware` property on your\n`App\\Http\\Kernel` class. The example shown below is enough to ensure that all incoming requests \u0026 outgoing responses are\nlogged in Laravel:\n\n```php\n\u003c?php\n\nnamespace App\\Http;\n\nuse Illuminate\\Foundation\\Http\\Kernel as HttpKernel;\n\nclass Kernel extends HttpKernel\n{\n    // ...\n    protected $middleware = [\n        \\Garbetjie\\RequestLogging\\Http\\Middleware\\IncomingRequestLoggingMiddleware::class\n    ];\n    // ...\n} \n```\n\n\u003e **Take note:** You should add the request logging middleware to your application's global middleware stack, and\n\u003e determine when logging should take place in a service provider. When added to a middleware group, any uncaught\n\u003e exceptions thrown will prevent the request \u0026 response from being logged.\n\u003e \n\u003e See the [Toggle enabled/disabled](#toggle-enableddisabled) section for more information on this.\n\n## Incoming requests in PSR-15 compliant frameworks\n\nIf you are not using Laravel, but are making use of a framework that adheres to [PSR-15](https://www.php-fig.org/psr/psr-15),\nyou'll need to be a little more explicit in creating the middleware. The example below makes use of the Slim framework\nas an example:\n\n```php\n\u003c?php\n\n$app = Slim\\Factory\\AppFactory::create();\n$app-\u003eadd(\\Garbetjie\\RequestLogging\\Http\\Middleware\\IncomingRequestLoggingMiddleware::class);\n$app-\u003erun();\n```\n\n## Incoming SOAP requests\n\nLogging incoming SOAP requests is trivial. Instead of creating a new `\\SoapServer` instance, simply create a new instance\nof `\\Garbetjie\\RequestLogging\\Http\\SoapServer`. You can use this new instance exactly the same as you would with an\ninstance of `\\SoapServer`. Example shown below:\n\n```php\n\u003c?php\n\n$monolog = new Monolog\\Logger('logger');\n$logger = new Garbetjie\\RequestLogging\\Http\\Logger($monolog);\n$server = new Garbetjie\\RequestLogging\\Http\\SoapServer($logger, '/path/to/wsdl/or/null');\n$server-\u003esetObject(new stdClass());\n$server-\u003ehandle();;\n```\n\n## Outgoing requests in Laravel\n\nWHen using Laravel, you can simply type-hint either `GuzzleHttp\\ClientInterface` or `GuzzleHttp\\Client` wherever\nLaravel performs dependency injection. This package includes a service provider that automatically adds the middleware\nto a handler stack for you.\n\nAn example of using this type-hinting in a controller is shown below:\n\n```php\n\u003c?php\n\nnamespace App\\Http\\Controllers;\n\nclass MyController\n{\n    public function myAction(\\GuzzleHttp\\ClientInterface $client)\n    {\n        return $client-\u003erequest('GET', 'https://example.org')-\u003egetBody()-\u003egetContents();\n    }\n}\n```\n\n## Outgoing requests through Guzzle\n\nOutbound request logging happens through Guzzle middleware. In order to log outbound requests, simply add an instance\nof the `OutgoingRequestLoggingMiddleware` to your handler stack. Ideally, this should be the last middleware in your\nhandler stack in order to ensure the logged representation of the request is as accurate as possible.\n\n```php\n\u003c?php\n\n$monolog = new Monolog\\Logger('logger');\n$logger = new Garbetjie\\RequestLogging\\Http\\Logger($monolog);\n\n$stack = GuzzleHttp\\HandlerStack::create();\n$stack-\u003epush(new Garbetjie\\RequestLogging\\Http\\Middleware\\OutgoingRequestLoggingMiddleware($logger));\n$client = new GuzzleHttp\\Client(['stack' =\u003e $stack]);\n\n$client-\u003erequest('GET', 'https://example.org');\n```\n\n## Outgoing SOAP requests\n\nIn order to log outbound SOAP requests, simply create your Guzzle client as if you be logging any other outgoing HTTP\nrequest, and pass this client instance to a new instance of `Garbetjie\\RequestLogging\\Http\\SoapClient`. You can use\nthis SOAP client instance just as if you were making use of a native `SoapClient` instance:\n\n```php\n\u003c?php\n\n/* @var GuzzleHttp\\Client $guzzleClient */\n\n$soapClient = new Garbetjie\\RequestLogging\\Http\\SoapClient($guzzleClient, null, []);\n$soapResponse = $soapClient-\u003eMyCustomSoapMethod(['parameters']);\n```\n\n# Customisation\n\nAll aspects of the request \u0026 response logging are customisable. This includes the ID used to link a request \u0026 response\ntogether, the log message, as well as the context logged with each request \u0026 response.\n\n## Logging context\n\nBy default, incoming \u0026 outgoing requests generate a context with a similar structure to below.\nSensitive headers such as `Authorization` and `Cookie` have their values replaced with `***`:\n\n```php\n\u003c?php\n\n$context = [\n    'id' =\u003e '',  // string - contains the unique ID that links this request to its response.\n    'method' =\u003e '',  // string - upper-cased request method.\n    'url' =\u003e '',  // string - URL to which the request was sent.\n    'body_length' =\u003e 0,  // integer - size of the body sent.\n    'body' =\u003e base64_encode(''),  // string - base64-encoded body sent in the request.\n    'headers' =\u003e [],  // array\u003cstring, string\u003e - array of headers sent in the request. Names are normalized and lower-cased.\n];\n```\n\nThe context shown below indicates the default structure of the logging context for responses.\nAny `Set-Cookie` headers have their values stripped out and replaced with `***`.\n\n```php\n\u003c?php\n\n$context = [\n    'id' =\u003e '',  // string - contains the unique ID that links this response to the request that created it.\n    'duration' =\u003e 0.0,  // float - the duration of the request, in seconds (with fractional milliseconds).\n    'status_code' =\u003e 0,  // integer - the HTTP status code returned in the response.\n    'body_length' =\u003e 0,  // integer - the size of the body sent.\n    'body' =\u003e base64_encode(''),  // string - base64-encoded body sent in the response.\n    'headers' =\u003e [],  // array\u003cstring, string\u003e - array of headers sent in the response. Names are normalized and lower-cased.\n];\n```\n\nIt is quite simple to customise the logging context that is generated:\n\n```php\n\u003c?php\n\n$monolog = new Monolog\\Logger('name');\n$logger = new Garbetjie\\RequestLogging\\Http\\Logger($monolog);\n\n$logger-\u003econtext(\n    function (Garbetjie\\RequestLogging\\Http\\RequestEntry $entry): array {\n        // Return an array containing the context to log.\n        \n        return [];\n    },\n    function (Garbetjie\\RequestLogging\\Http\\ResponseEntry $entry): array {\n        // Return an array containing the context to log.\n    \n        return [];\n    }\n);\n```\n\nIf you'd like to simply extend off the context that is created by default, you can reuse the context extractors that are\nalready available:\n\n```php\n\u003c?php\n\n$monolog = new Monolog\\Logger('name');\n$logger = new Garbetjie\\RequestLogging\\Http\\Logger($monolog);\n\n$logger-\u003econtext(\n    function (Garbetjie\\RequestLogging\\Http\\RequestEntry $entry): array {\n        $context = (new Garbetjie\\RequestLogging\\Http\\Context\\RequestContext())($entry);\n        \n        $body = base64_decode($context['body']);\n        // Modify $body.\n        $context['body'] = base64_encode($body);\n        \n        return $context;\n    },\n    null\n);\n```\n\n## ID generation.\n\nBy default, the ID generation for linking requests \u0026 responses together makes use of `endyjasmi/cuid` to generate a full\nCUID.\n\nThis can be easily customised by providing a callable that simply returns a string containing the ID to use:\n\n```php\n\u003c?php\n\n$monolog = new Monolog\\Logger('name');\n$logger = new Garbetjie\\RequestLogging\\Http\\Logger($monolog);\n\n$logger-\u003eid(\n    function(): string {\n        return base64_encode(random_bytes(8));\n    }\n);\n```\n\n## Toggling logging\n\nBy default, all requests \u0026 responses are logged. However, it is possible to toggle whether a request or response should\nbe logged. Simply provide either a boolean value, or a callable that returns a boolean value indicating whether or not\nlogging should be enabled for the given request:\n\n```php\n\u003c?php\n\n$monolog = new Monolog\\Logger('name');\n$logger = new Garbetjie\\RequestLogging\\Http\\Logger($monolog);\n\nfunction shouldLog($request) {\n    if ($request instanceof Symfony\\Component\\HttpFoundation\\Request) {\n        return stripos($request-\u003egetUri(), 'https://example.org') === false;\n    } elseif ($request instanceof Psr\\Http\\Message\\RequestInterface) {\n        return stripos((string)$request-\u003egetUri(), 'https://example.org') === false;\n    } else {\n        return false;\n    }\n}\n\n$logger-\u003eenabled(\n    function(Garbetjie\\RequestLogging\\Http\\RequestEntry $entry): bool {  // Provide a callable that returns a boolean.\n        return shouldLog($entry-\u003erequest());\n    },\n    function(Garbetjie\\RequestLogging\\Http\\ResponseEntry $entry): bool {\n        return shouldLog($entry-\u003erequest());\n    }\n);\n\n// Alternatively:\n$logger-\u003eenabled(false, true);\n$logger-\u003eenabled(\n    new Garbetjie\\RequestLogging\\Http\\Context\\RequestContext(),\n    new Garbetjie\\RequestLogging\\Http\\Context\\ResponseContext()\n);\n```\n\n# Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md) for the full changelog.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgarbetjie%2Fhttp-request-logger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgarbetjie%2Fhttp-request-logger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgarbetjie%2Fhttp-request-logger/lists"}