implemented the method and body options for ngx.location.capture.

This commit is contained in:
agentzh (章亦春) 2010-11-16 20:47:33 +08:00
Родитель 539cad5991
Коммит 8e9a88981a
4 изменённых файлов: 214 добавлений и 14 удалений

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

@ -476,6 +476,10 @@ URI query strings can be concatenated to URI itself, for instance,
res = ngx.location.capture('/foo/bar?a=3&b=4')
Named locations like `@foo` are not allowed due to a limitation in
the nginx core. Use normal locations combined with the `internal` directive to
prepare internal-only locations.
ndk.set_var.DIRECTIVE
---------------------

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

@ -9,7 +9,23 @@
#define NGX_UNESCAPE_URI_COMPONENT 0
static ngx_int_t ngx_http_lua_adjust_subrequest(ngx_http_request_t *sr);
#define ngx_http_lua_method_name(m) { sizeof(m) - 1, (u_char *) m " " }
static ngx_str_t ngx_http_lua_get_method = ngx_http_lua_method_name("GET");
static ngx_str_t ngx_http_lua_put_method = ngx_http_lua_method_name("PUT");
static ngx_str_t ngx_http_lua_post_method = ngx_http_lua_method_name("POST");
static ngx_str_t ngx_http_lua_head_method = ngx_http_lua_method_name("HEAD");
static ngx_str_t ngx_http_lua_delete_method = ngx_http_lua_method_name("DELETE");
static ngx_str_t ngx_http_lua_content_length_header_key =
ngx_string("Content-Length");
static ngx_int_t ngx_http_lua_set_content_length_header(ngx_http_request_t *r,
size_t len);
static ngx_int_t ngx_http_lua_adjust_subrequest(ngx_http_request_t *sr,
ngx_uint_t method, ngx_http_request_body_t *body);
static ngx_int_t ngx_http_lua_post_subrequest(ngx_http_request_t *r, void *data, ngx_int_t rc);
static int ngx_http_lua_ngx_echo(lua_State *L, ngx_flag_t newline);
static void ngx_unescape_uri_patched(u_char **dst, u_char **src, size_t size, ngx_uint_t type);
@ -416,9 +432,15 @@ ngx_http_lua_ngx_location_capture(lua_State *L)
ngx_http_lua_ctx_t *sr_ctx;
ngx_str_t uri, args;
ngx_uint_t flags = 0;
const char *p;
u_char *p;
u_char *q;
size_t len;
int rc;
int n;
ngx_uint_t method;
ngx_http_request_body_t *body = NULL;
int type;
ngx_buf_t *b;
lua_getglobal(L, GLOBALS_SYMBOL_REQUEST);
r = lua_touserdata(L, -1);
@ -428,25 +450,83 @@ ngx_http_lua_ngx_location_capture(lua_State *L)
return luaL_error(L, "no request object found");
}
if (lua_gettop(L) != 1) {
return luaL_error(L, "expecting one argument");
n = lua_gettop(L);
if (n != 1 && n != 2) {
return luaL_error(L, "expecting one or two arguments");
}
p = luaL_checklstring(L, 1, &len);
if (n == 2) {
if (lua_type(L, 2) != LUA_TTABLE) {
return luaL_error(L, "expecting table as the 2nd argument");
}
lua_getfield(L, 2, "method");
type = lua_type(L, -1);
if (type == LUA_TNIL) {
method = NGX_HTTP_GET;
} else {
if (type != LUA_TNUMBER) {
return luaL_error(L, "Bad http request method");
}
method = (ngx_uint_t) lua_tonumber(L, -1);
}
lua_getfield(L, 2, "body");
if (type != LUA_TNIL) {
if (type != LUA_TSTRING && type != LUA_TNUMBER) {
return luaL_error(L, "Bad http request body");
}
q = (u_char *) lua_tolstring(L, -1, &len);
if (len != 0) {
body = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));
b = ngx_create_temp_buf(r->pool, len);
if (b == NULL) {
return luaL_error(L, "out of memory");
}
b->last = ngx_copy(b->last, q, len);
body->bufs = ngx_alloc_chain_link(r->pool);
if (body->bufs == NULL) {
return luaL_error(L, "out of memory");
}
body->bufs->buf = b;
body->bufs->next = NULL;
body->buf = b;
}
}
} else {
method = NGX_HTTP_GET;
}
p = (u_char *) luaL_checklstring(L, 1, &len);
uri.data = ngx_palloc(r->pool, len);
if (uri.data == NULL) {
return luaL_error(L, "memory allocation error");
}
uri.len = len;
ngx_memcpy(uri.data, p, len);
uri.len = len;
args.data = NULL;
args.len = 0;
if (ngx_http_parse_unsafe_uri(r, &uri, &args, &flags) != NGX_OK) {
return luaL_argerror(L, 1, "unsafe URL");
rc = ngx_http_parse_unsafe_uri(r, &uri, &args, &flags);
if (rc != NGX_OK) {
dd("rc = %d", (int) rc);
return luaL_error(L, "unsafe uri in argument #1: %s", p);
}
psr = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t));
@ -472,7 +552,7 @@ ngx_http_lua_ngx_location_capture(lua_State *L)
ngx_http_set_ctx(sr, sr_ctx, ngx_http_lua_module);
rc = ngx_http_lua_adjust_subrequest(sr);
rc = ngx_http_lua_adjust_subrequest(sr, method, body);
if (rc != NGX_OK) {
return luaL_error(L, "failed to adjust the subrequest: %d", (int) rc);
@ -485,18 +565,67 @@ ngx_http_lua_ngx_location_capture(lua_State *L)
static ngx_int_t
ngx_http_lua_adjust_subrequest(ngx_http_request_t *sr)
ngx_http_lua_adjust_subrequest(ngx_http_request_t *sr, ngx_uint_t method,
ngx_http_request_body_t *body)
{
ngx_http_core_main_conf_t *cmcf;
ngx_http_request_t *r;
ngx_int_t rc;
/* we do not inherit the parent request's variables */
cmcf = ngx_http_get_module_main_conf(sr, ngx_http_core_module);
/* cmcf = ngx_http_get_module_main_conf(sr, ngx_http_core_module); */
r = sr->parent;
sr->header_in = r->header_in;
#if 1
/* XXX work-around a bug in ngx_http_subrequest */
if (r->headers_in.headers.last == &r->headers_in.headers.part) {
sr->headers_in.headers.last = &sr->headers_in.headers.part;
}
#endif
if (body) {
sr->request_body = body;
rc = ngx_http_lua_set_content_length_header(sr,
ngx_buf_size(body->buf));
if (rc != NGX_OK) {
return NGX_ERROR;
}
}
sr->method = method;
switch (method) {
case NGX_HTTP_GET:
sr->method_name = ngx_http_lua_get_method;
break;
case NGX_HTTP_POST:
sr->method_name = ngx_http_lua_post_method;
break;
case NGX_HTTP_PUT:
sr->method_name = ngx_http_lua_put_method;
break;
case NGX_HTTP_HEAD:
sr->method_name = ngx_http_lua_head_method;
break;
case NGX_HTTP_DELETE:
sr->method_name = ngx_http_lua_delete_method;
break;
default:
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"unsupported HTTP method: %u", (unsigned) method);
return NGX_ERROR;
}
/* XXX work-around a bug in ngx_http_subrequest */
if (r->headers_in.headers.last == &r->headers_in.headers.part) {
sr->headers_in.headers.last = &sr->headers_in.headers.part;
@ -1796,3 +1925,54 @@ ngx_http_lua_run_set_var_directive(lua_State *L)
return 1;
}
static ngx_int_t
ngx_http_lua_set_content_length_header(ngx_http_request_t *r, size_t len)
{
ngx_table_elt_t *h;
r->headers_in.content_length_n = len;
r->headers_in.content_length = ngx_pcalloc(r->pool,
sizeof(ngx_table_elt_t));
r->headers_in.content_length->value.data =
ngx_palloc(r->pool, NGX_OFF_T_LEN);
if (r->headers_in.content_length->value.data == NULL) {
return NGX_ERROR;
}
r->headers_in.content_length->value.len = ngx_sprintf(
r->headers_in.content_length->value.data, "%O",
r->headers_in.content_length_n) -
r->headers_in.content_length->value.data;
if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
sizeof(ngx_table_elt_t)) != NGX_OK) {
return NGX_ERROR;
}
h = ngx_list_push(&r->headers_in.headers);
if (h == NULL) {
return NGX_ERROR;
}
h->hash = r->header_hash;
h->key = ngx_http_lua_content_length_header_key;
h->value = r->headers_in.content_length->value;
h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
if (h->lowcase_key == NULL) {
return NGX_ERROR;
}
ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
dd("r content length: %.*s",
(int)r->headers_in.content_length->value.len,
r->headers_in.content_length->value.data);
return NGX_OK;
}

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

