reproxy <other flags> --lua.enabled --lua.file=./script/one.lua --lua.file=./script/two.lua
local function before(request, response)
end
local function after(request, response)
end
return {
before = before,
after = after
}
You can return only before
, only after
, both or empty table
Do not use
after
hook if you not use it. It's make some work, for example, read response body and pass it to script. It may increase latency for large payloads.
Only before
hook example:
local function before(request, response)
-- your code
end
return {
before = before
}
request function | description |
---|---|
getRemoteAddr() | Returns remote host:port |
getURI() | Returns Returns request URI (without host) |
getMethod() | Returns HTTP method of request. Returns capitalized string |
addHeader(name, value) | Add request header. Name and Value must be a string |
removeHeader(name) | Remove request header. Name must be a string |
getHeader(name) | Get request header value. Name must be a string |
stop(code, content, headers) | Stop request execution and return code, content and headers |
response function | description |
---|---|
addHeader(name, value) | Add response header. Name and Value must be a string |
request function | description |
---|---|
getHeader(name) | Get request header value. Name must be a string |
response function | description |
---|---|
getBody() | Returns response body. Returns a string |
setBody(content) | Set response body. Content must be a string |
addHeader(name, value) | Add response header. Name and Value must be a string |
removeHeader(name) | Remove response header. Name must be a string |
getHeader(name) | Returns response header. Name must be a string |
getCode() | Returns response status code. Returns a number |
setCode(value) | Set response status code. Value must be a number |
Reproxy allows you to use some additional lua modules
Send message to reproxy log output
Module methods:
- debug(message)
- info(message)
- warn(message)
- error(message)
message
must be a string
Example
local log = require('log')
log.debug('message')
log.info('message')
log.warn('message')
log.error('message')
Send http requests
Module consts:
- MethodGet - returns
GET
- MethodHead - returns
HEAD
- MethodPost - returns
POST
- MethodPut - returns
PUT
- MethodPatch - returns
PATCH
- MethodDelete - returns
DELETE
- MethodConnect - returns
CONNECT
- MethodOptions - returns
OPTIONS
- MethodTrace - returns
TRACE
Module methods:
- get(url)
- post(url, contentType, body)
- request(method, url, options)
url
,contentType
,method
must be a string,options
must be a table
Request options fields (all fields is not required):
- timeout - request timeout in seconds, default 30s
- body - request body, default empty
- headers - a headers table with strings key/value pairs
Request options example:
local opts = {
timeout = 10,
body = '{"foo": 42}',
headers = {
['content-type'] = 'application/json',
['X-Authorization'] = 'some_token'
}
}
All methods return response
as first argument (a table) and string error as second argument, if error occurred
Response fields:
- code - status code, number
- body - response body, string
- headers - response headers, table
Response example:
{
code = 200,
body = 'foobar',
headers = {
'content-type' = { 'application/json' },
'custom' = { 'foo', 'bar' }
}
}
get
local http = require('http')
local res, err = http.get('https://domain.com/foo/bar')
if err ~= nil then
print('error', err)
return
end
-- res is a lua table, for example:
-- {
-- code = 200,
-- headers = {
-- 'Content-Type' = {'application/json'},
-- 'Custom' = {'foo', 'bar'},
-- ...
-- },
-- body = '{"foo":"bar"}'
-- }
post
local http = require('http')
local res, err = http.post('https://domain.com/foo/bar', 'application/json', '{"foo":"bar"}')
You can omit
contentType
andbody
(but not both)
local http = require('http')
local res, err = http.post('https://domain.com/foo/bar') -- correct
local res, err = http.post('https://domain.com/foo/bar', 'application/json') -- error, contentType is present, but body is omit
request
local http = require('http')
local res, err = http.request(http.methodPost, 'https://domain.com/foo/bar', {
headers = {
['content-type'] = 'application/json',
['X-Authorization'] = 'baz',
},
body = '{"foo":"bar"}',
timeout = 30,
})
local function before(request, response)
response.addHeader('X-Foo', 'bar')
end
return {
before = before
}
local function before(request, response)
if request.getMethod() == 'POST' then
request.stop(403, 'forbidden', {})
end
end
return {
before = before
}
local function after(request, response)
local body = string.gsub(response.getBody(), "{NAME}", 'Foobar', 1)
response.setBody(body)
end
return {
after = after
}
I run tests with vegeta
tool
echo "GET http://localhost:8000" | vegeta attack -duration=30s | tee results.bin | vegeta report
As backend payload I use index.html
313581 bytes
Before every test, I make single request curl http://localhost:8000
reproxy --listen=localhost:8000 --assets.location=./var/web --assets.cache=1m
Result:
Requests [total, rate, throughput] 1500, 50.03, 50.03
Duration [total, attack, wait] 29.981s, 29.98s, 513.542µs
Latencies [min, mean, 50, 90, 95, 99, max] 388.75µs, 1.172ms, 898.648µs, 1.993ms, 2.527ms, 4.427ms, 9.065ms
Bytes In [total, mean] 492000, 328.00
Bytes Out [total, mean] 0, 0.00
Success [ratio] 100.00%
Status Codes [code:count] 200:1500
Error Set:
reproxy --listen=localhost:8000 --assets.location=./var/web --assets.cache=1m --lua.enabled --lua.file=./web/lua/plugin1.lua
local function before(request, response)
response.addHeader('foo', 'bar')
end
return {
before = before,
}
Result:
Requests [total, rate, throughput] 1500, 50.03, 50.03
Duration [total, attack, wait] 29.981s, 29.98s, 1.074ms
Latencies [min, mean, 50, 90, 95, 99, max] 466.25µs, 1.961ms, 1.453ms, 3.555ms, 4.816ms, 7.849ms, 11.631ms
Bytes In [total, mean] 492000, 328.00
Bytes Out [total, mean] 0, 0.00
Success [ratio] 100.00%
Status Codes [code:count] 200:1500
Error Set:
Run with lua script, add response header in before
(add some bytes count to response) and replace substring in after
hook
reproxy --listen=localhost:8000 --assets.location=./var/web --assets.cache=1m --lua.enabled --lua.file=./web/lua/plugin1.lua
local function before(request, response)
response.addHeader('foo', 'bar')
end
local function after(request, response)
local body = string.gsub(response.getBody(), "{NAME}", 'Foobar', 1)
response.setBody(body)
end
return {
before = before,
after = after
}
Result:
Requests [total, rate, throughput] 1500, 50.03, 49.99
Duration [total, attack, wait] 30.003s, 29.98s, 23.021ms
Latencies [min, mean, 50, 90, 95, 99, max] 21.733ms, 23.245ms, 23.152ms, 24.008ms, 24.324ms, 25.697ms, 43.863ms
Bytes In [total, mean] 470371500, 313581.00
Bytes Out [total, mean] 0, 0.00
Success [ratio] 100.00%
Status Codes [code:count] 200:1500
Error Set: