diff --git a/lib/api/api.js b/lib/api/api.js index 2a7a876371..7e59581270 100644 --- a/lib/api/api.js +++ b/lib/api/api.js @@ -387,10 +387,18 @@ const api = { rateLimited: true, rateLimitSource: cachedConfig.source, }); + // Add to server access log + if (request.serverAccessLog) { + /* eslint-disable no-param-reassign */ + request.serverAccessLog.rateLimited = true; + request.serverAccessLog.rateLimitSource = cachedConfig.source; + /* eslint-enable no-param-reassign */ + } return callback(config.rateLimiting.error); } // Set tracker - rate limiting already applied + // eslint-disable-next-line no-param-reassign request.rateLimitAlreadyChecked = true; // Continue with normal flow diff --git a/lib/metadata/metadataUtils.js b/lib/metadata/metadataUtils.js index 5c1f82b1b8..e9055f3894 100644 --- a/lib/metadata/metadataUtils.js +++ b/lib/metadata/metadataUtils.js @@ -257,8 +257,14 @@ function checkRateLimitIfNeeded(bucket, bucketName, request, log, callback) { rateLimited: true, rateLimitSource: rateLimitConfig.source, }); - // eslint-disable-next-line no-param-reassign + // Add to server access log + /* eslint-disable no-param-reassign */ + if (request.serverAccessLog) { + request.serverAccessLog.rateLimited = true; + request.serverAccessLog.rateLimitSource = rateLimitConfig.source; + } request.rateLimitAlreadyChecked = true; + /* eslint-enable no-param-reassign */ return callback(config.rateLimiting.error); } diff --git a/lib/utilities/serverAccessLogger.js b/lib/utilities/serverAccessLogger.js index 448e3a6195..3832e5ecca 100644 --- a/lib/utilities/serverAccessLogger.js +++ b/lib/utilities/serverAccessLogger.js @@ -463,6 +463,10 @@ function logServerAccess(req, res) { loggingTargetPrefix: params.loggingEnabled ? params.loggingEnabled.TargetPrefix : null, awsAccessKeyID: authInfo ? authInfo.getAccessKey() : null, raftSessionID: params.raftSessionID === undefined ? null : params.raftSessionID, + + // Rate Limiting fields (only present when rate limited) + rateLimited: params.rateLimited, + rateLimitSource: params.rateLimitSource, })}\n`); } diff --git a/package.json b/package.json index 4137bf3ac8..f5ecef2c8e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@zenko/cloudserver", - "version": "9.2.6", + "version": "9.2.7", "description": "Zenko CloudServer, an open-source Node.js implementation of a server handling the Amazon S3 protocol", "main": "index.js", "engines": { diff --git a/schema/server_access_log.schema.json b/schema/server_access_log.schema.json index a191437b79..b7e803eb24 100644 --- a/schema/server_access_log.schema.json +++ b/schema/server_access_log.schema.json @@ -195,6 +195,15 @@ "raftSessionID": { "description": "Raft session ID.", "type": ["integer", "null"] + }, + "rateLimited": { + "description": "True when the request was rate-limited. This field is emitted only when rate limiting occurs; if absent, the request was not rate-limited.", + "type": "boolean" + }, + "rateLimitSource": { + "description": "Source of the rate-limit configuration that applied to this request. 'global' means the global default bucket rate limit; 'bucket' means a bucket-specific override. This field is only emitted when the request was rate-limited.", + "type": "string", + "enum": ["global", "bucket"] } }, "additionalProperties": false,