implemented the ngx.req.header table interface for retrieving all the request headers for Lua. thanks moodydeath.

This commit is contained in:
agentzh (章亦春) 2011-05-09 23:37:06 +08:00
Родитель c230c16f58
Коммит 35b4c8d86d
5 изменённых файлов: 205 добавлений и 4 удалений

Просмотреть файл

@ -905,13 +905,34 @@ same does assigning an empty table:
`ngx.header` is not a normal Lua table so you cannot
iterate through it.
For reading request headers, use `ngx.var.http_HEADER`, that is, nginx's standard $http_HEADER variables:
For reading request headers, see the `ngx.req.header` interface instead.
Reading values from ngx.header.HEADER is not implemented yet,
and usually you shouldn't need it.
ngx.req.header
--------------
* **Context:** `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
This read-only Lua table holds all of the request headers. Because it is an ordinary Lua table,
iterating through it via Lua's `pairs` function is supported, for instance,
local h = {}
for k, v in pairs(ngx.req.header) do
h[k] = v
end
For performance reasons, this table
is generated on-the-fly at the first time it is accessed.
This Lua table is read-only, setting values to this table will not automatically modify the request headers on the Nginx land.
(TODO: we'll provide `ngx.req.set_header()` and `ngx.req.clear_header()` for
request header modification.)
Another way to read individual request headers is to use `ngx.var.http_HEADER`, that is, nginx's standard $http_HEADER variables:
http://wiki.nginx.org/NginxHttpCoreModule#.24http_HEADER
Reading values from ngx.header.HEADER is not implemented yet, and usually you
shouldn't need it.
ngx.exec(uri, args)
-------------------
* **Context:** `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`

Просмотреть файл

@ -42,6 +42,7 @@ static void log_wrapper(ngx_http_request_t *r, const char *ident, int level,
lua_State *L);
static uintptr_t ngx_http_lua_escape_uri(u_char *dst, u_char *src,
size_t size, ngx_uint_t type);
static void ngx_http_lua_create_req_header_table(lua_State *L);
#if defined(NDK) && NDK
static ndk_set_var_value_pt ngx_http_lookup_ndk_set_var_directive(u_char *name,
@ -1933,6 +1934,88 @@ ngx_http_lua_ngx_set(lua_State *L) {
}
int
ngx_http_lua_ngx_req_get(lua_State *L) {
u_char *p;
size_t len;
p = (u_char *) luaL_checklstring(L, -1, &len);
if (len == sizeof("header") - 1 &&
ngx_strncmp(p, "header", sizeof("header") - 1) == 0)
{
ngx_http_lua_create_req_header_table(L); /* req "header" header */
lua_insert(L, 2); /* req header "header" */
lua_pushvalue(L, 2); /* req header "header" header */
lua_rawset(L, 1); /* req header */
return 1;
}
dd("key %s not matched", p);
lua_pushnil(L);
return 1;
}
static void
ngx_http_lua_create_req_header_table(lua_State *L) {
ngx_list_part_t *part;
ngx_table_elt_t *header;
ngx_http_request_t *r;
ngx_uint_t i;
lua_getglobal(L, GLOBALS_SYMBOL_REQUEST);
r = lua_touserdata(L, -1);
lua_pop(L, 1);
if (r == NULL) {
luaL_error(L, "no request object found");
return;
}
lua_createtable(L, 0, 8); /* Firefox creates 8 headers in its requests */
part = &r->headers_in.headers.part;
header = part->elts;
for (i = 0; /* void */; i++) {
if (i >= part->nelts) {
if (part->next == NULL) {
break;
}
part = part->next;
header = part->elts;
i = 0;
}
lua_pushlstring(L, (char *) header[i].key.data, header[i].key.len);
lua_pushlstring(L, (char *) header[i].value.data, header[i].value.len);
lua_rawset(L, -3);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http lua req header: \"%V: %V\"",
&header[i].key, &header[i].value);
}
}
int
ngx_http_lua_ngx_req_set(lua_State *L) {
u_char *p;
size_t len;
/* we skip the first argument that is the table */
p = (u_char *) luaL_checklstring(L, 2, &len);
return luaL_error(L, "Attempt to write to ngx.req. with the key \"%s\"", p);
}
int
ngx_http_lua_header_get(lua_State *L)
{

Просмотреть файл

@ -49,6 +49,9 @@ int ngx_http_lua_ngx_location_capture_multi(lua_State *L);
int ngx_http_lua_ngx_get(lua_State *L);
int ngx_http_lua_ngx_set(lua_State *L);
int ngx_http_lua_ngx_req_get(lua_State *L);
int ngx_http_lua_ngx_req_set(lua_State *L);
int ngx_http_lua_header_get(lua_State *L);
int ngx_http_lua_header_set(lua_State *L);

Просмотреть файл

@ -631,6 +631,21 @@ init_ngx_lua_globals(lua_State *L)
lua_setfield(L, -2, "var");
/* {{{ ngx.req table */
lua_newtable(L); /* .req */
lua_createtable(L, 0, 2); /* metatable for .header */
lua_pushcfunction(L, ngx_http_lua_ngx_req_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, ngx_http_lua_ngx_req_set);
lua_setfield(L, -2, "__newindex");
lua_setmetatable(L, -2);
lua_setfield(L, -2, "req");
/* }}} */
#if 1
lua_newtable(L); /* .header */

79
t/028-req-header.t Normal file
Просмотреть файл

@ -0,0 +1,79 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use lib 'lib';
use Test::Nginx::Socket;
#worker_connections(1014);
#master_process_enabled(1);
#log_level('warn');
repeat_each(2);
#repeat_each(1);
plan tests => blocks() * repeat_each() * 2;
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: random access req headers
--- config
location /req-header {
content_by_lua '
ngx.say("Foo: ", ngx.req.header["Foo"] or "nil")
ngx.say("Bar: ", ngx.req.header["Bar"] or "nil")
';
}
--- request
GET /req-header
--- more_headers
Foo: bar
Bar: baz
--- response_body
Foo: bar
Bar: baz
=== TEST 2: iterating through headers
--- config
location /req-header {
content_by_lua '
local h = {}
for k, v in pairs(ngx.req.header) do
h[k] = v
end
ngx.say("Foo: ", h["Foo"] or "nil")
ngx.say("Bar: ", h["Bar"] or "nil")
';
}
--- request
GET /req-header
--- more_headers
Foo: bar
Bar: baz
--- response_body
Foo: bar
Bar: baz
=== TEST 3: setting req header table
--- config
location /req-header {
content_by_lua '
ngx.req.header.foo = 3;
ngx.say(ngx.req.header.foo)
';
}
--- request
GET /req-header
--- more_headers
Foo: bar
Bar: baz
--- response_body
3