From 6ae1262cb2f84892bb6eb25ffb27da99614dbfca Mon Sep 17 00:00:00 2001 From: Alacner Zhang Date: Mon, 2 May 2011 23:31:03 +0800 Subject: [PATCH] finish ngx.get, cannot use & like & , use %26 mode --- config | 4 +- example/t1.lua | 2 +- src/ngx_http_lua_module.c | 131 +++++++++++++++++++++++++------------- src/strtok_r.c | 106 ++++++++++++++++++++++++++++++ src/strtok_r.h | 1 + 5 files changed, 195 insertions(+), 49 deletions(-) create mode 100644 src/strtok_r.c create mode 100644 src/strtok_r.h diff --git a/config b/config index bdd6522..58932d6 100644 --- a/config +++ b/config @@ -140,8 +140,8 @@ fi ngx_addon_name=ngx_http_lua_module HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES ngx_http_lua_module" -NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/src/ngx_http_lua_module.c" -NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_addon_dir/src/ddebug.h" +NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/src/ngx_http_lua_module.c $ngx_addon_dir/src/strtok_r.c" +NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_addon_dir/src/ddebug.h $ngx_addon_dir/src/strtok_r.h" CFLAGS="$CFLAGS -DNDK_SET_VAR" ngx_feature="export symbols by default" diff --git a/example/t1.lua b/example/t1.lua index abcba91..ddf7917 100644 --- a/example/t1.lua +++ b/example/t1.lua @@ -1,5 +1,5 @@ --Copyright (c) 2011-2015 Zhihua Zhang (alacner@gmail.com) -ngx.set_header('Content-Type', "text"); +ngx.set_header('Content-Type', "text/html"); --local f = io.open('/root/test.jpg', 'rb') --ngx.print(f:read("*a")) diff --git a/src/ngx_http_lua_module.c b/src/ngx_http_lua_module.c index cab7f39..deccecb 100644 --- a/src/ngx_http_lua_module.c +++ b/src/ngx_http_lua_module.c @@ -1,6 +1,9 @@ /* Copyright (C) Alacner */ #define DDEBUG 1 #include "ddebug.h" +#include "strtok_r.h" + +#define lua_strtok_r(a, b, c) strtok_r((a), (b), (c)) #include #include @@ -44,21 +47,22 @@ static ngx_int_t ngx_set_http_out_header(ngx_http_request_t *r, char *key, char static ngx_int_t ngx_set_http_by_lua(ngx_http_request_t *r); static void log_wrapper(ngx_http_request_t *r, const char *ident, int level, lua_State *L); -static int luaM_print (lua_State *L); -static int luaM_set_header (lua_State *L); +static int luaM_ngx_print (lua_State *L); +static int luaM_ngx_set_header (lua_State *L); +static int luaM_ngx_get (lua_State *L); +static int luaM_ngx_post (lua_State *L); #if 0 -static int luaM_get_get (lua_State *L); +static int luaM_ngx_cookie (lua_State *L); +static int luaM_ngx_set_cookie (lua_State *L); -static int luaM_get_request (lua_State *L); static int luaM_get_post (lua_State *L); static int luaM_get_files (lua_State *L); static int luaM_get_cookie (lua_State *L); static int luaM_set_cookie (lua_State *L); - #endif static int -luaM_print (lua_State *L) { +luaM_ngx_print (lua_State *L) { size_t l = 0; const char *str = luaL_optlstring(L, 1, NULL, &l); @@ -73,7 +77,7 @@ luaM_print (lua_State *L) { } static int -luaM_set_header (lua_State *L) { +luaM_ngx_set_header (lua_State *L) { const char *key = luaL_optstring(L, 1, NULL); const char *value = luaL_optstring(L, 2, NULL); @@ -96,6 +100,53 @@ luaM_set_header (lua_State *L) { return 1; } +static int +luaM_ngx_get (lua_State *L) { + ngx_http_request_t *r; + + lua_getglobal(L, LUA_NGX_REQUEST); + r = lua_touserdata(L, -1); + lua_pop(L, 1); + + if (r == NULL) { + return luaL_error(L, "no request object found"); + } + + lua_newtable(L); + + u_char *variables; + variables = ngx_pnalloc(r->pool, r->args.len+1); + ngx_cpystrn(variables, r->args.data, r->args.len+1); + + char *strtok_buf, *variable, *k, *v; + variable = lua_strtok_r((char *)variables, "&", &strtok_buf); + + while (variable) { + k = lua_strtok_r(variable, "=", &v); + lua_pushstring(L, v); + lua_setfield(L, -2, k); + variable = lua_strtok_r(NULL, "&", &strtok_buf); + } + + return 1; +} + +static int +luaM_ngx_post (lua_State *L) { + ngx_http_request_t *r; + + lua_getglobal(L, LUA_NGX_REQUEST); + r = lua_touserdata(L, -1); + lua_pop(L, 1); + + if (r == NULL) { + return luaL_error(L, "no request object found"); + } + + lua_newtable(L); + return 1; +} + /* Commands */ static ngx_command_t ngx_http_lua_commands[] = { { @@ -225,8 +276,16 @@ ngx_http_lua_create_loc_conf(ngx_conf_t *cf) { } static ngx_int_t ngx_set_http_out_header(ngx_http_request_t *r, char *key, char *value){ + if (strcasecmp("Content-Type", key) == 0) { /* if key: content-type */ + r->headers_out.content_type_len = strlen(key); + r->headers_out.content_type.len = strlen(value); + r->headers_out.content_type.data = (u_char *)value; + r->headers_out.content_type_lowcase = NULL; + return NGX_OK; + } - ngx_table_elt_t *head_type = (ngx_table_elt_t *)ngx_list_push(&r->headers_out.headers); + ngx_table_elt_t *head_type; + head_type = (ngx_table_elt_t *)ngx_list_push(&r->headers_out.headers); if (head_type != NULL) { head_type->hash = 1; head_type->key.len = strlen(key); @@ -242,9 +301,7 @@ static ngx_int_t ngx_set_http_out_header(ngx_http_request_t *r, char *key, char } static ngx_int_t ngx_set_http_by_lua(ngx_http_request_t *r){ - ngx_int_t rc; - ngx_buf_t *b; - ngx_chain_t out; + ngx_http_complex_value_t cv; luaL_Buffer lb; /* for out_buf */ ngx_http_lua_loc_conf_t *llcf; @@ -254,7 +311,7 @@ static ngx_int_t ngx_set_http_by_lua(ngx_http_request_t *r){ lua_pushlightuserdata(L, r); lua_setglobal(L, LUA_NGX_REQUEST); - + /* out buff */ luaL_buffinit(L, &lb); lua_pushlightuserdata(L, &lb); lua_setglobal(L, LUA_NGX_OUT_BUFFER); @@ -265,12 +322,18 @@ static ngx_int_t ngx_set_http_by_lua(ngx_http_request_t *r){ lua_pushnumber(L, ngx_random()); lua_setfield(L, -2, "random"); - lua_pushcfunction(L, luaM_print); + lua_pushcfunction(L, luaM_ngx_print); lua_setfield(L, -2, "print"); - lua_pushcfunction(L, luaM_set_header); + lua_pushcfunction(L, luaM_ngx_set_header); lua_setfield(L, -2, "set_header"); + luaM_ngx_get(L); + lua_setfield(L, -2, "get"); + + luaM_ngx_post(L); + lua_setfield(L, -2, "post"); + /* {{{ ngx.server */ lua_newtable(L); @@ -329,15 +392,16 @@ static ngx_int_t ngx_set_http_by_lua(ngx_http_request_t *r){ // execute lua code if (luaL_dofile(L, (const char *)llcf->file_src.data) != 0) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "runtime error: %s", lua_tostring(L, -1)); lua_pop(L, 1); return NGX_HTTP_INTERNAL_SERVER_ERROR; } luaL_pushresult(&lb); - - const char *out_buf = lua_tostring(L, -1); + + size_t l = 0; + const char *out_buf = lua_tolstring(L, -1, &l); ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "concat all ngx.print data: %s", lua_tostring(L, -1)); @@ -345,46 +409,21 @@ static ngx_int_t ngx_set_http_by_lua(ngx_http_request_t *r){ lua_pop(L, 1); - // buff - b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); - if (b == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - out.buf = b; - out.next = NULL; - - b->pos = (u_char *)out_buf; - b->last = (u_char *)out_buf + strlen(out_buf); - b->memory = 1; - b->last_buf = 1; - r->headers_out.status = NGX_HTTP_OK; - r->headers_out.content_length_n = strlen(out_buf); + ngx_memzero(&cv, sizeof(ngx_http_complex_value_t)); - rc = ngx_http_send_header(r); + cv.value.len = l; + cv.value.data = (u_char *)out_buf; - if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { - return rc; - } - - return ngx_http_output_filter(r, &out); + return ngx_http_send_response(r, NGX_HTTP_OK, NULL, &cv); } static ngx_int_t ngx_http_lua_handler(ngx_http_request_t *r) { - ngx_int_t rc; - if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_POST|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } - rc = ngx_http_discard_request_body(r); - - if (rc != NGX_OK && rc != NGX_AGAIN) { - return rc; - } - if (r->method == NGX_HTTP_HEAD) { r->headers_out.status = NGX_HTTP_OK; return ngx_http_send_header(r); diff --git a/src/strtok_r.c b/src/strtok_r.c new file mode 100644 index 0000000..7519fd1 --- /dev/null +++ b/src/strtok_r.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 1998 Softweyr LLC. All rights reserved. + * + * strtok_r, from Berkeley strtok + * Oct 13, 1998 by Wes Peters + * + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notices, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notices, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * + * This product includes software developed by Softweyr LLC, the + * University of California, Berkeley, and its contributors. + * + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY SOFTWEYR LLC, THE REGENTS 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 SOFTWEYR LLC, THE + * REGENTS, 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. + */ + +#include + +char * +strtok_r(char *s, const char *delim, char **last) +{ + char *spanp; + int c, sc; + char *tok; + + if (s == NULL && (s = *last) == NULL) + { + return NULL; + } + + /* + * Skip (span) leading delimiters (s += strspn(s, delim), sort of). + */ +cont: + c = *s++; + for (spanp = (char *)delim; (sc = *spanp++) != 0; ) + { + if (c == sc) + { + goto cont; + } + } + + if (c == 0) /* no non-delimiter characters */ + { + *last = NULL; + return NULL; + } + tok = s - 1; + + /* + * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). + * Note that delim must have one NUL; we stop if we see that, too. + */ + for (;;) + { + c = *s++; + spanp = (char *)delim; + do + { + if ((sc = *spanp++) == c) + { + if (c == 0) + { + s = NULL; + } + else + { + char *w = s - 1; + *w = '\0'; + } + *last = s; + return tok; + } + } + while (sc != 0); + } + /* NOTREACHED */ +} diff --git a/src/strtok_r.h b/src/strtok_r.h new file mode 100644 index 0000000..e0d72c6 --- /dev/null +++ b/src/strtok_r.h @@ -0,0 +1 @@ +char * php_strtok_r(char *s, const char *delim, char **last);