Skip to content

Commit

Permalink
Policy: Add request/response content limit
Browse files Browse the repository at this point in the history
This policy check the content-caching header value and rejects if the
content is larger than  the value.

Fix THREESCALE-5244

Signed-off-by: Eloy Coto <eloy.coto@acalustra.com>
  • Loading branch information
eloycoto committed Oct 9, 2020
1 parent 1915775 commit 9f55b79
Show file tree
Hide file tree
Showing 7 changed files with 453 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Added new original_request_uri tag on Opentracing [PR #1223](https://github.com/3scale/APIcast/pull/1223) [THREESCALE-5669](https://issues.redhat.com/browse/THREESCALE-5669)
- Added a new metric when the `worker_process` starts [PR #1228](https://github.com/3scale/APIcast/pull/1228) [THREESCALE-5965](https://issues.redhat.com/browse/THREESCALE-5965)
- Caching policy disable default field [PR #1226](https://github.com/3scale/APIcast/pull/1226) [THREESCALE-1514](https://issues.redhat.com/browse/THREESCALE-1514)
- Add response/request content size limits [PR #1227](https://github.com/3scale/APIcast/pull/1227) [THREESCALE-5244](https://issues.redhat.com/browse/THREESCALE-5244)


### Fixed

Expand Down
21 changes: 21 additions & 0 deletions gateway/src/apicast/policy/limits/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Response/Request content limits policy

This policy enables response and request content limits based on the
Content-size header.


If the values are 0, means that no limit is applied.

## Examples:

Limit request content size to 1000 bytes.

```
{
"name": "apicast.policy.limits",
"configuration": {
"request": 1000,
"response": 0
}
},
```
37 changes: 37 additions & 0 deletions gateway/src/apicast/policy/limits/apicast-policy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"$schema": "http://apicast.io/policy-v1.1/schema#manifest#",
"name": "Response/Request content limits",
"summary": "Limit request or response base on the size of the content",
"description": [
"This policy add limits based on request or response content size."
],
"version": "builtin",
"configuration": {
"type": "object",
"required": [
"request",
"response"
],
"properties": {
"request": {
"type": "integer",
"title": "The request limit in bytes",
"default": 0,
"minimum": 0,
"examples": [
0
]
},
"response": {
"type": "integer",
"title": "The response limit in bytes",
"default": 0,
"minimum": 0,
"examples": [
0
]
}
},
"additionalProperties": true
}
}
1 change: 1 addition & 0 deletions gateway/src/apicast/policy/limits/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
return require("limits")
59 changes: 59 additions & 0 deletions gateway/src/apicast/policy/limits/limits.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
local _M = require('apicast.policy').new('Logging Policy', 'builtin')
local new = _M.new

local ngx_print = ngx.print
local ngx_exit = ngx.exit
local ngx_say = ngx.say

function _M.new(config)
local self = new(config)
self.request_limit = tonumber(config.request) or 0
self.response_limit = tonumber(config.response) or 0
return self
end

function _M:access()
if self.request_limit <= 0 then
return
end

-- No content-length header is present
if not ngx.var.content_length then
return
end

if tonumber(ngx.var.content_length) > self.request_limit then
ngx.log(ngx.INFO, "request rejected due to large body")
ngx.status = 413
ngx_say("Payload Too Large")
return ngx_exit(413)
end
end

function _M:header_filter(context)
if self.response_limit <= 0 then
return
end

-- Not content-length header in Upstream response, skip it
if not ngx.var.upstream_http_content_length then
return
end

if tonumber(ngx.var.upstream_http_content_length) > self.response_limit then
ngx.log(ngx.INFO, "Response rejected due to large body")
context.request_limited = true;
ngx.status = 413
return ngx_exit(413)
end
end

function _M:body_filter(context)
if context.request_limited then
ngx.arg[1] = "Payload Too Large"
ngx.arg[2] = true
return
end
end

return _M
32 changes: 32 additions & 0 deletions gateway/src/apicast/policy/limits/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Request/response size limits policy

This policy allows users to limit the size of the request and the response.

To get this policy working, the content-length header is mandatory on request
and response.

## Configuration

- Limit request to 100 bytes, response unlimited

```
{
"name": "apicast.policy.limits",
"configuration": {
"request": 100,
"response": 0
}
}
```

- Limit response to 100 bytes, request unlimited

```
{
"name": "apicast.policy.limits",
"configuration": {
"request": 0,
"response": 100
}
}
```
Loading

0 comments on commit 9f55b79

Please sign in to comment.