@ -9,7 +9,8 @@ static void init_ngx_lua_globals(lua_State *L);
static void inject_http_consts(lua_State *L);
static void inject_log_consts(lua_State *L);
static void inject_core_consts(lua_State *L);
static void setpath(lua_State *L, int tab_idx, const char *fieldname, const char *path, const char *def);
static void setpath(lua_State *L, int tab_idx, const char *fieldname,
const char *path, const char *def);
#define LUA_PATH_SEP ";"
#define AUX_MARK "\1"
@ -337,6 +338,21 @@ static void
inject_http_consts(lua_State *L)
{
/* {{{ HTTP status constants */
lua_pushinteger(L, NGX_HTTP_GET);
lua_setfield(L, -2, "HTTP_GET");
lua_pushinteger(L, NGX_HTTP_POST);
lua_setfield(L, -2, "HTTP_POST");
lua_pushinteger(L, NGX_HTTP_PUT);
lua_setfield(L, -2, "HTTP_PUT");
lua_pushinteger(L, NGX_HTTP_DELETE);
lua_setfield(L, -2, "HTTP_DELETE");
lua_pushinteger(L, NGX_HTTP_HEAD);
lua_setfield(L, -2, "HTTP_HEAD");
lua_pushinteger(L, 200);
lua_setfield(L, -2, "HTTP_OK");

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

@ -27,7 +27,7 @@ __DATA__
--- request
GET /read
--- response_body
%20:
%20%3a
a b