implemented, tested, and documented the new ngx.redirect(uri, status) method for Lua.
This commit is contained in:
Родитель
d98a147780
Коммит
32c3686a15
|
@ -424,7 +424,43 @@ Named locations are also supported, but query strings are ignored. For example
|
|||
...
|
||||
}
|
||||
|
||||
This function never returns.
|
||||
Note that this is very different from ngx.redirect() in that
|
||||
it's just an internal redirect and no new HTTP traffic is involved.
|
||||
|
||||
This method never returns.
|
||||
|
||||
This method MUST be called before `ngx.send_headers()` or explicit response body
|
||||
outputs by either `ngx.print` or `ngx.say`.
|
||||
|
||||
This method is very much like the `echo_exec`
|
||||
directive in the ngx_echo module.
|
||||
|
||||
ngx.redirect(uri, status?)
|
||||
--------------------------
|
||||
|
||||
Issue an HTTP 301 or 302 redirection to `uri`.
|
||||
|
||||
The optional `status` parameter specify whether
|
||||
301 or 302 to be used. It's 302 (ngx.HTTP_MOVED_TEMPORARILY) by default.
|
||||
|
||||
This method MUST be called before `ngx.send_headers()` or explicit response body
|
||||
outputs by either `ngx.print` or `ngx.say`.
|
||||
|
||||
Here's a small example:
|
||||
|
||||
return ngx.redirect("/foo")
|
||||
|
||||
which is equivalent to
|
||||
|
||||
return ngx.redirect("http://<host>:<port>/foo", ngx.HTTP_MOVED_TEMPORARILY)
|
||||
|
||||
where <host> is the current virtual server name and
|
||||
<port> is the listerning port.
|
||||
|
||||
This method never returns.
|
||||
|
||||
This method is very much like the `rewrite` directive with the `redirect` modifier in the standard
|
||||
`ngx_rewrite` module.
|
||||
|
||||
ngx.send_headers()
|
||||
------------------
|
||||
|
|
|
@ -2060,3 +2060,79 @@ ngx_http_lua_ngx_cookie_time(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ngx_http_lua_ngx_redirect(lua_State *L)
|
||||
{
|
||||
ngx_http_lua_ctx_t *ctx;
|
||||
ngx_int_t rc;
|
||||
int n;
|
||||
u_char *p;
|
||||
u_char *uri;
|
||||
size_t len;
|
||||
ngx_http_request_t *r;
|
||||
|
||||
n = lua_gettop(L);
|
||||
|
||||
if (n != 1 && n != 2) {
|
||||
return luaL_error(L, "expecting one or two arguments");
|
||||
}
|
||||
|
||||
p = (u_char *) luaL_checklstring(L, 1, &len);
|
||||
|
||||
if (n == 2) {
|
||||
rc = (ngx_int_t) luaL_checknumber(L, 2);
|
||||
|
||||
if (rc != NGX_HTTP_MOVED_TEMPORARILY &&
|
||||
rc != NGX_HTTP_MOVED_PERMANENTLY)
|
||||
{
|
||||
return luaL_error(L, "only ngx.HTTP_MOVED_TEMPORARILY and "
|
||||
"ngx.HTTP_MOVED_PERMANENTLY are allowed");
|
||||
}
|
||||
} else {
|
||||
rc = NGX_HTTP_MOVED_TEMPORARILY;
|
||||
}
|
||||
|
||||
lua_getglobal(L, GLOBALS_SYMBOL_REQUEST);
|
||||
r = lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (r == NULL) {
|
||||
return luaL_error(L, "no request object found");
|
||||
}
|
||||
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
|
||||
if (ctx == NULL) {
|
||||
return luaL_error(L, "no request ctx found");
|
||||
}
|
||||
|
||||
if (ctx->headers_sent) {
|
||||
return luaL_error(L, "attempt to call ngx.redirect after sending out the headers");
|
||||
}
|
||||
|
||||
uri = ngx_palloc(r->pool, len);
|
||||
if (uri == NULL) {
|
||||
return luaL_error(L, "out of memory");
|
||||
}
|
||||
|
||||
ngx_memcpy(uri, p, len);
|
||||
|
||||
r->headers_out.location = ngx_list_push(&r->headers_out.headers);
|
||||
if (r->headers_out.location == NULL) {
|
||||
return luaL_error(L, "out of memory");
|
||||
}
|
||||
|
||||
r->headers_out.location->hash = 1;
|
||||
r->headers_out.location->value.len = len;
|
||||
r->headers_out.location->value.data = uri;
|
||||
ngx_str_set(&r->headers_out.location->key, "Location");
|
||||
|
||||
r->headers_out.status = rc;
|
||||
|
||||
ctx->exit_code = rc;
|
||||
ctx->exited = 1;
|
||||
|
||||
lua_pushnil(L);
|
||||
return lua_error(L);
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ int ngx_http_lua_ngx_strtime(lua_State *L);
|
|||
int ngx_http_lua_ngx_utc_time(lua_State *L);
|
||||
int ngx_http_lua_ngx_utc_strtime(lua_State *L);
|
||||
int ngx_http_lua_ngx_cookie_time(lua_State *L);
|
||||
int ngx_http_lua_ngx_redirect(lua_State *L);
|
||||
|
||||
int ngx_http_lua_ngx_location_capture(lua_State *L);
|
||||
|
||||
|
|
|
@ -530,6 +530,9 @@ init_ngx_lua_globals(lua_State *L)
|
|||
lua_pushcfunction(L, ngx_http_lua_ngx_cookie_time);
|
||||
lua_setfield(L, -2, "cookie_time");
|
||||
|
||||
lua_pushcfunction(L, ngx_http_lua_ngx_redirect);
|
||||
lua_setfield(L, -2, "redirect");
|
||||
|
||||
lua_createtable(L, 0, 2); /* .location */
|
||||
lua_pushcfunction(L, ngx_http_lua_ngx_location_capture);
|
||||
lua_setfield(L, -2, "capture");
|
||||
|
|
12
t/005-exit.t
12
t/005-exit.t
|
@ -201,8 +201,8 @@ Logged in 56
|
|||
|
||||
set $key "conv-uid-$arg_uid";
|
||||
|
||||
srcache_fetch GET /memc key=$key;
|
||||
srcache_store PUT /memc key=$key;
|
||||
#srcache_fetch GET /memc key=$key;
|
||||
#srcache_store PUT /memc key=$key;
|
||||
|
||||
default_type 'application/json';
|
||||
|
||||
|
@ -281,8 +281,8 @@ Logged in 56
|
|||
|
||||
set $key "conv-uid-$arg_uid";
|
||||
|
||||
srcache_fetch GET /memc key=$key;
|
||||
srcache_store PUT /memc key=$key;
|
||||
#srcache_fetch GET /memc key=$key;
|
||||
#srcache_store PUT /memc key=$key;
|
||||
|
||||
default_type 'application/json';
|
||||
|
||||
|
@ -358,8 +358,8 @@ Logged in 56
|
|||
|
||||
set $key "conv-uri-$query_string";
|
||||
|
||||
srcache_fetch GET /memc key=$key;
|
||||
srcache_store PUT /memc key=$key;
|
||||
#srcache_fetch GET /memc key=$key;
|
||||
#srcache_store PUT /memc key=$key;
|
||||
|
||||
default_type 'application/json';
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ use Test::Nginx::Socket;
|
|||
#master_process_enabled(1);
|
||||
#log_level('warn');
|
||||
|
||||
#repeat_each(120);
|
||||
repeat_each(1);
|
||||
repeat_each(2);
|
||||
#repeat_each(1);
|
||||
|
||||
plan tests => blocks() * repeat_each() * 3;
|
||||
|
||||
|
|
|
@ -355,7 +355,8 @@ PUT: 201
|
|||
cached: hello
|
||||
|
||||
|
||||
=== TEST 12: POST (with body, memc method)
|
||||
|
||||
=== TEST 13: POST (with body, memc method)
|
||||
--- config
|
||||
location /flush {
|
||||
set $memc_cmd flush_all;
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
# 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() * 3;
|
||||
|
||||
#no_diff();
|
||||
#no_long_string();
|
||||
|
||||
$ENV{TEST_NGINX_PORT} ||= 1984;
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: default 302
|
||||
--- config
|
||||
location /read {
|
||||
content_by_lua '
|
||||
ngx.redirect("http://www.taobao.com/foo");
|
||||
ngx.say("hi")
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /read
|
||||
--- response_headers
|
||||
Location: http://www.taobao.com/foo
|
||||
--- response_body_like: 302 Found
|
||||
--- error_code: 302
|
||||
|
||||
|
||||
|
||||
=== TEST 2: explicit 302
|
||||
--- config
|
||||
location /read {
|
||||
content_by_lua '
|
||||
ngx.redirect("http://www.taobao.com/foo", ngx.HTTP_MOVED_TEMPORARILY);
|
||||
ngx.say("hi")
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /read
|
||||
--- response_headers
|
||||
Location: http://www.taobao.com/foo
|
||||
--- response_body_like: 302 Found
|
||||
--- error_code: 302
|
||||
|
||||
|
||||
|
||||
=== TEST 3: explicit 301
|
||||
--- config
|
||||
location /read {
|
||||
content_by_lua '
|
||||
ngx.redirect("http://www.taobao.com/foo", ngx.HTTP_MOVED_PERMANENTLY);
|
||||
ngx.say("hi")
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /read
|
||||
--- response_headers
|
||||
Location: http://www.taobao.com/foo
|
||||
--- response_body_like: 301 Moved Permanently
|
||||
--- error_code: 301
|
||||
|
||||
|
||||
|
||||
=== TEST 4: bad rc
|
||||
--- config
|
||||
location /read {
|
||||
content_by_lua '
|
||||
ngx.redirect("http://www.taobao.com/foo", 404);
|
||||
ngx.say("hi")
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /read
|
||||
--- response_headers
|
||||
!Location
|
||||
--- response_body_like: 500 Internal Server Error
|
||||
--- error_code: 500
|
||||
|
||||
|
||||
|
||||
=== TEST 5: no args
|
||||
--- config
|
||||
location /read {
|
||||
content_by_lua '
|
||||
ngx.redirect()
|
||||
ngx.say("hi")
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /read
|
||||
--- response_headers
|
||||
!Location
|
||||
--- response_body_like: 500 Internal Server Error
|
||||
--- error_code: 500
|
||||
|
||||
|
||||
|
||||
=== TEST 6: relative uri
|
||||
--- config
|
||||
location /read {
|
||||
content_by_lua '
|
||||
ngx.redirect("/foo")
|
||||
ngx.say("hi")
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /read
|
||||
--- raw_response_headers_like: Location: http://localhost(?::\d+)?/foo\r\n
|
||||
--- response_body_like: 302 Found
|
||||
--- error_code: 302
|
||||
|
Загрузка…
Ссылка в новой задаче