Rename controller to nginx
This commit is contained in:
parent
41c34bd9e8
commit
b7dee6f95c
47 changed files with 24 additions and 24 deletions
67
controllers/nginx/lua/error_page.lua
Normal file
67
controllers/nginx/lua/error_page.lua
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
http = require "resty.http"
|
||||
def_backend = "upstream-default-backend"
|
||||
|
||||
local concat = table.concat
|
||||
local upstream = require "ngx.upstream"
|
||||
local get_servers = upstream.get_servers
|
||||
local get_upstreams = upstream.get_upstreams
|
||||
local random = math.random
|
||||
local us = get_upstreams()
|
||||
|
||||
function openURL(status)
|
||||
local httpc = http.new()
|
||||
|
||||
local random_backend = get_destination()
|
||||
local res, err = httpc:request_uri(random_backend, {
|
||||
path = "/",
|
||||
method = "GET",
|
||||
headers = {
|
||||
["X-Code"] = status or "404",
|
||||
["X-Format"] = ngx.var.httpAccept or "html",
|
||||
}
|
||||
})
|
||||
|
||||
if not res then
|
||||
ngx.log(ngx.ERR, err)
|
||||
ngx.exit(500)
|
||||
end
|
||||
|
||||
if ngx.var.http_cookie then
|
||||
ngx.header["Cookie"] = ngx.var.http_cookie
|
||||
end
|
||||
|
||||
ngx.status = tonumber(status)
|
||||
ngx.say(res.body)
|
||||
end
|
||||
|
||||
function get_destination()
|
||||
for _, u in ipairs(us) do
|
||||
if u == def_backend then
|
||||
local srvs, err = get_servers(u)
|
||||
local us_table = {}
|
||||
if not srvs then
|
||||
return "http://127.0.0.1:8181"
|
||||
else
|
||||
for _, srv in ipairs(srvs) do
|
||||
us_table[srv["name"]] = srv["weight"]
|
||||
end
|
||||
end
|
||||
local destination = random_weight(us_table)
|
||||
return "http://"..destination
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function random_weight(tbl)
|
||||
local total = 0
|
||||
for k, v in pairs(tbl) do
|
||||
total = total + v
|
||||
end
|
||||
local offset = random(0, total - 1)
|
||||
for k1, v1 in pairs(tbl) do
|
||||
if offset < v1 then
|
||||
return k1
|
||||
end
|
||||
offset = offset - v1
|
||||
end
|
||||
end
|
||||
78
controllers/nginx/lua/trie.lua
Normal file
78
controllers/nginx/lua/trie.lua
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
-- Simple trie for URLs
|
||||
|
||||
local _M = {}
|
||||
|
||||
local mt = {
|
||||
__index = _M
|
||||
}
|
||||
|
||||
-- http://lua-users.org/wiki/SplitJoin
|
||||
local strfind, tinsert, strsub = string.find, table.insert, string.sub
|
||||
function _M.strsplit(delimiter, text)
|
||||
local list = {}
|
||||
local pos = 1
|
||||
while 1 do
|
||||
local first, last = strfind(text, delimiter, pos)
|
||||
if first then -- found?
|
||||
tinsert(list, strsub(text, pos, first-1))
|
||||
pos = last+1
|
||||
else
|
||||
tinsert(list, strsub(text, pos))
|
||||
break
|
||||
end
|
||||
end
|
||||
return list
|
||||
end
|
||||
|
||||
local strsplit = _M.strsplit
|
||||
|
||||
function _M.new()
|
||||
local t = { }
|
||||
return setmetatable(t, mt)
|
||||
end
|
||||
|
||||
function _M.add(t, key, val)
|
||||
local parts = {}
|
||||
-- hack for just /
|
||||
if key == "/" then
|
||||
parts = { "" }
|
||||
else
|
||||
parts = strsplit("/", key)
|
||||
end
|
||||
|
||||
local l = t
|
||||
for i = 1, #parts do
|
||||
local p = parts[i]
|
||||
if not l[p] then
|
||||
l[p] = {}
|
||||
end
|
||||
l = l[p]
|
||||
end
|
||||
l.__value = val
|
||||
end
|
||||
|
||||
function _M.get(t, key)
|
||||
local parts = strsplit("/", key)
|
||||
|
||||
local l = t
|
||||
|
||||
-- this may be nil
|
||||
local val = t.__value
|
||||
for i = 1, #parts do
|
||||
local p = parts[i]
|
||||
if l[p] then
|
||||
l = l[p]
|
||||
local v = l.__value
|
||||
if v then
|
||||
val = v
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- may be nil
|
||||
return val
|
||||
end
|
||||
|
||||
return _M
|
||||
2
controllers/nginx/lua/vendor/lua-resty-http/.gitignore
vendored
Normal file
2
controllers/nginx/lua/vendor/lua-resty-http/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
t/servroot/
|
||||
t/error.log
|
||||
23
controllers/nginx/lua/vendor/lua-resty-http/LICENSE
vendored
Normal file
23
controllers/nginx/lua/vendor/lua-resty-http/LICENSE
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
Copyright (c) 2013, James Hurst
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
20
controllers/nginx/lua/vendor/lua-resty-http/Makefile
vendored
Normal file
20
controllers/nginx/lua/vendor/lua-resty-http/Makefile
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
OPENRESTY_PREFIX=/usr/local/openresty
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
LUA_INCLUDE_DIR ?= $(PREFIX)/include
|
||||
LUA_LIB_DIR ?= $(PREFIX)/lib/lua/$(LUA_VERSION)
|
||||
INSTALL ?= install
|
||||
TEST_FILE ?= t
|
||||
|
||||
.PHONY: all test install
|
||||
|
||||
all: ;
|
||||
|
||||
install: all
|
||||
$(INSTALL) -d $(DESTDIR)/$(LUA_LIB_DIR)/resty
|
||||
$(INSTALL) lib/resty/*.lua $(DESTDIR)/$(LUA_LIB_DIR)/resty/
|
||||
|
||||
test: all
|
||||
PATH=$(OPENRESTY_PREFIX)/nginx/sbin:$$PATH TEST_NGINX_NO_SHUFFLE=1 prove -I../test-nginx/lib -r $(TEST_FILE)
|
||||
util/lua-releng
|
||||
|
||||
423
controllers/nginx/lua/vendor/lua-resty-http/README.md
vendored
Normal file
423
controllers/nginx/lua/vendor/lua-resty-http/README.md
vendored
Normal file
|
|
@ -0,0 +1,423 @@
|
|||
# lua-resty-http
|
||||
|
||||
Lua HTTP client cosocket driver for [OpenResty](http://openresty.org/) / [ngx_lua](https://github.com/chaoslawful/lua-nginx-module).
|
||||
|
||||
# Status
|
||||
|
||||
Ready for testing. Probably production ready in most cases, though not yet proven in the wild. Please check the issues list and let me know if you have any problems / questions.
|
||||
|
||||
# Features
|
||||
|
||||
* HTTP 1.0 and 1.1
|
||||
* Streaming interface to reading bodies using coroutines, for predictable memory usage in Lua land.
|
||||
* Alternative simple interface for singleshot requests without manual connection step.
|
||||
* Headers treated case insensitively.
|
||||
* Chunked transfer encoding.
|
||||
* Keepalive.
|
||||
* Pipelining.
|
||||
* Trailers.
|
||||
|
||||
|
||||
# API
|
||||
|
||||
* [new](#name)
|
||||
* [connect](#connect)
|
||||
* [set_timeout](#set_timeout)
|
||||
* [ssl_handshake](#ssl_handshake)
|
||||
* [set_keepalive](#set_keepalive)
|
||||
* [get_reused_times](#get_reused_times)
|
||||
* [close](#close)
|
||||
* [request](#request)
|
||||
* [request_uri](#request_uri)
|
||||
* [request_pipeline](#request_pipeline)
|
||||
* [Response](#response)
|
||||
* [body_reader](#resbody_reader)
|
||||
* [read_body](#resread_body)
|
||||
* [read_trailes](#resread_trailers)
|
||||
* [Proxy](#proxy)
|
||||
* [proxy_request](#proxy_request)
|
||||
* [proxy_response](#proxy_response)
|
||||
* [Utility](#utility)
|
||||
* [parse_uri](#parse_uri)
|
||||
* [get_client_body_reader](#get_client_body_reader)
|
||||
|
||||
|
||||
## Synopsis
|
||||
|
||||
```` lua
|
||||
lua_package_path "/path/to/lua-resty-http/lib/?.lua;;";
|
||||
|
||||
server {
|
||||
|
||||
|
||||
location /simpleinterface {
|
||||
resolver 8.8.8.8; # use Google's open DNS server for an example
|
||||
|
||||
content_by_lua '
|
||||
|
||||
-- For simple singleshot requests, use the URI interface.
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
local res, err = httpc:request_uri("http://example.com/helloworld", {
|
||||
method = "POST",
|
||||
body = "a=1&b=2",
|
||||
headers = {
|
||||
["Content-Type"] = "application/x-www-form-urlencoded",
|
||||
}
|
||||
})
|
||||
|
||||
if not res then
|
||||
ngx.say("failed to request: ", err)
|
||||
return
|
||||
end
|
||||
|
||||
-- In this simple form, there is no manual connection step, so the body is read
|
||||
-- all in one go, including any trailers, and the connection closed or keptalive
|
||||
-- for you.
|
||||
|
||||
ngx.status = res.status
|
||||
|
||||
for k,v in pairs(res.headers) do
|
||||
--
|
||||
end
|
||||
|
||||
ngx.say(res.body)
|
||||
';
|
||||
}
|
||||
|
||||
|
||||
location /genericinterface {
|
||||
content_by_lua '
|
||||
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
|
||||
-- The generic form gives us more control. We must connect manually.
|
||||
httpc:set_timeout(500)
|
||||
httpc:connect("127.0.0.1", 80)
|
||||
|
||||
-- And request using a path, rather than a full URI.
|
||||
local res, err = httpc:request{
|
||||
path = "/helloworld",
|
||||
headers = {
|
||||
["Host"] = "example.com",
|
||||
},
|
||||
}
|
||||
|
||||
if not res then
|
||||
ngx.say("failed to request: ", err)
|
||||
return
|
||||
end
|
||||
|
||||
-- Now we can use the body_reader iterator, to stream the body according to our desired chunk size.
|
||||
local reader = res.body_reader
|
||||
|
||||
repeat
|
||||
local chunk, err = reader(8192)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
break
|
||||
end
|
||||
|
||||
if chunk then
|
||||
-- process
|
||||
end
|
||||
until not chunk
|
||||
|
||||
local ok, err = httpc:set_keepalive()
|
||||
if not ok then
|
||||
ngx.say("failed to set keepalive: ", err)
|
||||
return
|
||||
end
|
||||
';
|
||||
}
|
||||
}
|
||||
````
|
||||
|
||||
# Connection
|
||||
|
||||
## new
|
||||
|
||||
`syntax: httpc = http.new()`
|
||||
|
||||
Creates the http object. In case of failures, returns `nil` and a string describing the error.
|
||||
|
||||
## connect
|
||||
|
||||
`syntax: ok, err = httpc:connect(host, port, options_table?)`
|
||||
|
||||
`syntax: ok, err = httpc:connect("unix:/path/to/unix.sock", options_table?)`
|
||||
|
||||
Attempts to connect to the web server.
|
||||
|
||||
Before actually resolving the host name and connecting to the remote backend, this method will always look up the connection pool for matched idle connections created by previous calls of this method.
|
||||
|
||||
An optional Lua table can be specified as the last argument to this method to specify various connect options:
|
||||
|
||||
* `pool`
|
||||
: Specifies a custom name for the connection pool being used. If omitted, then the connection pool name will be generated from the string template `<host>:<port>` or `<unix-socket-path>`.
|
||||
|
||||
## set_timeout
|
||||
|
||||
`syntax: httpc:set_timeout(time)`
|
||||
|
||||
Sets the timeout (in ms) protection for subsequent operations, including the `connect` method.
|
||||
|
||||
## ssl_handshake
|
||||
|
||||
`syntax: session, err = httpc:ssl_handshake(session, host, verify)`
|
||||
|
||||
Performs an SSL handshake on the TCP connection, only availble in ngx_lua > v0.9.11
|
||||
|
||||
See docs for [ngx.socket.tcp](https://github.com/openresty/lua-nginx-module#ngxsockettcp) for details.
|
||||
|
||||
## set_keepalive
|
||||
|
||||
`syntax: ok, err = httpc:set_keepalive(max_idle_timeout, pool_size)`
|
||||
|
||||
Attempts to puts the current connection into the ngx_lua cosocket connection pool.
|
||||
|
||||
You can specify the max idle timeout (in ms) when the connection is in the pool and the maximal size of the pool every nginx worker process.
|
||||
|
||||
Only call this method in the place you would have called the `close` method instead. Calling this method will immediately turn the current http object into the `closed` state. Any subsequent operations other than `connect()` on the current objet will return the `closed` error.
|
||||
|
||||
Note that calling this instead of `close` is "safe" in that it will conditionally close depending on the type of request. Specifically, a `1.0` request without `Connection: Keep-Alive` will be closed, as will a `1.1` request with `Connection: Close`.
|
||||
|
||||
In case of success, returns `1`. In case of errors, returns `nil, err`. In the case where the conneciton is conditionally closed as described above, returns `2` and the error string `connection must be closed`.
|
||||
|
||||
## get_reused_times
|
||||
|
||||
`syntax: times, err = httpc:get_reused_times()`
|
||||
|
||||
This method returns the (successfully) reused times for the current connection. In case of error, it returns `nil` and a string describing the error.
|
||||
|
||||
If the current connection does not come from the built-in connection pool, then this method always returns `0`, that is, the connection has never been reused (yet). If the connection comes from the connection pool, then the return value is always non-zero. So this method can also be used to determine if the current connection comes from the pool.
|
||||
|
||||
## close
|
||||
|
||||
`syntax: ok, err = http:close()`
|
||||
|
||||
Closes the current connection and returns the status.
|
||||
|
||||
In case of success, returns `1`. In case of errors, returns `nil` with a string describing the error.
|
||||
|
||||
|
||||
# Requesting
|
||||
|
||||
## request
|
||||
|
||||
`syntax: res, err = httpc:request(params)`
|
||||
|
||||
Returns a `res` table or `nil` and an error message.
|
||||
|
||||
The `params` table accepts the following fields:
|
||||
|
||||
* `version` The HTTP version number, currently supporting 1.0 or 1.1.
|
||||
* `method` The HTTP method string.
|
||||
* `path` The path string.
|
||||
* `headers` A table of request headers.
|
||||
* `body` The request body as a string, or an iterator function (see [get_client_body_reader](#get_client_body_reader)).
|
||||
* `ssl_verify` Verify SSL cert matches hostname
|
||||
|
||||
When the request is successful, `res` will contain the following fields:
|
||||
|
||||
* `status` The status code.
|
||||
* `headers` A table of headers. Multiple headers with the same field name will be presented as a table of values.
|
||||
* `has_body` A boolean flag indicating if there is a body to be read.
|
||||
* `body_reader` An iterator function for reading the body in a streaming fashion.
|
||||
* `read_body` A method to read the entire body into a string.
|
||||
* `read_trailers` A method to merge any trailers underneath the headers, after reading the body.
|
||||
|
||||
## request_uri
|
||||
|
||||
`syntax: res, err = httpc:request_uri(uri, params)`
|
||||
|
||||
The simple interface. Options supplied in the `params` table are the same as in the generic interface, and will override components found in the uri itself.
|
||||
|
||||
In this mode, there is no need to connect manually first. The connection is made on your behalf, suiting cases where you simply need to grab a URI without too much hassle.
|
||||
|
||||
Additionally there is no ability to stream the response body in this mode. If the request is successful, `res` will contain the following fields:
|
||||
|
||||
* `status` The status code.
|
||||
* `headers` A table of headers.
|
||||
* `body` The response body as a string.
|
||||
|
||||
|
||||
## request_pipeline
|
||||
|
||||
`syntax: responses, err = httpc:request_pipeline(params)`
|
||||
|
||||
This method works as per the [request](#request) method above, but `params` is instead a table of param tables. Each request is sent in order, and `responses` is returned as a table of response handles. For example:
|
||||
|
||||
```lua
|
||||
local responses = httpc:request_pipeline{
|
||||
{
|
||||
path = "/b",
|
||||
},
|
||||
{
|
||||
path = "/c",
|
||||
},
|
||||
{
|
||||
path = "/d",
|
||||
}
|
||||
}
|
||||
|
||||
for i,r in ipairs(responses) do
|
||||
if r.status then
|
||||
ngx.say(r.status)
|
||||
ngx.say(r:read_body())
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
Due to the nature of pipelining, no responses are actually read until you attempt to use the response fields (status / headers etc). And since the responses are read off in order, you must read the entire body (and any trailers if you have them), before attempting to read the next response.
|
||||
|
||||
Note this doesn't preclude the use of the streaming response body reader. Responses can still be streamed, so long as the entire body is streamed before attempting to access the next response.
|
||||
|
||||
Be sure to test at least one field (such as status) before trying to use the others, in case a socket read error has occurred.
|
||||
|
||||
# Response
|
||||
|
||||
## res.body_reader
|
||||
|
||||
The `body_reader` iterator can be used to stream the response body in chunk sizes of your choosing, as follows:
|
||||
|
||||
````lua
|
||||
local reader = res.body_reader
|
||||
|
||||
repeat
|
||||
local chunk, err = reader(8192)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
break
|
||||
end
|
||||
|
||||
if chunk then
|
||||
-- process
|
||||
end
|
||||
until not chunk
|
||||
````
|
||||
|
||||
If the reader is called with no arguments, the behaviour depends on the type of connection. If the response is encoded as chunked, then the iterator will return the chunks as they arrive. If not, it will simply return the entire body.
|
||||
|
||||
Note that the size provided is actually a **maximum** size. So in the chunked transfer case, you may get chunks smaller than the size you ask, as a remainder of the actual HTTP chunks.
|
||||
|
||||
## res:read_body
|
||||
|
||||
`syntax: body, err = res:read_body()`
|
||||
|
||||
Reads the entire body into a local string.
|
||||
|
||||
|
||||
## res:read_trailers
|
||||
|
||||
`syntax: res:read_trailers()`
|
||||
|
||||
This merges any trailers underneath the `res.headers` table itself. Must be called after reading the body.
|
||||
|
||||
|
||||
# Proxy
|
||||
|
||||
There are two convenience methods for when one simply wishes to proxy the current request to the connected upstream, and safely send it downstream to the client, as a reverse proxy. A complete example:
|
||||
|
||||
```lua
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
|
||||
httpc:set_timeout(500)
|
||||
local ok, err = httpc:connect(HOST, PORT)
|
||||
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
httpc:set_timeout(2000)
|
||||
httpc:proxy_response(httpc:proxy_request())
|
||||
httpc:set_keepalive()
|
||||
```
|
||||
|
||||
|
||||
## proxy_request
|
||||
|
||||
`syntax: local res, err = httpc:proxy_request(request_body_chunk_size?)`
|
||||
|
||||
Performs a request using the current client request arguments, effectively proxying to the connected upstream. The request body will be read in a streaming fashion, according to `request_body_chunk_size` (see [documentation on the client body reader](#get_client_body_reader) below).
|
||||
|
||||
|
||||
## proxy_response
|
||||
|
||||
`syntax: httpc:proxy_response(res, chunksize?)`
|
||||
|
||||
Sets the current response based on the given `res`. Ensures that hop-by-hop headers are not sent downstream, and will read the response according to `chunksize` (see [documentation on the body reader](#resbody_reader) above).
|
||||
|
||||
|
||||
# Utility
|
||||
|
||||
## parse_uri
|
||||
|
||||
`syntax: local scheme, host, port, path = unpack(httpc:parse_uri(uri))`
|
||||
|
||||
This is a convenience function allowing one to more easily use the generic interface, when the input data is a URI.
|
||||
|
||||
|
||||
## get_client_body_reader
|
||||
|
||||
`syntax: reader, err = httpc:get_client_body_reader(chunksize?, sock?)`
|
||||
|
||||
Returns an iterator function which can be used to read the downstream client request body in a streaming fashion. You may also specify an optional default chunksize (default is `65536`), or an already established socket in
|
||||
place of the client request.
|
||||
|
||||
Example:
|
||||
|
||||
```lua
|
||||
local req_reader = httpc:get_client_body_reader()
|
||||
|
||||
repeat
|
||||
local chunk, err = req_reader(8192)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
break
|
||||
end
|
||||
|
||||
if chunk then
|
||||
-- process
|
||||
end
|
||||
until not chunk
|
||||
```
|
||||
|
||||
This iterator can also be used as the value for the body field in request params, allowing one to stream the request body into a proxied upstream request.
|
||||
|
||||
```lua
|
||||
local client_body_reader, err = httpc:get_client_body_reader()
|
||||
|
||||
local res, err = httpc:request{
|
||||
path = "/helloworld",
|
||||
body = client_body_reader,
|
||||
}
|
||||
```
|
||||
|
||||
If `sock` is specified,
|
||||
|
||||
# Author
|
||||
|
||||
James Hurst <james@pintsized.co.uk>
|
||||
|
||||
Originally started life based on https://github.com/bakins/lua-resty-http-simple. Cosocket docs and implementation borrowed from the other lua-resty-* cosocket modules.
|
||||
|
||||
|
||||
# Licence
|
||||
|
||||
This module is licensed under the 2-clause BSD license.
|
||||
|
||||
Copyright (c) 2013, James Hurst <james@pintsized.co.uk>
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
818
controllers/nginx/lua/vendor/lua-resty-http/lib/resty/http.lua
vendored
Normal file
818
controllers/nginx/lua/vendor/lua-resty-http/lib/resty/http.lua
vendored
Normal file
|
|
@ -0,0 +1,818 @@
|
|||
local http_headers = require "resty.http_headers"
|
||||
|
||||
local ngx_socket_tcp = ngx.socket.tcp
|
||||
local ngx_req = ngx.req
|
||||
local ngx_req_socket = ngx_req.socket
|
||||
local ngx_req_get_headers = ngx_req.get_headers
|
||||
local ngx_req_get_method = ngx_req.get_method
|
||||
local str_gmatch = string.gmatch
|
||||
local str_lower = string.lower
|
||||
local str_upper = string.upper
|
||||
local str_find = string.find
|
||||
local str_sub = string.sub
|
||||
local str_gsub = string.gsub
|
||||
local tbl_concat = table.concat
|
||||
local tbl_insert = table.insert
|
||||
local ngx_encode_args = ngx.encode_args
|
||||
local ngx_re_match = ngx.re.match
|
||||
local ngx_re_gsub = ngx.re.gsub
|
||||
local ngx_log = ngx.log
|
||||
local ngx_DEBUG = ngx.DEBUG
|
||||
local ngx_ERR = ngx.ERR
|
||||
local ngx_NOTICE = ngx.NOTICE
|
||||
local ngx_var = ngx.var
|
||||
local co_yield = coroutine.yield
|
||||
local co_create = coroutine.create
|
||||
local co_status = coroutine.status
|
||||
local co_resume = coroutine.resume
|
||||
|
||||
|
||||
-- http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1
|
||||
local HOP_BY_HOP_HEADERS = {
|
||||
["connection"] = true,
|
||||
["keep-alive"] = true,
|
||||
["proxy-authenticate"] = true,
|
||||
["proxy-authorization"] = true,
|
||||
["te"] = true,
|
||||
["trailers"] = true,
|
||||
["transfer-encoding"] = true,
|
||||
["upgrade"] = true,
|
||||
["content-length"] = true, -- Not strictly hop-by-hop, but Nginx will deal
|
||||
-- with this (may send chunked for example).
|
||||
}
|
||||
|
||||
|
||||
-- Reimplemented coroutine.wrap, returning "nil, err" if the coroutine cannot
|
||||
-- be resumed. This protects user code from inifite loops when doing things like
|
||||
-- repeat
|
||||
-- local chunk, err = res.body_reader()
|
||||
-- if chunk then -- <-- This could be a string msg in the core wrap function.
|
||||
-- ...
|
||||
-- end
|
||||
-- until not chunk
|
||||
local co_wrap = function(func)
|
||||
local co = co_create(func)
|
||||
if not co then
|
||||
return nil, "could not create coroutine"
|
||||
else
|
||||
return function(...)
|
||||
if co_status(co) == "suspended" then
|
||||
return select(2, co_resume(co, ...))
|
||||
else
|
||||
return nil, "can't resume a " .. co_status(co) .. " coroutine"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local _M = {
|
||||
_VERSION = '0.07',
|
||||
}
|
||||
_M._USER_AGENT = "lua-resty-http/" .. _M._VERSION .. " (Lua) ngx_lua/" .. ngx.config.ngx_lua_version
|
||||
|
||||
local mt = { __index = _M }
|
||||
|
||||
|
||||
local HTTP = {
|
||||
[1.0] = " HTTP/1.0\r\n",
|
||||
[1.1] = " HTTP/1.1\r\n",
|
||||
}
|
||||
|
||||
local DEFAULT_PARAMS = {
|
||||
method = "GET",
|
||||
path = "/",
|
||||
version = 1.1,
|
||||
}
|
||||
|
||||
|
||||
function _M.new(self)
|
||||
local sock, err = ngx_socket_tcp()
|
||||
if not sock then
|
||||
return nil, err
|
||||
end
|
||||
return setmetatable({ sock = sock, keepalive = true }, mt)
|
||||
end
|
||||
|
||||
|
||||
function _M.set_timeout(self, timeout)
|
||||
local sock = self.sock
|
||||
if not sock then
|
||||
return nil, "not initialized"
|
||||
end
|
||||
|
||||
return sock:settimeout(timeout)
|
||||
end
|
||||
|
||||
|
||||
function _M.ssl_handshake(self, ...)
|
||||
local sock = self.sock
|
||||
if not sock then
|
||||
return nil, "not initialized"
|
||||
end
|
||||
|
||||
return sock:sslhandshake(...)
|
||||
end
|
||||
|
||||
|
||||
function _M.connect(self, ...)
|
||||
local sock = self.sock
|
||||
if not sock then
|
||||
return nil, "not initialized"
|
||||
end
|
||||
|
||||
self.host = select(1, ...)
|
||||
self.keepalive = true
|
||||
|
||||
return sock:connect(...)
|
||||
end
|
||||
|
||||
|
||||
function _M.set_keepalive(self, ...)
|
||||
local sock = self.sock
|
||||
if not sock then
|
||||
return nil, "not initialized"
|
||||
end
|
||||
|
||||
if self.keepalive == true then
|
||||
return sock:setkeepalive(...)
|
||||
else
|
||||
-- The server said we must close the connection, so we cannot setkeepalive.
|
||||
-- If close() succeeds we return 2 instead of 1, to differentiate between
|
||||
-- a normal setkeepalive() failure and an intentional close().
|
||||
local res, err = sock:close()
|
||||
if res then
|
||||
return 2, "connection must be closed"
|
||||
else
|
||||
return res, err
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function _M.get_reused_times(self)
|
||||
local sock = self.sock
|
||||
if not sock then
|
||||
return nil, "not initialized"
|
||||
end
|
||||
|
||||
return sock:getreusedtimes()
|
||||
end
|
||||
|
||||
|
||||
function _M.close(self)
|
||||
local sock = self.sock
|
||||
if not sock then
|
||||
return nil, "not initialized"
|
||||
end
|
||||
|
||||
return sock:close()
|
||||
end
|
||||
|
||||
|
||||
local function _should_receive_body(method, code)
|
||||
if method == "HEAD" then return nil end
|
||||
if code == 204 or code == 304 then return nil end
|
||||
if code >= 100 and code < 200 then return nil end
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
function _M.parse_uri(self, uri)
|
||||
local m, err = ngx_re_match(uri, [[^(http[s]*)://([^:/]+)(?::(\d+))?(.*)]],
|
||||
"jo")
|
||||
|
||||
if not m then
|
||||
if err then
|
||||
return nil, "failed to match the uri: " .. err
|
||||
end
|
||||
|
||||
return nil, "bad uri"
|
||||
else
|
||||
if not m[3] then
|
||||
if m[1] == "https" then
|
||||
m[3] = 443
|
||||
else
|
||||
m[3] = 80
|
||||
end
|
||||
end
|
||||
if not m[4] or "" == m[4] then m[4] = "/" end
|
||||
return m, nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function _format_request(params)
|
||||
local version = params.version
|
||||
local headers = params.headers or {}
|
||||
|
||||
local query = params.query or ""
|
||||
if query then
|
||||
if type(query) == "table" then
|
||||
query = "?" .. ngx_encode_args(query)
|
||||
end
|
||||
end
|
||||
|
||||
-- Initialize request
|
||||
local req = {
|
||||
str_upper(params.method),
|
||||
" ",
|
||||
params.path,
|
||||
query,
|
||||
HTTP[version],
|
||||
-- Pre-allocate slots for minimum headers and carriage return.
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
}
|
||||
local c = 6 -- req table index it's faster to do this inline vs table.insert
|
||||
|
||||
-- Append headers
|
||||
for key, values in pairs(headers) do
|
||||
if type(values) ~= "table" then
|
||||
values = {values}
|
||||
end
|
||||
|
||||
key = tostring(key)
|
||||
for _, value in pairs(values) do
|
||||
req[c] = key .. ": " .. tostring(value) .. "\r\n"
|
||||
c = c + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Close headers
|
||||
req[c] = "\r\n"
|
||||
|
||||
return tbl_concat(req)
|
||||
end
|
||||
|
||||
|
||||
local function _receive_status(sock)
|
||||
local line, err = sock:receive("*l")
|
||||
if not line then
|
||||
return nil, nil, err
|
||||
end
|
||||
|
||||
return tonumber(str_sub(line, 10, 12)), tonumber(str_sub(line, 6, 8))
|
||||
end
|
||||
|
||||
|
||||
|
||||
local function _receive_headers(sock)
|
||||
local headers = http_headers.new()
|
||||
|
||||
repeat
|
||||
local line, err = sock:receive("*l")
|
||||
if not line then
|
||||
return nil, err
|
||||
end
|
||||
|
||||
for key, val in str_gmatch(line, "([^:%s]+):%s*(.+)") do
|
||||
if headers[key] then
|
||||
if type(headers[key]) ~= "table" then
|
||||
headers[key] = { headers[key] }
|
||||
end
|
||||
tbl_insert(headers[key], tostring(val))
|
||||
else
|
||||
headers[key] = tostring(val)
|
||||
end
|
||||
end
|
||||
until str_find(line, "^%s*$")
|
||||
|
||||
return headers, nil
|
||||
end
|
||||
|
||||
|
||||
local function _chunked_body_reader(sock, default_chunk_size)
|
||||
return co_wrap(function(max_chunk_size)
|
||||
local max_chunk_size = max_chunk_size or default_chunk_size
|
||||
local remaining = 0
|
||||
local length
|
||||
|
||||
repeat
|
||||
-- If we still have data on this chunk
|
||||
if max_chunk_size and remaining > 0 then
|
||||
|
||||
if remaining > max_chunk_size then
|
||||
-- Consume up to max_chunk_size
|
||||
length = max_chunk_size
|
||||
remaining = remaining - max_chunk_size
|
||||
else
|
||||
-- Consume all remaining
|
||||
length = remaining
|
||||
remaining = 0
|
||||
end
|
||||
else -- This is a fresh chunk
|
||||
|
||||
-- Receive the chunk size
|
||||
local str, err = sock:receive("*l")
|
||||
if not str then
|
||||
co_yield(nil, err)
|
||||
end
|
||||
|
||||
length = tonumber(str, 16)
|
||||
|
||||
if not length then
|
||||
co_yield(nil, "unable to read chunksize")
|
||||
end
|
||||
|
||||
if max_chunk_size and length > max_chunk_size then
|
||||
-- Consume up to max_chunk_size
|
||||
remaining = length - max_chunk_size
|
||||
length = max_chunk_size
|
||||
end
|
||||
end
|
||||
|
||||
if length > 0 then
|
||||
local str, err = sock:receive(length)
|
||||
if not str then
|
||||
co_yield(nil, err)
|
||||
end
|
||||
|
||||
max_chunk_size = co_yield(str) or default_chunk_size
|
||||
|
||||
-- If we're finished with this chunk, read the carriage return.
|
||||
if remaining == 0 then
|
||||
sock:receive(2) -- read \r\n
|
||||
end
|
||||
else
|
||||
-- Read the last (zero length) chunk's carriage return
|
||||
sock:receive(2) -- read \r\n
|
||||
end
|
||||
|
||||
until length == 0
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
local function _body_reader(sock, content_length, default_chunk_size)
|
||||
return co_wrap(function(max_chunk_size)
|
||||
local max_chunk_size = max_chunk_size or default_chunk_size
|
||||
|
||||
if not content_length and max_chunk_size then
|
||||
-- We have no length, but wish to stream.
|
||||
-- HTTP 1.0 with no length will close connection, so read chunks to the end.
|
||||
repeat
|
||||
local str, err, partial = sock:receive(max_chunk_size)
|
||||
if not str and err == "closed" then
|
||||
max_chunk_size = tonumber(co_yield(partial, err) or default_chunk_size)
|
||||
end
|
||||
|
||||
max_chunk_size = tonumber(co_yield(str) or default_chunk_size)
|
||||
if max_chunk_size and max_chunk_size < 0 then max_chunk_size = nil end
|
||||
|
||||
if not max_chunk_size then
|
||||
ngx_log(ngx_ERR, "Buffer size not specified, bailing")
|
||||
break
|
||||
end
|
||||
until not str
|
||||
|
||||
elseif not content_length then
|
||||
-- We have no length but don't wish to stream.
|
||||
-- HTTP 1.0 with no length will close connection, so read to the end.
|
||||
co_yield(sock:receive("*a"))
|
||||
|
||||
elseif not max_chunk_size then
|
||||
-- We have a length and potentially keep-alive, but want everything.
|
||||
co_yield(sock:receive(content_length))
|
||||
|
||||
else
|
||||
-- We have a length and potentially a keep-alive, and wish to stream
|
||||
-- the response.
|
||||
local received = 0
|
||||
repeat
|
||||
local length = max_chunk_size
|
||||
if received + length > content_length then
|
||||
length = content_length - received
|
||||
end
|
||||
|
||||
if length > 0 then
|
||||
local str, err = sock:receive(length)
|
||||
if not str then
|
||||
max_chunk_size = tonumber(co_yield(nil, err) or default_chunk_size)
|
||||
end
|
||||
received = received + length
|
||||
|
||||
max_chunk_size = tonumber(co_yield(str) or default_chunk_size)
|
||||
if max_chunk_size and max_chunk_size < 0 then max_chunk_size = nil end
|
||||
|
||||
if not max_chunk_size then
|
||||
ngx_log(ngx_ERR, "Buffer size not specified, bailing")
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
until length == 0
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
local function _no_body_reader()
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
local function _read_body(res)
|
||||
local reader = res.body_reader
|
||||
|
||||
if not reader then
|
||||
-- Most likely HEAD or 304 etc.
|
||||
return nil, "no body to be read"
|
||||
end
|
||||
|
||||
local chunks = {}
|
||||
local c = 1
|
||||
|
||||
local chunk, err
|
||||
repeat
|
||||
chunk, err = reader()
|
||||
|
||||
if err then
|
||||
return nil, err, tbl_concat(chunks) -- Return any data so far.
|
||||
end
|
||||
if chunk then
|
||||
chunks[c] = chunk
|
||||
c = c + 1
|
||||
end
|
||||
until not chunk
|
||||
|
||||
return tbl_concat(chunks)
|
||||
end
|
||||
|
||||
|
||||
local function _trailer_reader(sock)
|
||||
return co_wrap(function()
|
||||
co_yield(_receive_headers(sock))
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
local function _read_trailers(res)
|
||||
local reader = res.trailer_reader
|
||||
if not reader then
|
||||
return nil, "no trailers"
|
||||
end
|
||||
|
||||
local trailers = reader()
|
||||
setmetatable(res.headers, { __index = trailers })
|
||||
end
|
||||
|
||||
|
||||
local function _send_body(sock, body)
|
||||
if type(body) == 'function' then
|
||||
repeat
|
||||
local chunk, err, partial = body()
|
||||
|
||||
if chunk then
|
||||
local ok,err = sock:send(chunk)
|
||||
|
||||
if not ok then
|
||||
return nil, err
|
||||
end
|
||||
elseif err ~= nil then
|
||||
return nil, err, partial
|
||||
end
|
||||
|
||||
until chunk == nil
|
||||
elseif body ~= nil then
|
||||
local bytes, err = sock:send(body)
|
||||
|
||||
if not bytes then
|
||||
return nil, err
|
||||
end
|
||||
end
|
||||
return true, nil
|
||||
end
|
||||
|
||||
|
||||
local function _handle_continue(sock, body)
|
||||
local status, version, err = _receive_status(sock)
|
||||
if not status then
|
||||
return nil, err
|
||||
end
|
||||
|
||||
-- Only send body if we receive a 100 Continue
|
||||
if status == 100 then
|
||||
local ok, err = sock:receive("*l") -- Read carriage return
|
||||
if not ok then
|
||||
return nil, err
|
||||
end
|
||||
_send_body(sock, body)
|
||||
end
|
||||
return status, version, err
|
||||
end
|
||||
|
||||
|
||||
function _M.send_request(self, params)
|
||||
-- Apply defaults
|
||||
setmetatable(params, { __index = DEFAULT_PARAMS })
|
||||
|
||||
local sock = self.sock
|
||||
local body = params.body
|
||||
local headers = http_headers.new()
|
||||
|
||||
local params_headers = params.headers
|
||||
if params_headers then
|
||||
-- We assign one by one so that the metatable can handle case insensitivity
|
||||
-- for us. You can blame the spec for this inefficiency.
|
||||
for k,v in pairs(params_headers) do
|
||||
headers[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
-- Ensure minimal headers are set
|
||||
if type(body) == 'string' and not headers["Content-Length"] then
|
||||
headers["Content-Length"] = #body
|
||||
end
|
||||
if not headers["Host"] then
|
||||
headers["Host"] = self.host
|
||||
end
|
||||
if not headers["User-Agent"] then
|
||||
headers["User-Agent"] = _M._USER_AGENT
|
||||
end
|
||||
if params.version == 1.0 and not headers["Connection"] then
|
||||
headers["Connection"] = "Keep-Alive"
|
||||
end
|
||||
|
||||
params.headers = headers
|
||||
|
||||
-- Format and send request
|
||||
local req = _format_request(params)
|
||||
ngx_log(ngx_DEBUG, "\n", req)
|
||||
local bytes, err = sock:send(req)
|
||||
|
||||
if not bytes then
|
||||
return nil, err
|
||||
end
|
||||
|
||||
-- Send the request body, unless we expect: continue, in which case
|
||||
-- we handle this as part of reading the response.
|
||||
if headers["Expect"] ~= "100-continue" then
|
||||
local ok, err, partial = _send_body(sock, body)
|
||||
if not ok then
|
||||
return nil, err, partial
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
function _M.read_response(self, params)
|
||||
local sock = self.sock
|
||||
|
||||
local status, version, err
|
||||
|
||||
-- If we expect: continue, we need to handle this, sending the body if allowed.
|
||||
-- If we don't get 100 back, then status is the actual status.
|
||||
if params.headers["Expect"] == "100-continue" then
|
||||
local _status, _version, _err = _handle_continue(sock, params.body)
|
||||
if not _status then
|
||||
return nil, _err
|
||||
elseif _status ~= 100 then
|
||||
status, version, err = _status, _version, _err
|
||||
end
|
||||
end
|
||||
|
||||
-- Just read the status as normal.
|
||||
if not status then
|
||||
status, version, err = _receive_status(sock)
|
||||
if not status then
|
||||
return nil, err
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local res_headers, err = _receive_headers(sock)
|
||||
if not res_headers then
|
||||
return nil, err
|
||||
end
|
||||
|
||||
-- Determine if we should keepalive or not.
|
||||
local ok, connection = pcall(str_lower, res_headers["Connection"])
|
||||
if ok then
|
||||
if (version == 1.1 and connection == "close") or
|
||||
(version == 1.0 and connection ~= "keep-alive") then
|
||||
self.keepalive = false
|
||||
end
|
||||
end
|
||||
|
||||
local body_reader = _no_body_reader
|
||||
local trailer_reader, err = nil, nil
|
||||
local has_body = false
|
||||
|
||||
-- Receive the body_reader
|
||||
if _should_receive_body(params.method, status) then
|
||||
local ok, encoding = pcall(str_lower, res_headers["Transfer-Encoding"])
|
||||
if ok and version == 1.1 and encoding == "chunked" then
|
||||
body_reader, err = _chunked_body_reader(sock)
|
||||
has_body = true
|
||||
else
|
||||
|
||||
local ok, length = pcall(tonumber, res_headers["Content-Length"])
|
||||
if ok then
|
||||
body_reader, err = _body_reader(sock, length)
|
||||
has_body = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if res_headers["Trailer"] then
|
||||
trailer_reader, err = _trailer_reader(sock)
|
||||
end
|
||||
|
||||
if err then
|
||||
return nil, err
|
||||
else
|
||||
return {
|
||||
status = status,
|
||||
headers = res_headers,
|
||||
has_body = has_body,
|
||||
body_reader = body_reader,
|
||||
read_body = _read_body,
|
||||
trailer_reader = trailer_reader,
|
||||
read_trailers = _read_trailers,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function _M.request(self, params)
|
||||
local res, err = self:send_request(params)
|
||||
if not res then
|
||||
return res, err
|
||||
else
|
||||
return self:read_response(params)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function _M.request_pipeline(self, requests)
|
||||
for i, params in ipairs(requests) do
|
||||
if params.headers and params.headers["Expect"] == "100-continue" then
|
||||
return nil, "Cannot pipeline request specifying Expect: 100-continue"
|
||||
end
|
||||
|
||||
local res, err = self:send_request(params)
|
||||
if not res then
|
||||
return res, err
|
||||
end
|
||||
end
|
||||
|
||||
local responses = {}
|
||||
for i, params in ipairs(requests) do
|
||||
responses[i] = setmetatable({
|
||||
params = params,
|
||||
response_read = false,
|
||||
}, {
|
||||
-- Read each actual response lazily, at the point the user tries
|
||||
-- to access any of the fields.
|
||||
__index = function(t, k)
|
||||
local res, err
|
||||
if t.response_read == false then
|
||||
res, err = _M.read_response(self, t.params)
|
||||
t.response_read = true
|
||||
|
||||
if not res then
|
||||
ngx_log(ngx_ERR, err)
|
||||
else
|
||||
for rk, rv in pairs(res) do
|
||||
t[rk] = rv
|
||||
end
|
||||
end
|
||||
end
|
||||
return rawget(t, k)
|
||||
end,
|
||||
})
|
||||
end
|
||||
return responses
|
||||
end
|
||||
|
||||
|
||||
function _M.request_uri(self, uri, params)
|
||||
if not params then params = {} end
|
||||
|
||||
local parsed_uri, err = self:parse_uri(uri)
|
||||
if not parsed_uri then
|
||||
return nil, err
|
||||
end
|
||||
|
||||
local scheme, host, port, path = unpack(parsed_uri)
|
||||
if not params.path then params.path = path end
|
||||
|
||||
local c, err = self:connect(host, port)
|
||||
if not c then
|
||||
return nil, err
|
||||
end
|
||||
|
||||
if scheme == "https" then
|
||||
local verify = true
|
||||
if params.ssl_verify == false then
|
||||
verify = false
|
||||
end
|
||||
local ok, err = self:ssl_handshake(nil, host, verify)
|
||||
if not ok then
|
||||
return nil, err
|
||||
end
|
||||
end
|
||||
|
||||
local res, err = self:request(params)
|
||||
if not res then
|
||||
return nil, err
|
||||
end
|
||||
|
||||
local body, err = res:read_body()
|
||||
if not body then
|
||||
return nil, err
|
||||
end
|
||||
|
||||
res.body = body
|
||||
|
||||
local ok, err = self:set_keepalive()
|
||||
if not ok then
|
||||
ngx_log(ngx_ERR, err)
|
||||
end
|
||||
|
||||
return res, nil
|
||||
end
|
||||
|
||||
|
||||
function _M.get_client_body_reader(self, chunksize, sock)
|
||||
local chunksize = chunksize or 65536
|
||||
if not sock then
|
||||
local ok, err
|
||||
ok, sock, err = pcall(ngx_req_socket)
|
||||
|
||||
if not ok then
|
||||
return nil, sock -- pcall err
|
||||
end
|
||||
|
||||
if not sock then
|
||||
if err == "no body" then
|
||||
return nil
|
||||
else
|
||||
return nil, err
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local headers = ngx_req_get_headers()
|
||||
local length = headers.content_length
|
||||
local encoding = headers.transfer_encoding
|
||||
if length then
|
||||
return _body_reader(sock, tonumber(length), chunksize)
|
||||
elseif encoding and str_lower(encoding) == 'chunked' then
|
||||
-- Not yet supported by ngx_lua but should just work...
|
||||
return _chunked_body_reader(sock, chunksize)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function _M.proxy_request(self, chunksize)
|
||||
return self:request{
|
||||
method = ngx_req_get_method(),
|
||||
path = ngx_re_gsub(ngx_var.uri, "\\s", "%20", "jo") .. ngx_var.is_args .. (ngx_var.query_string or ""),
|
||||
body = self:get_client_body_reader(chunksize),
|
||||
headers = ngx_req_get_headers(),
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
function _M.proxy_response(self, response, chunksize)
|
||||
if not response then
|
||||
ngx_log(ngx_ERR, "no response provided")
|
||||
return
|
||||
end
|
||||
|
||||
ngx.status = response.status
|
||||
|
||||
-- Filter out hop-by-hop headeres
|
||||
for k,v in pairs(response.headers) do
|
||||
if not HOP_BY_HOP_HEADERS[str_lower(k)] then
|
||||
ngx.header[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
local reader = response.body_reader
|
||||
repeat
|
||||
local chunk, err = reader(chunksize)
|
||||
if err then
|
||||
ngx_log(ngx_ERR, err)
|
||||
break
|
||||
end
|
||||
|
||||
if chunk then
|
||||
local res, err = ngx.print(chunk)
|
||||
if not res then
|
||||
ngx_log(ngx_ERR, err)
|
||||
break
|
||||
end
|
||||
end
|
||||
until not chunk
|
||||
end
|
||||
|
||||
|
||||
return _M
|
||||
62
controllers/nginx/lua/vendor/lua-resty-http/lib/resty/http_headers.lua
vendored
Normal file
62
controllers/nginx/lua/vendor/lua-resty-http/lib/resty/http_headers.lua
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
local rawget, rawset, setmetatable =
|
||||
rawget, rawset, setmetatable
|
||||
|
||||
local str_gsub = string.gsub
|
||||
local str_lower = string.lower
|
||||
|
||||
|
||||
local _M = {
|
||||
_VERSION = '0.01',
|
||||
}
|
||||
|
||||
|
||||
-- Returns an empty headers table with internalised case normalisation.
|
||||
-- Supports the same cases as in ngx_lua:
|
||||
--
|
||||
-- headers.content_length
|
||||
-- headers["content-length"]
|
||||
-- headers["Content-Length"]
|
||||
function _M.new(self)
|
||||
local mt = {
|
||||
normalised = {},
|
||||
}
|
||||
|
||||
|
||||
mt.__index = function(t, k)
|
||||
local k_hyphened = str_gsub(k, "_", "-")
|
||||
local matched = rawget(t, k)
|
||||
if matched then
|
||||
return matched
|
||||
else
|
||||
local k_normalised = str_lower(k_hyphened)
|
||||
return rawget(t, mt.normalised[k_normalised])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- First check the normalised table. If there's no match (first time) add an entry for
|
||||
-- our current case in the normalised table. This is to preserve the human (prettier) case
|
||||
-- instead of outputting lowercased header names.
|
||||
--
|
||||
-- If there's a match, we're being updated, just with a different case for the key. We use
|
||||
-- the normalised table to give us the original key, and perorm a rawset().
|
||||
mt.__newindex = function(t, k, v)
|
||||
-- we support underscore syntax, so always hyphenate.
|
||||
local k_hyphened = str_gsub(k, "_", "-")
|
||||
|
||||
-- lowercase hyphenated is "normalised"
|
||||
local k_normalised = str_lower(k_hyphened)
|
||||
|
||||
if not mt.normalised[k_normalised] then
|
||||
mt.normalised[k_normalised] = k_hyphened
|
||||
rawset(t, k_hyphened, v)
|
||||
else
|
||||
rawset(t, mt.normalised[k_normalised], v)
|
||||
end
|
||||
end
|
||||
|
||||
return setmetatable({}, mt)
|
||||
end
|
||||
|
||||
|
||||
return _M
|
||||
33
controllers/nginx/lua/vendor/lua-resty-http/lua-resty-http-0.07-0.rockspec
vendored
Normal file
33
controllers/nginx/lua/vendor/lua-resty-http/lua-resty-http-0.07-0.rockspec
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
package = "lua-resty-http"
|
||||
version = "0.07-0"
|
||||
source = {
|
||||
url = "git://github.com/pintsized/lua-resty-http",
|
||||
tag = "v0.07"
|
||||
}
|
||||
description = {
|
||||
summary = "Lua HTTP client cosocket driver for OpenResty / ngx_lua.",
|
||||
detailed = [[
|
||||
Features an HTTP 1.0 and 1.1 streaming interface to reading
|
||||
bodies using coroutines, for predictable memory usage in Lua
|
||||
land. Alternative simple interface for singleshot requests
|
||||
without manual connection step. Supports chunked transfer
|
||||
encoding, keepalive, pipelining, and trailers. Headers are
|
||||
treated case insensitively. Probably production ready in most
|
||||
cases, though not yet proven in the wild.
|
||||
Recommended by the OpenResty maintainer as a long-term
|
||||
replacement for internal requests through ngx.location.capture.
|
||||
]],
|
||||
homepage = "https://github.com/pintsized/lua-resty-http",
|
||||
license = "2-clause BSD",
|
||||
maintainer = "James Hurst <james@pintsized.co.uk>"
|
||||
}
|
||||
dependencies = {
|
||||
"lua >= 5.1"
|
||||
}
|
||||
build = {
|
||||
type = "builtin",
|
||||
modules = {
|
||||
["resty.http"] = "lib/resty/http.lua",
|
||||
["resty.http_headers"] = "lib/resty/http_headers.lua"
|
||||
}
|
||||
}
|
||||
231
controllers/nginx/lua/vendor/lua-resty-http/t/01-basic.t
vendored
Normal file
231
controllers/nginx/lua/vendor/lua-resty-http/t/01-basic.t
vendored
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
# vim:set ft= ts=4 sw=4 et:
|
||||
|
||||
use Test::Nginx::Socket;
|
||||
use Cwd qw(cwd);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 4) + 1;
|
||||
|
||||
my $pwd = cwd();
|
||||
|
||||
our $HttpConfig = qq{
|
||||
lua_package_path "$pwd/lib/?.lua;;";
|
||||
error_log logs/error.log debug;
|
||||
};
|
||||
|
||||
$ENV{TEST_NGINX_RESOLVER} = '8.8.8.8';
|
||||
|
||||
no_long_string();
|
||||
#no_diff();
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
=== TEST 1: Simple default get.
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
path = "/b"
|
||||
}
|
||||
|
||||
ngx.status = res.status
|
||||
ngx.print(res:read_body())
|
||||
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
echo "OK";
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
OK
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 2: HTTP 1.0
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
version = 1.0,
|
||||
path = "/b"
|
||||
}
|
||||
|
||||
ngx.status = res.status
|
||||
ngx.print(res:read_body())
|
||||
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
echo "OK";
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
OK
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 3: Status code
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
path = "/b"
|
||||
}
|
||||
|
||||
ngx.status = res.status
|
||||
ngx.print(res:read_body())
|
||||
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
ngx.status = 404
|
||||
ngx.say("OK")
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
OK
|
||||
--- error_code: 404
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 4: Response headers
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
path = "/b"
|
||||
}
|
||||
|
||||
ngx.status = res.status
|
||||
ngx.say(res.headers["X-Test"])
|
||||
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
ngx.header["X-Test"] = "x-value"
|
||||
ngx.say("OK")
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
x-value
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 5: Query
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
query = {
|
||||
a = 1,
|
||||
b = 2,
|
||||
},
|
||||
path = "/b"
|
||||
}
|
||||
|
||||
ngx.status = res.status
|
||||
|
||||
for k,v in pairs(res.headers) do
|
||||
ngx.header[k] = v
|
||||
end
|
||||
|
||||
ngx.print(res:read_body())
|
||||
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
for k,v in pairs(ngx.req.get_uri_args()) do
|
||||
ngx.header["X-Header-" .. string.upper(k)] = v
|
||||
end
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_headers
|
||||
X-Header-A: 1
|
||||
X-Header-B: 2
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 7: HEAD has no body.
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
method = "HEAD",
|
||||
path = "/b"
|
||||
}
|
||||
|
||||
local body = res:read_body()
|
||||
|
||||
if body then
|
||||
ngx.print(body)
|
||||
end
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
echo "OK";
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
158
controllers/nginx/lua/vendor/lua-resty-http/t/02-chunked.t
vendored
Normal file
158
controllers/nginx/lua/vendor/lua-resty-http/t/02-chunked.t
vendored
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
# vim:set ft= ts=4 sw=4 et:
|
||||
|
||||
use Test::Nginx::Socket;
|
||||
use Cwd qw(cwd);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 4);
|
||||
|
||||
my $pwd = cwd();
|
||||
|
||||
our $HttpConfig = qq{
|
||||
lua_package_path "$pwd/lib/?.lua;;";
|
||||
};
|
||||
|
||||
$ENV{TEST_NGINX_RESOLVER} = '8.8.8.8';
|
||||
|
||||
no_long_string();
|
||||
#no_diff();
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
=== TEST 1: Non chunked.
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
path = "/b"
|
||||
}
|
||||
|
||||
local body = res:read_body()
|
||||
|
||||
ngx.say(#body)
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
chunked_transfer_encoding off;
|
||||
content_by_lua '
|
||||
local len = 32768
|
||||
local t = {}
|
||||
for i=1,len do
|
||||
t[i] = 0
|
||||
end
|
||||
ngx.print(table.concat(t))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
32768
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 2: Chunked. The number of chunks received when no max size is given proves the response was in fact chunked.
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
path = "/b"
|
||||
}
|
||||
|
||||
local chunks = {}
|
||||
local c = 1
|
||||
repeat
|
||||
local chunk, err = res.body_reader()
|
||||
if chunk then
|
||||
chunks[c] = chunk
|
||||
c = c + 1
|
||||
end
|
||||
until not chunk
|
||||
|
||||
local body = table.concat(chunks)
|
||||
|
||||
ngx.say(#body)
|
||||
ngx.say(#chunks)
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
local len = 32768
|
||||
local t = {}
|
||||
for i=1,len do
|
||||
t[i] = 0
|
||||
end
|
||||
ngx.print(table.concat(t))
|
||||
local len = 32768
|
||||
local t = {}
|
||||
for i=1,len do
|
||||
t[i] = 0
|
||||
end
|
||||
ngx.print(table.concat(t))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
65536
|
||||
2
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 3: Chunked using read_body method.
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
path = "/b"
|
||||
}
|
||||
|
||||
local body = res:read_body()
|
||||
|
||||
ngx.say(#body)
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
local len = 32768
|
||||
local t = {}
|
||||
for i=1,len do
|
||||
t[i] = 0
|
||||
end
|
||||
ngx.print(table.concat(t))
|
||||
local len = 32768
|
||||
local t = {}
|
||||
for i=1,len do
|
||||
t[i] = 0
|
||||
end
|
||||
ngx.print(table.concat(t))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
65536
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
185
controllers/nginx/lua/vendor/lua-resty-http/t/03-requestbody.t
vendored
Normal file
185
controllers/nginx/lua/vendor/lua-resty-http/t/03-requestbody.t
vendored
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
# vim:set ft= ts=4 sw=4 et:
|
||||
|
||||
use Test::Nginx::Socket;
|
||||
use Cwd qw(cwd);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 4);
|
||||
|
||||
my $pwd = cwd();
|
||||
|
||||
our $HttpConfig = qq{
|
||||
lua_package_path "$pwd/lib/?.lua;;";
|
||||
};
|
||||
|
||||
$ENV{TEST_NGINX_RESOLVER} = '8.8.8.8';
|
||||
|
||||
no_long_string();
|
||||
#no_diff();
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
=== TEST 1: POST form-urlencoded
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
body = "a=1&b=2&c=3",
|
||||
path = "/b",
|
||||
headers = {
|
||||
["Content-Type"] = "application/x-www-form-urlencoded",
|
||||
}
|
||||
}
|
||||
|
||||
ngx.say(res:read_body())
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
ngx.req.read_body()
|
||||
local args = ngx.req.get_post_args()
|
||||
ngx.say("a: ", args.a)
|
||||
ngx.say("b: ", args.b)
|
||||
ngx.print("c: ", args.c)
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
a: 1
|
||||
b: 2
|
||||
c: 3
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 2: POST form-urlencoded 1.0
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
method = "POST",
|
||||
body = "a=1&b=2&c=3",
|
||||
path = "/b",
|
||||
headers = {
|
||||
["Content-Type"] = "application/x-www-form-urlencoded",
|
||||
},
|
||||
version = 1.0,
|
||||
}
|
||||
|
||||
ngx.say(res:read_body())
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
ngx.req.read_body()
|
||||
local args = ngx.req.get_post_args()
|
||||
ngx.say(ngx.req.get_method())
|
||||
ngx.say("a: ", args.a)
|
||||
ngx.say("b: ", args.b)
|
||||
ngx.print("c: ", args.c)
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
POST
|
||||
a: 1
|
||||
b: 2
|
||||
c: 3
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 3: 100 Continue does not end requset
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
body = "a=1&b=2&c=3",
|
||||
path = "/b",
|
||||
headers = {
|
||||
["Expect"] = "100-continue",
|
||||
["Content-Type"] = "application/x-www-form-urlencoded",
|
||||
}
|
||||
}
|
||||
ngx.say(res.status)
|
||||
ngx.say(res:read_body())
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
ngx.req.read_body()
|
||||
local args = ngx.req.get_post_args()
|
||||
ngx.say("a: ", args.a)
|
||||
ngx.say("b: ", args.b)
|
||||
ngx.print("c: ", args.c)
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
200
|
||||
a: 1
|
||||
b: 2
|
||||
c: 3
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
=== TEST 4: Return non-100 status to user
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
path = "/b",
|
||||
headers = {
|
||||
["Expect"] = "100-continue",
|
||||
["Content-Type"] = "application/x-www-form-urlencoded",
|
||||
}
|
||||
}
|
||||
if not res then
|
||||
ngx.say(err)
|
||||
end
|
||||
ngx.say(res.status)
|
||||
ngx.say(res:read_body())
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
return 417 "Expectation Failed";
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
417
|
||||
Expectation Failed
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
151
controllers/nginx/lua/vendor/lua-resty-http/t/04-trailers.t
vendored
Normal file
151
controllers/nginx/lua/vendor/lua-resty-http/t/04-trailers.t
vendored
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
# vim:set ft= ts=4 sw=4 et:
|
||||
|
||||
use Test::Nginx::Socket;
|
||||
use Cwd qw(cwd);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 4);
|
||||
|
||||
my $pwd = cwd();
|
||||
|
||||
our $HttpConfig = qq{
|
||||
lua_package_path "$pwd/lib/?.lua;;";
|
||||
};
|
||||
|
||||
$ENV{TEST_NGINX_RESOLVER} = '8.8.8.8';
|
||||
|
||||
no_long_string();
|
||||
#no_diff();
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
=== TEST 1: Trailers. Check Content-MD5 generated after the body is sent matches up.
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
path = "/b",
|
||||
headers = {
|
||||
["TE"] = "trailers",
|
||||
}
|
||||
}
|
||||
|
||||
local body = res:read_body()
|
||||
local hash = ngx.md5(body)
|
||||
res:read_trailers()
|
||||
|
||||
if res.headers["Content-MD5"] == hash then
|
||||
ngx.say("OK")
|
||||
else
|
||||
ngx.say(res.headers["Content-MD5"])
|
||||
end
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
-- We use the raw socket to compose a response, since OpenResty
|
||||
-- doesnt support trailers natively.
|
||||
|
||||
ngx.req.read_body()
|
||||
local sock, err = ngx.req.socket(true)
|
||||
if not sock then
|
||||
ngx.say(err)
|
||||
end
|
||||
|
||||
local res = {}
|
||||
table.insert(res, "HTTP/1.1 200 OK")
|
||||
table.insert(res, "Date: " .. ngx.http_time(ngx.time()))
|
||||
table.insert(res, "Transfer-Encoding: chunked")
|
||||
table.insert(res, "Trailer: Content-MD5")
|
||||
table.insert(res, "")
|
||||
|
||||
local body = "Hello, World"
|
||||
|
||||
table.insert(res, string.format("%x", #body))
|
||||
table.insert(res, body)
|
||||
table.insert(res, "0")
|
||||
table.insert(res, "")
|
||||
|
||||
table.insert(res, "Content-MD5: " .. ngx.md5(body))
|
||||
|
||||
table.insert(res, "")
|
||||
table.insert(res, "")
|
||||
sock:send(table.concat(res, "\\r\\n"))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
OK
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 2: Advertised trailer does not exist, handled gracefully.
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
path = "/b",
|
||||
headers = {
|
||||
["TE"] = "trailers",
|
||||
}
|
||||
}
|
||||
|
||||
local body = res:read_body()
|
||||
local hash = ngx.md5(body)
|
||||
res:read_trailers()
|
||||
|
||||
ngx.say("OK")
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
-- We use the raw socket to compose a response, since OpenResty
|
||||
-- doesnt support trailers natively.
|
||||
|
||||
ngx.req.read_body()
|
||||
local sock, err = ngx.req.socket(true)
|
||||
if not sock then
|
||||
ngx.say(err)
|
||||
end
|
||||
|
||||
local res = {}
|
||||
table.insert(res, "HTTP/1.1 200 OK")
|
||||
table.insert(res, "Date: " .. ngx.http_time(ngx.time()))
|
||||
table.insert(res, "Transfer-Encoding: chunked")
|
||||
table.insert(res, "Trailer: Content-MD5")
|
||||
table.insert(res, "")
|
||||
|
||||
local body = "Hello, World"
|
||||
|
||||
table.insert(res, string.format("%x", #body))
|
||||
table.insert(res, body)
|
||||
table.insert(res, "0")
|
||||
|
||||
table.insert(res, "")
|
||||
table.insert(res, "")
|
||||
sock:send(table.concat(res, "\\r\\n"))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
OK
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
566
controllers/nginx/lua/vendor/lua-resty-http/t/05-stream.t
vendored
Normal file
566
controllers/nginx/lua/vendor/lua-resty-http/t/05-stream.t
vendored
Normal file
|
|
@ -0,0 +1,566 @@
|
|||
# vim:set ft= ts=4 sw=4 et:
|
||||
|
||||
use Test::Nginx::Socket;
|
||||
use Cwd qw(cwd);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 4) - 1;
|
||||
|
||||
my $pwd = cwd();
|
||||
|
||||
our $HttpConfig = qq{
|
||||
lua_package_path "$pwd/lib/?.lua;;";
|
||||
};
|
||||
|
||||
$ENV{TEST_NGINX_RESOLVER} = '8.8.8.8';
|
||||
|
||||
no_long_string();
|
||||
#no_diff();
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
=== TEST 1: Chunked streaming body reader returns the right content length.
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
path = "/b",
|
||||
}
|
||||
|
||||
local chunks = {}
|
||||
repeat
|
||||
local chunk = res.body_reader()
|
||||
if chunk then
|
||||
table.insert(chunks, chunk)
|
||||
end
|
||||
until not chunk
|
||||
|
||||
local body = table.concat(chunks)
|
||||
ngx.say(#body)
|
||||
ngx.say(res.headers["Transfer-Encoding"])
|
||||
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
local len = 32768
|
||||
local t = {}
|
||||
for i=1,len do
|
||||
t[i] = 0
|
||||
end
|
||||
ngx.print(table.concat(t))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
32768
|
||||
chunked
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 2: Non-Chunked streaming body reader returns the right content length.
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
path = "/b",
|
||||
}
|
||||
|
||||
local chunks = {}
|
||||
repeat
|
||||
local chunk = res.body_reader()
|
||||
if chunk then
|
||||
table.insert(chunks, chunk)
|
||||
end
|
||||
until not chunk
|
||||
|
||||
local body = table.concat(chunks)
|
||||
ngx.say(#body)
|
||||
ngx.say(res.headers["Transfer-Encoding"])
|
||||
ngx.say(#chunks)
|
||||
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
chunked_transfer_encoding off;
|
||||
content_by_lua '
|
||||
local len = 32768
|
||||
local t = {}
|
||||
for i=1,len do
|
||||
t[i] = 0
|
||||
end
|
||||
ngx.print(table.concat(t))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
32768
|
||||
nil
|
||||
1
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 2b: Non-Chunked streaming body reader, buffer size becomes nil
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
path = "/b",
|
||||
}
|
||||
|
||||
local chunks = {}
|
||||
local buffer_size = 16384
|
||||
repeat
|
||||
local chunk = res.body_reader(buffer_size)
|
||||
if chunk then
|
||||
table.insert(chunks, chunk)
|
||||
end
|
||||
|
||||
buffer_size = nil
|
||||
until not chunk
|
||||
|
||||
local body = table.concat(chunks)
|
||||
ngx.say(res.headers["Transfer-Encoding"])
|
||||
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
chunked_transfer_encoding off;
|
||||
content_by_lua '
|
||||
local len = 32768
|
||||
local t = {}
|
||||
for i=1,len do
|
||||
t[i] = 0
|
||||
end
|
||||
ngx.print(table.concat(t))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
nil
|
||||
--- error_log
|
||||
Buffer size not specified, bailing
|
||||
|
||||
|
||||
=== TEST 3: HTTP 1.0 body reader with no max size returns the right content length.
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
path = "/b",
|
||||
version = 1.0,
|
||||
}
|
||||
|
||||
local chunks = {}
|
||||
repeat
|
||||
local chunk = res.body_reader()
|
||||
if chunk then
|
||||
table.insert(chunks, chunk)
|
||||
end
|
||||
until not chunk
|
||||
|
||||
local body = table.concat(chunks)
|
||||
ngx.say(#body)
|
||||
ngx.say(res.headers["Transfer-Encoding"])
|
||||
ngx.say(#chunks)
|
||||
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
chunked_transfer_encoding off;
|
||||
content_by_lua '
|
||||
local len = 32768
|
||||
local t = {}
|
||||
for i=1,len do
|
||||
t[i] = 0
|
||||
end
|
||||
ngx.print(table.concat(t))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
32768
|
||||
nil
|
||||
1
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 4: HTTP 1.0 body reader with max chunk size returns the right content length.
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
path = "/b",
|
||||
version = 1.0,
|
||||
}
|
||||
|
||||
local chunks = {}
|
||||
local size = 8192
|
||||
repeat
|
||||
local chunk = res.body_reader(size)
|
||||
if chunk then
|
||||
table.insert(chunks, chunk)
|
||||
end
|
||||
size = size + size
|
||||
until not chunk
|
||||
|
||||
local body = table.concat(chunks)
|
||||
ngx.say(#body)
|
||||
ngx.say(res.headers["Transfer-Encoding"])
|
||||
ngx.say(#chunks)
|
||||
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
chunked_transfer_encoding off;
|
||||
content_by_lua '
|
||||
local len = 32769
|
||||
local t = {}
|
||||
for i=1,len do
|
||||
t[i] = 0
|
||||
end
|
||||
ngx.print(table.concat(t))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
32769
|
||||
nil
|
||||
3
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 4b: HTTP 1.0 body reader with no content length, stream works as expected.
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
path = "/b",
|
||||
version = 1.0,
|
||||
}
|
||||
|
||||
local chunks = {}
|
||||
local size = 8192
|
||||
repeat
|
||||
local chunk = res.body_reader(size)
|
||||
if chunk then
|
||||
table.insert(chunks, chunk)
|
||||
end
|
||||
size = size + size
|
||||
until not chunk
|
||||
|
||||
local body = table.concat(chunks)
|
||||
ngx.say(#body)
|
||||
ngx.say(#chunks)
|
||||
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
ngx.req.read_body()
|
||||
local sock, err = ngx.req.socket(true)
|
||||
if not sock then
|
||||
ngx.say(err)
|
||||
end
|
||||
|
||||
local res = {}
|
||||
table.insert(res, "HTTP/1.0 200 OK")
|
||||
table.insert(res, "Date: " .. ngx.http_time(ngx.time()))
|
||||
table.insert(res, "")
|
||||
|
||||
local len = 32769
|
||||
local t = {}
|
||||
for i=1,len do
|
||||
t[i] = 0
|
||||
end
|
||||
table.insert(res, table.concat(t))
|
||||
sock:send(table.concat(res, "\\r\\n"))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
32769
|
||||
3
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 5: Chunked streaming body reader with max chunk size returns the right content length.
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
path = "/b",
|
||||
}
|
||||
|
||||
local chunks = {}
|
||||
local size = 8192
|
||||
repeat
|
||||
local chunk = res.body_reader(size)
|
||||
if chunk then
|
||||
table.insert(chunks, chunk)
|
||||
end
|
||||
size = size + size
|
||||
until not chunk
|
||||
|
||||
local body = table.concat(chunks)
|
||||
ngx.say(#body)
|
||||
ngx.say(res.headers["Transfer-Encoding"])
|
||||
ngx.say(#chunks)
|
||||
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
local len = 32768
|
||||
local t = {}
|
||||
for i=1,len do
|
||||
t[i] = 0
|
||||
end
|
||||
ngx.print(table.concat(t))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
32768
|
||||
chunked
|
||||
3
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 6: Request reader correctly reads body
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
lua_need_request_body off;
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
|
||||
local reader, err = httpc:get_client_body_reader(8192)
|
||||
|
||||
repeat
|
||||
local chunk, err = reader()
|
||||
if chunk then
|
||||
ngx.print(chunk)
|
||||
end
|
||||
until chunk == nil
|
||||
|
||||
';
|
||||
}
|
||||
|
||||
--- request
|
||||
POST /a
|
||||
foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz
|
||||
--- response_body: foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
=== TEST 7: Request reader correctly reads body in chunks
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
lua_need_request_body off;
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
|
||||
local reader, err = httpc:get_client_body_reader(64)
|
||||
|
||||
local chunks = 0
|
||||
repeat
|
||||
chunks = chunks +1
|
||||
local chunk, err = reader()
|
||||
if chunk then
|
||||
ngx.print(chunk)
|
||||
end
|
||||
until chunk == nil
|
||||
ngx.say("\\n"..chunks)
|
||||
';
|
||||
}
|
||||
|
||||
--- request
|
||||
POST /a
|
||||
foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz
|
||||
--- response_body
|
||||
foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz
|
||||
3
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 8: Request reader passes into client
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
lua_need_request_body off;
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local reader, err = httpc:get_client_body_reader(64)
|
||||
|
||||
local res, err = httpc:request{
|
||||
method = POST,
|
||||
path = "/b",
|
||||
body = reader,
|
||||
headers = ngx.req.get_headers(100, true),
|
||||
}
|
||||
|
||||
local body = res:read_body()
|
||||
ngx.say(body)
|
||||
httpc:close()
|
||||
|
||||
';
|
||||
}
|
||||
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
ngx.req.read_body()
|
||||
local body, err = ngx.req.get_body_data()
|
||||
ngx.print(body)
|
||||
';
|
||||
}
|
||||
|
||||
--- request
|
||||
POST /a
|
||||
foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz
|
||||
--- response_body
|
||||
foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 9: Body reader is a function returning nil when no body is present.
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
path = "/b",
|
||||
method = "HEAD",
|
||||
}
|
||||
|
||||
repeat
|
||||
local chunk = res.body_reader()
|
||||
until not chunk
|
||||
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
ngx.exit(200)
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 10: Issue a notice (but do not error) if trying to read the request body in a subrequest
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
echo_location /b;
|
||||
}
|
||||
location = /b {
|
||||
lua_need_request_body off;
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
|
||||
local reader, err = httpc:get_client_body_reader(8192)
|
||||
if not reader then
|
||||
ngx.log(ngx.NOTICE, err)
|
||||
return
|
||||
end
|
||||
|
||||
repeat
|
||||
local chunk, err = reader()
|
||||
if chunk then
|
||||
ngx.print(chunk)
|
||||
end
|
||||
until chunk == nil
|
||||
';
|
||||
}
|
||||
|
||||
--- request
|
||||
POST /a
|
||||
foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz
|
||||
--- response_body:
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
--- error_log
|
||||
attempt to read the request body in a subrequest
|
||||
145
controllers/nginx/lua/vendor/lua-resty-http/t/06-simpleinterface.t
vendored
Normal file
145
controllers/nginx/lua/vendor/lua-resty-http/t/06-simpleinterface.t
vendored
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
# vim:set ft= ts=4 sw=4 et:
|
||||
|
||||
use Test::Nginx::Socket;
|
||||
use Cwd qw(cwd);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 4) + 6;
|
||||
|
||||
my $pwd = cwd();
|
||||
|
||||
our $HttpConfig = qq{
|
||||
lua_package_path "$pwd/lib/?.lua;;";
|
||||
error_log logs/error.log debug;
|
||||
};
|
||||
|
||||
$ENV{TEST_NGINX_RESOLVER} = '8.8.8.8';
|
||||
|
||||
no_long_string();
|
||||
#no_diff();
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
=== TEST 1: Simple URI interface
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
local res, err = httpc:request_uri("http://127.0.0.1:"..ngx.var.server_port.."/b?a=1&b=2")
|
||||
|
||||
if not res then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
ngx.status = res.status
|
||||
|
||||
ngx.header["X-Header-A"] = res.headers["X-Header-A"]
|
||||
ngx.header["X-Header-B"] = res.headers["X-Header-B"]
|
||||
|
||||
ngx.print(res.body)
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
for k,v in pairs(ngx.req.get_uri_args()) do
|
||||
ngx.header["X-Header-" .. string.upper(k)] = v
|
||||
end
|
||||
ngx.say("OK")
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_headers
|
||||
X-Header-A: 1
|
||||
X-Header-B: 2
|
||||
--- response_body
|
||||
OK
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 2: Simple URI interface HTTP 1.0
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
local res, err = httpc:request_uri(
|
||||
"http://127.0.0.1:"..ngx.var.server_port.."/b?a=1&b=2", {
|
||||
}
|
||||
)
|
||||
|
||||
ngx.status = res.status
|
||||
|
||||
ngx.header["X-Header-A"] = res.headers["X-Header-A"]
|
||||
ngx.header["X-Header-B"] = res.headers["X-Header-B"]
|
||||
|
||||
ngx.print(res.body)
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
for k,v in pairs(ngx.req.get_uri_args()) do
|
||||
ngx.header["X-Header-" .. string.upper(k)] = v
|
||||
end
|
||||
ngx.say("OK")
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_headers
|
||||
X-Header-A: 1
|
||||
X-Header-B: 2
|
||||
--- response_body
|
||||
OK
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 3 Simple URI interface, params override
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
local res, err = httpc:request_uri(
|
||||
"http://127.0.0.1:"..ngx.var.server_port.."/b?a=1&b=2", {
|
||||
path = "/c",
|
||||
query = {
|
||||
a = 2,
|
||||
b = 3,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
ngx.status = res.status
|
||||
|
||||
ngx.header["X-Header-A"] = res.headers["X-Header-A"]
|
||||
ngx.header["X-Header-B"] = res.headers["X-Header-B"]
|
||||
|
||||
ngx.print(res.body)
|
||||
';
|
||||
}
|
||||
location = /c {
|
||||
content_by_lua '
|
||||
for k,v in pairs(ngx.req.get_uri_args()) do
|
||||
ngx.header["X-Header-" .. string.upper(k)] = v
|
||||
end
|
||||
ngx.say("OK")
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_headers
|
||||
X-Header-A: 2
|
||||
X-Header-B: 3
|
||||
--- response_body
|
||||
OK
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
182
controllers/nginx/lua/vendor/lua-resty-http/t/07-keepalive.t
vendored
Normal file
182
controllers/nginx/lua/vendor/lua-resty-http/t/07-keepalive.t
vendored
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
# vim:set ft= ts=4 sw=4 et:
|
||||
|
||||
use Test::Nginx::Socket;
|
||||
use Cwd qw(cwd);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 4);
|
||||
|
||||
my $pwd = cwd();
|
||||
|
||||
our $HttpConfig = qq{
|
||||
lua_package_path "$pwd/lib/?.lua;;";
|
||||
error_log logs/error.log debug;
|
||||
};
|
||||
|
||||
$ENV{TEST_NGINX_RESOLVER} = '8.8.8.8';
|
||||
|
||||
no_long_string();
|
||||
#no_diff();
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
=== TEST 1 Simple interface, Connection: Keep-alive. Test the connection is reused.
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
local res, err = httpc:request_uri(
|
||||
"http://127.0.0.1:"..ngx.var.server_port.."/b", {
|
||||
}
|
||||
)
|
||||
|
||||
ngx.say(res.headers["Connection"])
|
||||
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
ngx.say(httpc:get_reused_times())
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
ngx.say("OK")
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
keep-alive
|
||||
1
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 2 Simple interface, Connection: close, test we don't try to keepalive, but also that subsequent connections can keepalive.
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
local res, err = httpc:request_uri(
|
||||
"http://127.0.0.1:"..ngx.var.server_port.."/b", {
|
||||
version = 1.0,
|
||||
headers = {
|
||||
["Connection"] = "close",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
ngx.say(httpc:get_reused_times())
|
||||
|
||||
httpc:set_keepalive()
|
||||
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
ngx.say(httpc:get_reused_times())
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
ngx.say("OK")
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
0
|
||||
1
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 3 Generic interface, Connection: Keep-alive. Test the connection is reused.
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
path = "/b"
|
||||
}
|
||||
|
||||
local body = res:read_body()
|
||||
|
||||
ngx.say(res.headers["Connection"])
|
||||
ngx.say(httpc:set_keepalive())
|
||||
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
ngx.say(httpc:get_reused_times())
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
ngx.say("OK")
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
keep-alive
|
||||
1
|
||||
1
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 4 Generic interface, Connection: Close. Test we don't try to keepalive, but also that subsequent connections can keepalive.
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
version = 1.0,
|
||||
headers = {
|
||||
["Connection"] = "Close",
|
||||
},
|
||||
path = "/b"
|
||||
}
|
||||
|
||||
local body = res:read_body()
|
||||
|
||||
ngx.say(res.headers["Connection"])
|
||||
local r, e = httpc:set_keepalive()
|
||||
ngx.say(r)
|
||||
ngx.say(e)
|
||||
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
ngx.say(httpc:get_reused_times())
|
||||
|
||||
httpc:set_keepalive()
|
||||
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
ngx.say(httpc:get_reused_times())
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
ngx.say("OK")
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
close
|
||||
2
|
||||
connection must be closed
|
||||
0
|
||||
1
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
143
controllers/nginx/lua/vendor/lua-resty-http/t/08-pipeline.t
vendored
Normal file
143
controllers/nginx/lua/vendor/lua-resty-http/t/08-pipeline.t
vendored
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
# vim:set ft= ts=4 sw=4 et:
|
||||
|
||||
use Test::Nginx::Socket;
|
||||
use Cwd qw(cwd);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 4);
|
||||
|
||||
my $pwd = cwd();
|
||||
|
||||
our $HttpConfig = qq{
|
||||
lua_package_path "$pwd/lib/?.lua;;";
|
||||
error_log logs/error.log debug;
|
||||
};
|
||||
|
||||
$ENV{TEST_NGINX_RESOLVER} = '8.8.8.8';
|
||||
|
||||
no_long_string();
|
||||
#no_diff();
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
=== TEST 1 Test that pipelined reqests can be read correctly.
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local responses = httpc:request_pipeline{
|
||||
{
|
||||
path = "/b",
|
||||
},
|
||||
{
|
||||
path = "/c",
|
||||
},
|
||||
{
|
||||
path = "/d",
|
||||
}
|
||||
}
|
||||
|
||||
for i,r in ipairs(responses) do
|
||||
if r.status then
|
||||
ngx.say(r.status)
|
||||
ngx.say(r.headers["X-Res"])
|
||||
ngx.say(r:read_body())
|
||||
end
|
||||
end
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
ngx.status = 200
|
||||
ngx.header["X-Res"] = "B"
|
||||
ngx.print("B")
|
||||
';
|
||||
}
|
||||
location = /c {
|
||||
content_by_lua '
|
||||
ngx.status = 404
|
||||
ngx.header["X-Res"] = "C"
|
||||
ngx.print("C")
|
||||
';
|
||||
}
|
||||
location = /d {
|
||||
content_by_lua '
|
||||
ngx.status = 200
|
||||
ngx.header["X-Res"] = "D"
|
||||
ngx.print("D")
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
200
|
||||
B
|
||||
B
|
||||
404
|
||||
C
|
||||
C
|
||||
200
|
||||
D
|
||||
D
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 2: Test we can handle timeouts on reading the pipelined requests.
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
httpc:set_timeout(1)
|
||||
|
||||
local responses = httpc:request_pipeline{
|
||||
{
|
||||
path = "/b",
|
||||
},
|
||||
{
|
||||
path = "/c",
|
||||
},
|
||||
}
|
||||
|
||||
for i,r in ipairs(responses) do
|
||||
if r.status then
|
||||
ngx.say(r.status)
|
||||
ngx.say(r.headers["X-Res"])
|
||||
ngx.say(r:read_body())
|
||||
end
|
||||
end
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
ngx.status = 200
|
||||
ngx.header["X-Res"] = "B"
|
||||
ngx.print("B")
|
||||
';
|
||||
}
|
||||
location = /c {
|
||||
content_by_lua '
|
||||
ngx.status = 404
|
||||
ngx.header["X-Res"] = "C"
|
||||
ngx.sleep(1)
|
||||
ngx.print("C")
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
200
|
||||
B
|
||||
B
|
||||
--- no_error_log
|
||||
[warn]
|
||||
--- error_log eval
|
||||
[qr/timeout/]
|
||||
59
controllers/nginx/lua/vendor/lua-resty-http/t/09-ssl.t
vendored
Normal file
59
controllers/nginx/lua/vendor/lua-resty-http/t/09-ssl.t
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
# vim:set ft= ts=4 sw=4 et:
|
||||
|
||||
use Test::Nginx::Socket;
|
||||
use Cwd qw(cwd);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 4);
|
||||
|
||||
my $pwd = cwd();
|
||||
|
||||
our $HttpConfig = qq{
|
||||
lua_package_path "$pwd/lib/?.lua;;";
|
||||
error_log logs/error.log debug;
|
||||
};
|
||||
|
||||
$ENV{TEST_NGINX_RESOLVER} = '8.8.8.8';
|
||||
|
||||
no_long_string();
|
||||
#no_diff();
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
=== TEST 1: parse_uri returns port 443 for https URIs
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
local parsed = httpc:parse_uri("https://www.google.com/foobar")
|
||||
ngx.say(parsed[3])
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
443
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
=== TEST 2: parse_uri returns port 80 for http URIs
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
local parsed = httpc:parse_uri("http://www.google.com/foobar")
|
||||
ngx.say(parsed[3])
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
80
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
57
controllers/nginx/lua/vendor/lua-resty-http/t/10-clientbodyreader.t
vendored
Normal file
57
controllers/nginx/lua/vendor/lua-resty-http/t/10-clientbodyreader.t
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
# vim:set ft= ts=4 sw=4 et:
|
||||
|
||||
use Test::Nginx::Socket;
|
||||
use Cwd qw(cwd);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 4);
|
||||
|
||||
my $pwd = cwd();
|
||||
|
||||
our $HttpConfig = qq{
|
||||
lua_package_path "$pwd/lib/?.lua;;";
|
||||
};
|
||||
|
||||
$ENV{TEST_NGINX_RESOLVER} = '8.8.8.8';
|
||||
|
||||
no_long_string();
|
||||
#no_diff();
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
=== TEST 1: Issue a notice (but do not error) if trying to read the request body in a subrequest
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
echo_location /b;
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
path = "/c",
|
||||
headers = {
|
||||
["Content-Type"] = "application/x-www-form-urlencoded",
|
||||
}
|
||||
}
|
||||
if not res then
|
||||
ngx.say(err)
|
||||
end
|
||||
ngx.print(res:read_body())
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location /c {
|
||||
echo "OK";
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
OK
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
152
controllers/nginx/lua/vendor/lua-resty-http/t/11-proxy.t
vendored
Normal file
152
controllers/nginx/lua/vendor/lua-resty-http/t/11-proxy.t
vendored
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
# vim:set ft= ts=4 sw=4 et:
|
||||
|
||||
use Test::Nginx::Socket;
|
||||
use Cwd qw(cwd);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 5);
|
||||
|
||||
my $pwd = cwd();
|
||||
|
||||
our $HttpConfig = qq{
|
||||
lua_package_path "$pwd/lib/?.lua;;";
|
||||
error_log logs/error.log debug;
|
||||
};
|
||||
|
||||
$ENV{TEST_NGINX_RESOLVER} = '8.8.8.8';
|
||||
|
||||
no_long_string();
|
||||
#no_diff();
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
=== TEST 1: Proxy GET request and response
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a_prx {
|
||||
rewrite ^(.*)_prx$ $1 break;
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
httpc:proxy_response(httpc:proxy_request())
|
||||
httpc:set_keepalive()
|
||||
';
|
||||
}
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
ngx.status = 200
|
||||
ngx.header["X-Test"] = "foo"
|
||||
ngx.say("OK")
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a_prx
|
||||
--- response_body
|
||||
OK
|
||||
--- response_headers
|
||||
X-Test: foo
|
||||
--- error_code: 200
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 2: Proxy POST request and response
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a_prx {
|
||||
rewrite ^(.*)_prx$ $1 break;
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
httpc:proxy_response(httpc:proxy_request())
|
||||
httpc:set_keepalive()
|
||||
';
|
||||
}
|
||||
location = /a {
|
||||
lua_need_request_body on;
|
||||
content_by_lua '
|
||||
ngx.status = 404
|
||||
ngx.header["X-Test"] = "foo"
|
||||
local args, err = ngx.req.get_post_args()
|
||||
ngx.say(args["foo"])
|
||||
ngx.say(args["hello"])
|
||||
';
|
||||
}
|
||||
--- request
|
||||
POST /a_prx
|
||||
foo=bar&hello=world
|
||||
--- response_body
|
||||
bar
|
||||
world
|
||||
--- response_headers
|
||||
X-Test: foo
|
||||
--- error_code: 404
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 3: Proxy multiple headers
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a_prx {
|
||||
rewrite ^(.*)_prx$ $1 break;
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
httpc:proxy_response(httpc:proxy_request())
|
||||
httpc:set_keepalive()
|
||||
';
|
||||
}
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
ngx.status = 200
|
||||
ngx.header["Set-Cookie"] = { "cookie1", "cookie2" }
|
||||
ngx.say("OK")
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a_prx
|
||||
--- response_body
|
||||
OK
|
||||
--- raw_response_headers_like: .*Set-Cookie: cookie1\r\nSet-Cookie: cookie2\r\n
|
||||
--- error_code: 200
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 4: Proxy still works with spaces in URI
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = "/a_ b_prx" {
|
||||
rewrite ^(.*)_prx$ $1 break;
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
httpc:proxy_response(httpc:proxy_request())
|
||||
httpc:set_keepalive()
|
||||
';
|
||||
}
|
||||
location = "/a_ b" {
|
||||
content_by_lua '
|
||||
ngx.status = 200
|
||||
ngx.header["X-Test"] = "foo"
|
||||
ngx.say("OK")
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a_%20b_prx
|
||||
--- response_body
|
||||
OK
|
||||
--- response_headers
|
||||
X-Test: foo
|
||||
--- error_code: 200
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
160
controllers/nginx/lua/vendor/lua-resty-http/t/12-case_insensitive_headers.t
vendored
Normal file
160
controllers/nginx/lua/vendor/lua-resty-http/t/12-case_insensitive_headers.t
vendored
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
# vim:set ft= ts=4 sw=4 et:
|
||||
|
||||
use Test::Nginx::Socket;
|
||||
use Cwd qw(cwd);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 4);
|
||||
|
||||
my $pwd = cwd();
|
||||
|
||||
our $HttpConfig = qq{
|
||||
lua_package_path "$pwd/lib/?.lua;;";
|
||||
error_log logs/error.log debug;
|
||||
};
|
||||
|
||||
$ENV{TEST_NGINX_RESOLVER} = '8.8.8.8';
|
||||
|
||||
no_long_string();
|
||||
#no_diff();
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
=== TEST 1: Test header normalisation
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http_headers = require "resty.http_headers"
|
||||
|
||||
local headers = http_headers.new()
|
||||
|
||||
headers.x_a_header = "a"
|
||||
headers["x-b-header"] = "b"
|
||||
headers["X-C-Header"] = "c"
|
||||
headers["X_d-HEAder"] = "d"
|
||||
|
||||
ngx.say(headers["X-A-Header"])
|
||||
ngx.say(headers.x_b_header)
|
||||
|
||||
for k,v in pairs(headers) do
|
||||
ngx.say(k, ": ", v)
|
||||
end
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
a
|
||||
b
|
||||
x-b-header: b
|
||||
x-a-header: a
|
||||
X-d-HEAder: d
|
||||
X-C-Header: c
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 2: Test headers can be accessed in all cases
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
path = "/b"
|
||||
}
|
||||
|
||||
ngx.status = res.status
|
||||
ngx.say(res.headers["X-Foo-Header"])
|
||||
ngx.say(res.headers["x-fOo-heaDeR"])
|
||||
ngx.say(res.headers.x_foo_header)
|
||||
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
ngx.header["X-Foo-Header"] = "bar"
|
||||
ngx.say("OK")
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
bar
|
||||
bar
|
||||
bar
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
|
||||
|
||||
=== TEST 3: Test request headers are normalised
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||||
|
||||
local res, err = httpc:request{
|
||||
path = "/b",
|
||||
headers = {
|
||||
["uSeR-AgENT"] = "test_user_agent",
|
||||
x_foo = "bar",
|
||||
},
|
||||
}
|
||||
|
||||
ngx.status = res.status
|
||||
ngx.print(res:read_body())
|
||||
|
||||
httpc:close()
|
||||
';
|
||||
}
|
||||
location = /b {
|
||||
content_by_lua '
|
||||
ngx.say(ngx.req.get_headers()["User-Agent"])
|
||||
ngx.say(ngx.req.get_headers()["X-Foo"])
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_body
|
||||
test_user_agent
|
||||
bar
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
=== TEST 4: Test that headers remain unique
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location = /a {
|
||||
content_by_lua '
|
||||
local http_headers = require "resty.http_headers"
|
||||
|
||||
local headers = http_headers.new()
|
||||
|
||||
headers["x-a-header"] = "a"
|
||||
headers["X-A-HEAder"] = "b"
|
||||
|
||||
for k,v in pairs(headers) do
|
||||
ngx.log(ngx.DEBUG, k, ": ", v)
|
||||
ngx.header[k] = v
|
||||
end
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /a
|
||||
--- response_headers
|
||||
x-a-header: b
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
[warn]
|
||||
52
controllers/nginx/lua/vendor/lua-resty-http/t/13-default-path.t
vendored
Normal file
52
controllers/nginx/lua/vendor/lua-resty-http/t/13-default-path.t
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# vim:set ft= ts=4 sw=4 et:
|
||||
|
||||
use Test::Nginx::Socket;
|
||||
use Cwd qw(cwd);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 3);
|
||||
|
||||
my $pwd = cwd();
|
||||
|
||||
our $HttpConfig = qq{
|
||||
lua_package_path "$pwd/lib/?.lua;;";
|
||||
error_log logs/error.log debug;
|
||||
};
|
||||
|
||||
$ENV{TEST_NGINX_RESOLVER} = '8.8.8.8';
|
||||
|
||||
no_long_string();
|
||||
#no_diff();
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
=== TEST 1: request_uri (check the default path)
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /lua {
|
||||
content_by_lua '
|
||||
local http = require "resty.http"
|
||||
local httpc = http.new()
|
||||
|
||||
local res, err = httpc:request_uri("http://127.0.0.1:"..ngx.var.server_port)
|
||||
|
||||
if res and 200 == res.status then
|
||||
ngx.say("OK")
|
||||
else
|
||||
ngx.say("FAIL")
|
||||
end
|
||||
';
|
||||
}
|
||||
|
||||
location =/ {
|
||||
content_by_lua '
|
||||
ngx.print("OK")
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /lua
|
||||
--- response_body
|
||||
OK
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
63
controllers/nginx/lua/vendor/lua-resty-http/util/lua-releng
vendored
Executable file
63
controllers/nginx/lua/vendor/lua-resty-http/util/lua-releng
vendored
Executable file
|
|
@ -0,0 +1,63 @@
|
|||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub file_contains ($$);
|
||||
|
||||
my $version;
|
||||
for my $file (map glob, qw{ *.lua lib/*.lua lib/*/*.lua lib/*/*/*.lua lib/*/*/*/*.lua lib/*/*/*/*/*.lua }) {
|
||||
# Check the sanity of each .lua file
|
||||
open my $in, $file or
|
||||
die "ERROR: Can't open $file for reading: $!\n";
|
||||
my $found_ver;
|
||||
while (<$in>) {
|
||||
my ($ver, $skipping);
|
||||
if (/(?x) (?:_VERSION) \s* = .*? ([\d\.]*\d+) (.*? SKIP)?/) {
|
||||
my $orig_ver = $ver = $1;
|
||||
$found_ver = 1;
|
||||
# $skipping = $2;
|
||||
$ver =~ s{^(\d+)\.(\d{3})(\d{3})$}{join '.', int($1), int($2), int($3)}e;
|
||||
warn "$file: $orig_ver ($ver)\n";
|
||||
|
||||
} elsif (/(?x) (?:_VERSION) \s* = \s* ([a-zA-Z_]\S*)/) {
|
||||
warn "$file: $1\n";
|
||||
$found_ver = 1;
|
||||
last;
|
||||
}
|
||||
|
||||
if ($ver and $version and !$skipping) {
|
||||
if ($version ne $ver) {
|
||||
# die "$file: $ver != $version\n";
|
||||
}
|
||||
} elsif ($ver and !$version) {
|
||||
$version = $ver;
|
||||
}
|
||||
}
|
||||
if (!$found_ver) {
|
||||
warn "WARNING: No \"_VERSION\" or \"version\" field found in `$file`.\n";
|
||||
}
|
||||
close $in;
|
||||
|
||||
print "Checking use of Lua global variables in file $file ...\n";
|
||||
system("luac -p -l $file | grep ETGLOBAL | grep -vE 'require|type|tostring|error|ngx|ndk|jit|setmetatable|getmetatable|string|table|io|os|print|tonumber|math|pcall|xpcall|unpack|pairs|ipairs|assert|module|package|coroutine|[gs]etfenv|next|select|rawset|rawget|debug'");
|
||||
#file_contains($file, "attempt to write to undeclared variable");
|
||||
system("grep -H -n -E --color '.{120}' $file");
|
||||
}
|
||||
|
||||
sub file_contains ($$) {
|
||||
my ($file, $regex) = @_;
|
||||
open my $in, $file
|
||||
or die "Cannot open $file fo reading: $!\n";
|
||||
my $content = do { local $/; <$in> };
|
||||
close $in;
|
||||
#print "$content";
|
||||
return scalar ($content =~ /$regex/);
|
||||
}
|
||||
|
||||
if (-d 't') {
|
||||
for my $file (map glob, qw{ t/*.t t/*/*.t t/*/*/*.t }) {
|
||||
system(qq{grep -H -n --color -E '\\--- ?(ONLY|LAST)' $file});
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue