Skip to content

Commit 2502bdc

Browse files
committed
now we allow boolean and nil values as args to ngx.print/ngx.say; also done the first cut on the ngx.req.get_query_args() API.
1 parent db34dab commit 2502bdc

File tree

7 files changed

+347
-17
lines changed

7 files changed

+347
-17
lines changed

src/ngx_http_lua_hook.c

Lines changed: 189 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,8 @@ ngx_http_lua_ngx_echo(lua_State *L, ngx_flag_t newline)
259259
ngx_int_t rc;
260260
int i;
261261
int nargs;
262+
int type;
263+
const char *msg;
262264

263265
lua_getglobal(L, GLOBALS_SYMBOL_REQUEST);
264266
r = lua_touserdata(L, -1);
@@ -282,9 +284,33 @@ ngx_http_lua_ngx_echo(lua_State *L, ngx_flag_t newline)
282284
size = 0;
283285

284286
for (i = 1; i <= nargs; i++) {
285-
luaL_checkstring(L, i);
286-
lua_tolstring(L, i, &len);
287-
size += len;
287+
type = lua_type(L, i);
288+
switch (type) {
289+
case LUA_TNUMBER:
290+
case LUA_TSTRING:
291+
lua_tolstring(L, i, &len);
292+
size += len;
293+
break;
294+
295+
case LUA_TNIL:
296+
size += sizeof("nil") - 1;
297+
break;
298+
299+
case LUA_TBOOLEAN:
300+
if (lua_toboolean(L, i)) {
301+
size += sizeof("true") - 1;
302+
303+
} else {
304+
size += sizeof("false") - 1;
305+
}
306+
307+
break;
308+
309+
default:
310+
msg = lua_pushfstring(L, "string, number, boolean, or nil "
311+
"expected, got %s", lua_typename(L, type));
312+
return luaL_argerror(L, i, msg);
313+
}
288314
}
289315

290316
if (newline) {
@@ -302,8 +328,43 @@ ngx_http_lua_ngx_echo(lua_State *L, ngx_flag_t newline)
302328
}
303329

304330
for (i = 1; i <= nargs; i++) {
305-
p = lua_tolstring(L, i, &len);
306-
b->last = ngx_copy(b->last, (u_char *) p, len);
331+
type = lua_type(L, i);
332+
switch (type) {
333+
case LUA_TNUMBER:
334+
case LUA_TSTRING:
335+
p = lua_tolstring(L, i, &len);
336+
b->last = ngx_copy(b->last, (u_char *) p, len);
337+
break;
338+
339+
case LUA_TNIL:
340+
*b->last++ = 'n';
341+
*b->last++ = 'i';
342+
*b->last++ = 'l';
343+
break;
344+
345+
case LUA_TBOOLEAN:
346+
if (lua_toboolean(L, i)) {
347+
*b->last++ = 't';
348+
*b->last++ = 'r';
349+
*b->last++ = 'u';
350+
*b->last++ = 'e';
351+
352+
} else {
353+
*b->last++ = 'f';
354+
*b->last++ = 'a';
355+
*b->last++ = 'l';
356+
*b->last++ = 's';
357+
*b->last++ = 'e';
358+
}
359+
360+
break;
361+
362+
default:
363+
/* impossible to reach here */
364+
msg = lua_pushfstring(L, "string, number, boolean, or nil "
365+
"expected, got %s", lua_typename(L, type));
366+
return luaL_argerror(L, i, msg);
367+
}
307368
}
308369

309370
if (newline) {
@@ -2864,3 +2925,126 @@ ngx_http_lua_process_args_option(ngx_http_request_t *r, lua_State *L,
28642925
}
28652926
}
28662927

2928+
2929+
int
2930+
ngx_http_lua_ngx_req_get_query_args(lua_State *L) {
2931+
ngx_http_request_t *r;
2932+
u_char *p, *q, *buf;
2933+
u_char *src, *dst;
2934+
u_char *last;
2935+
unsigned parsing_value;
2936+
size_t len;
2937+
2938+
if (lua_gettop(L) != 0) {
2939+
return luaL_error(L, "expecting 0 arguments but seen %d",
2940+
lua_gettop(L));
2941+
}
2942+
2943+
lua_getglobal(L, GLOBALS_SYMBOL_REQUEST);
2944+
r = lua_touserdata(L, -1);
2945+
lua_pop(L, 1);
2946+
2947+
if (r == NULL) {
2948+
return luaL_error(L, "no request object found");
2949+
}
2950+
2951+
lua_createtable(L, 0, 4);
2952+
2953+
/* we copy r->args over to buf to simplify
2954+
* unescaping query arg keys and values */
2955+
2956+
buf = ngx_palloc(r->pool, r->args.len);
2957+
if (buf == NULL) {
2958+
return luaL_error(L, "out of memory");
2959+
}
2960+
2961+
ngx_memcpy(buf, r->args.data, r->args.len);
2962+
2963+
p = r->args.data;
2964+
last = p + r->args.len;
2965+
2966+
parsing_value = 0;
2967+
q = p;
2968+
2969+
while (p != last) {
2970+
if (*p == '=' && ! parsing_value) {
2971+
/* key data is between p and q */
2972+
2973+
src = q; dst = q;
2974+
2975+
ngx_http_lua_unescape_uri(&dst, &src, p - q,
2976+
NGX_UNESCAPE_URI_COMPONENT);
2977+
2978+
/* push the key */
2979+
lua_pushlstring(L, (char *) q, dst - q);
2980+
2981+
/* skip the current '=' char */
2982+
p++;
2983+
2984+
q = p;
2985+
parsing_value = 1;
2986+
2987+
} else if (*p == '&') {
2988+
/* reached the end of a key or a value, just save it */
2989+
src = q; dst = q;
2990+
2991+
ngx_http_lua_unescape_uri(&dst, &src, p - q,
2992+
NGX_UNESCAPE_URI_COMPONENT);
2993+
2994+
/* push the value or key */
2995+
lua_pushlstring(L, (char *) q, dst - q);
2996+
2997+
/* skip the current '&' char */
2998+
p++;
2999+
3000+
q = p;
3001+
3002+
if (parsing_value) {
3003+
/* end of the current pair's value */
3004+
parsing_value = 0;
3005+
3006+
} else {
3007+
/* the current parsing pair takes no value,
3008+
* just push the value "true" */
3009+
lua_pushboolean(L, 1);
3010+
}
3011+
3012+
(void) lua_tolstring(L, -2, &len);
3013+
3014+
if (len == 0) {
3015+
/* ignore empty string key pairs */
3016+
lua_pop(L, 2);
3017+
3018+
} else {
3019+
lua_settable(L, 1);
3020+
}
3021+
3022+
} else {
3023+
p++;
3024+
}
3025+
}
3026+
3027+
if (p != q) {
3028+
src = q; dst = q;
3029+
3030+
ngx_http_lua_unescape_uri(&dst, &src, p - q,
3031+
NGX_UNESCAPE_URI_COMPONENT);
3032+
3033+
/* push the value or key */
3034+
lua_pushlstring(L, (char *) q, dst - q);
3035+
3036+
if (! parsing_value) {
3037+
lua_pushboolean(L, 1);
3038+
}
3039+
3040+
lua_settable(L, 1);
3041+
}
3042+
3043+
ngx_pfree(r->pool, buf);
3044+
3045+
dd("gettop: %d", lua_gettop(L));
3046+
dd("type: %s", lua_typename(L, lua_type(L, 1)));
3047+
3048+
return 1;
3049+
}
3050+

src/ngx_http_lua_hook.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ int ngx_http_lua_ngx_set(lua_State *L);
5353

5454
int ngx_http_lua_ngx_req_header_clear(lua_State *L);
5555
int ngx_http_lua_ngx_req_header_set(lua_State *L);
56+
int ngx_http_lua_ngx_req_get_query_args(lua_State *L);
5657

5758
int ngx_http_lua_ngx_header_get(lua_State *L);
5859
int ngx_http_lua_ngx_header_set(lua_State *L);

src/ngx_http_lua_util.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,9 @@ init_ngx_lua_globals(lua_State *L)
698698
lua_pushcfunction(L, ngx_http_lua_ngx_req_get_headers);
699699
lua_setfield(L, -2, "get_headers");
700700

701+
lua_pushcfunction(L, ngx_http_lua_ngx_req_get_query_args);
702+
lua_setfield(L, -2, "get_query_args");
703+
701704
lua_setfield(L, -2, "req");
702705

703706
/* }}} */

t/002-content.t

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ status=200 body=hello, world
160160

161161

162162

163-
=== TEST 9: capture non-existed location
163+
ei= TEST 9: capture non-existed location
164164
--- config
165165
location /lua {
166166
content_by_lua 'res = ngx.location.capture("/other"); ngx.print("status=", res.status)';
@@ -186,12 +186,12 @@ res=404
186186
=== TEST 11: nil is "nil"
187187
--- config
188188
location /lua {
189-
content_by_lua 'ngx.print(nil)';
189+
content_by_lua 'ngx.say(nil)';
190190
}
191191
--- request
192192
GET /lua
193-
--- response_body_like: 500 Internal Server Error
194-
--- error_code: 500
193+
--- response_body
194+
nil
195195

196196

197197

t/023-rewrite/sanity.t

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,13 +200,13 @@ res=404
200200
=== TEST 11: nil is "nil"
201201
--- config
202202
location /lua {
203-
rewrite_by_lua 'ngx.print(nil)';
204-
content_by_lua 'ngx.exit(ngx.OK)';
203+
rewrite_by_lua 'ngx.say(nil)';
204+
content_by_lua return;
205205
}
206206
--- request
207207
GET /lua
208-
--- response_body_like: 500 Internal Server Error
209-
--- error_code: 500
208+
--- response_body
209+
nil
210210

211211

212212

t/024-access/sanity.t

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,13 +200,13 @@ res=404
200200
=== TEST 11: nil is "nil"
201201
--- config
202202
location /lua {
203-
access_by_lua 'ngx.print(nil)';
204-
content_by_lua 'ngx.exit(ngx.OK)';
203+
access_by_lua 'ngx.say(nil)';
204+
content_by_lua return;
205205
}
206206
--- request
207207
GET /lua
208-
--- response_body_like: 500 Internal Server Error
209-
--- error_code: 500
208+
--- response_body
209+
nil
210210

211211

212212

0 commit comments

Comments
 (0)