Nextcloud app that logs all outgoing HTTP requests made by Nextcloud's built-in HTTP client (OC\Http\Client\Client, Guzzle-based).
Note
The app has no built-in log rotation. Monitor log file sizes and rotate them with the system's logrotate daemon.
All settings are optional.
Explicit override for the log directory. Takes precedence over everything else.
'audit_http_client_logdir' => '/var/log/nextcloud/http_client',If this key is absent, the log directory is derived automatically:
- If
logfile_auditis set and points outsidedatadirectory: logs go into aclient/subdirectory next to the audit log. - Else if
logfileis set and points outsidedatadirectory: logs go into aclient/subdirectory next to the main log. - Otherwise:
<datadirectory>/admin_audit_http_client_logs/
The directory is created automatically on first use.
Controls which responses are logged. Default: 0.
| Value | Logs |
|---|---|
0 |
all requests |
1 |
HTTP 400+ only |
2 |
HTTP 500+ only |
Network errors (connection failures, DNS failures, etc.) are always logged regardless of this setting. Values outside the 0–2 range are clamped to the nearest valid level.
'audit_http_client_loglevel' => 1,Selects the log output format. Default: 'both'.
| Value | Output |
|---|---|
'json' |
<host>.json — one JSON object per line |
'plain' |
<host>.log — one plain-text line per request |
'both' |
both files |
Every entry starts with the request ID: the ID of the server request that triggered the outgoing call (the same ID as in nextcloud.log), followed by a random per-request suffix. The ID is also sent to the remote server as X-Nextcloud-ReqId header; a caller-supplied header is used unchanged.
Plain-text example:
gkAokgFCiaAKp30GwoTn-a3f9bc12 2026-05-05T14:23:01+00:00 GET https://example.com/feed HTTP/2 200 compressed=4821 decompressed=18944 ratio=0.25 encoding=br Hdrs=Host,Accept-Encoding,User-Agent "Nextcloud/32 ..."
'audit_http_client_format' => 'json',List of hostnames to exclude from logging. Requests to matching hosts are passed through without any log entry. Matching is case-insensitive. Wildcard prefix (*.example.com) is supported and also matches the bare domain (example.com). Default: [].
'audit_http_client_exclude_domains' => [
'apps.nextcloud.com',
'updates.nextcloud.com',
'*.googleapis.com',
],Additional header names whose values are logged as ***REMOVED SENSITIVE VALUE***. Matching is case-insensitive. Default: [].
The following headers are always redacted and cannot be un-redacted: Authorization, Proxy-Authorization, Cookie, Set-Cookie, X-Api-Key, X-Auth-Token.
'audit_http_client_redact_headers' => [
'X-Vendor-Secret',
],Additional query parameter names whose values are logged as ***REMOVED SENSITIVE VALUE*** in the uri field. Matching is case-insensitive; the parameter name and the rest of the URI stay unchanged. Default: [].
The following parameters are always redacted and cannot be un-redacted: access_token, api_key, apikey, auth, client_secret, key, password, secret, signature, token, X-Amz-Credential, X-Amz-Security-Token, X-Amz-Signature.
'audit_http_client_redact_params' => [
'session_key',
],Additional PCRE patterns whose matches in the URI path are logged as ***REMOVED SENSITIVE VALUE*** — for secrets that live in the path instead of the query string. Default: [].
The following pattern is always applied and cannot be removed: #(?<=/private-)[^/]+# — it covers Google's secret iCal addresses (…/ical/<user>/private-<hash>/basic.ics), where the hash is the only protection of the calendar. Only the hash is replaced; the private- marker stays readable.
'audit_http_client_redact_path_patterns' => [
'#(?<=/)sess-[0-9a-f]+#',
],Invalid patterns are skipped. To skip logging for a host entirely, use audit_http_client_exclude_domains instead.
This app is not yet in the App Store. It is built with ncmake. To build and install it from source — release tarball, make rsync or make cp — see the installation guide.
- Event-based injection: the middleware is injected via reflection into the private Guzzle client of
OC\Http\Client\Client, because core dispatches no event that exposes the handler stack. Nextcloud 35 added an optional$handlerparameter toIClientService::newClient(); a core-sideHttpClientHandlerStackReadyEvent(or a comparable extension point) would allow dropping the reflection entirely. Until then the server-matrix CI job also runs againstmasterand fails the moment core changes the private structure. - Built-in log rotation (size/age based) instead of relying on the system's logrotate.
Background and data-flow notes: Architecture & Roadmap.
- Author & Maintainer: [ernolf] Raphael Gradenwitz
AGPL-3.0-or-later