6
6
#include "ngx_http_lua_control.h"
7
7
#include "ngx_http_lua_util.h"
8
#include "ngx_http_lua_coroutine.h"
10
11
static int ngx_http_lua_ngx_exec(lua_State *L);
11
12
static int ngx_http_lua_ngx_redirect(lua_State *L);
12
13
static int ngx_http_lua_ngx_exit(lua_State *L);
14
static int ngx_http_lua_on_abort(lua_State *L);
16
18
ngx_http_lua_inject_control_api(ngx_log_t *log, lua_State *L)
22
22
lua_pushcfunction(L, ngx_http_lua_ngx_redirect);
23
lua_setfield(L, -2, "_redirect");
27
const char buf[] = "ngx._redirect(...) ngx._check_aborted()";
29
rc = luaL_loadbuffer(L, buf, sizeof(buf) - 1, "ngx.redirect");
33
ngx_log_error(NGX_LOG_CRIT, log, 0,
34
"failed to load Lua code for ngx.redirect(): %i",
38
lua_setfield(L, -2, "redirect");
23
lua_setfield(L, -2, "redirect");
44
27
lua_pushcfunction(L, ngx_http_lua_ngx_exec);
45
lua_setfield(L, -2, "_exec");
49
const char buf[] = "ngx._exec(...) ngx._check_aborted()";
51
rc = luaL_loadbuffer(L, buf, sizeof(buf) - 1, "ngx.exec");
55
ngx_log_error(NGX_LOG_CRIT, log, 0,
56
"failed to load Lua code for ngx.exec(): %i",
60
lua_setfield(L, -2, "exec");
28
lua_setfield(L, -2, "exec");
64
30
lua_pushcfunction(L, ngx_http_lua_ngx_exit);
65
31
lua_setfield(L, -2, "throw_error"); /* deprecated */
69
35
lua_pushcfunction(L, ngx_http_lua_ngx_exit);
70
lua_setfield(L, -2, "_exit");
74
const char buf[] = "ngx._exit(...) ngx._check_aborted()";
76
rc = luaL_loadbuffer(L, buf, sizeof(buf) - 1, "ngx.exit");
80
ngx_log_error(NGX_LOG_CRIT, log, 0,
81
"failed to load Lua code for ngx.exit(): %i",
85
lua_setfield(L, -2, "exit");
36
lua_setfield(L, -2, "exit");
40
lua_pushcfunction(L, ngx_http_lua_on_abort);
41
lua_setfield(L, -2, "on_abort");
111
lua_getglobal(L, GLOBALS_SYMBOL_REQUEST);
65
lua_pushlightuserdata(L, &ngx_http_lua_request_key);
66
lua_rawget(L, LUA_GLOBALSINDEX);
112
67
r = lua_touserdata(L, -1);
139
94
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
96
return luaL_error(L, "no ctx found");
99
ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
100
| NGX_HTTP_LUA_CONTEXT_ACCESS
101
| NGX_HTTP_LUA_CONTEXT_CONTENT);
103
ngx_http_lua_check_if_abortable(L, ctx);
141
105
if (ngx_http_parse_unsafe_uri(r, &uri, &args, &flags)
248
217
rc = NGX_HTTP_MOVED_TEMPORARILY;
251
lua_getglobal(L, GLOBALS_SYMBOL_REQUEST);
220
lua_pushlightuserdata(L, &ngx_http_lua_request_key);
221
lua_rawget(L, LUA_GLOBALSINDEX);
252
222
r = lua_touserdata(L, -1);
261
231
return luaL_error(L, "no request ctx found");
234
ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
235
| NGX_HTTP_LUA_CONTEXT_ACCESS
236
| NGX_HTTP_LUA_CONTEXT_CONTENT);
238
ngx_http_lua_check_if_abortable(L, ctx);
264
240
if (ctx->headers_sent) {
265
241
return luaL_error(L, "attempt to call ngx.redirect after sending out "
317
293
return luaL_error(L, "expecting one argument");
320
lua_getglobal(L, GLOBALS_SYMBOL_REQUEST);
296
lua_pushlightuserdata(L, &ngx_http_lua_request_key);
297
lua_rawget(L, LUA_GLOBALSINDEX);
321
298
r = lua_touserdata(L, -1);
330
307
return luaL_error(L, "no request ctx found");
310
ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
311
| NGX_HTTP_LUA_CONTEXT_ACCESS
312
| NGX_HTTP_LUA_CONTEXT_CONTENT);
333
314
rc = (ngx_int_t) luaL_checkinteger(L, 1);
335
if (rc >= NGX_HTTP_SPECIAL_RESPONSE && ctx->headers_sent) {
336
return luaL_error(L, "attempt to call ngx.exit after sending "
318
&& rc != NGX_HTTP_CLOSE
319
&& rc != NGX_HTTP_REQUEST_TIME_OUT
320
&& rc != NGX_HTTP_CLIENT_CLOSED_REQUEST)
322
return luaL_error(L, "attempt to abort with pending subrequests");
325
if (ctx->headers_sent
326
&& rc >= NGX_HTTP_SPECIAL_RESPONSE
327
&& rc != NGX_HTTP_REQUEST_TIME_OUT
328
&& rc != NGX_HTTP_CLIENT_CLOSED_REQUEST
329
&& rc != NGX_HTTP_CLOSE)
331
if (rc != (ngx_int_t) r->headers_out.status) {
332
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "attempt to "
333
"set status %i via ngx.exit after sending out the "
334
"response status %ui", rc, r->headers_out.status);
340
340
ctx->exit_code = rc;
347
347
return lua_yield(L, 0);
352
ngx_http_lua_on_abort(lua_State *L)
354
ngx_http_request_t *r;
355
ngx_http_lua_ctx_t *ctx;
356
ngx_http_lua_co_ctx_t *coctx = NULL;
357
ngx_http_lua_loc_conf_t *llcf;
359
lua_pushlightuserdata(L, &ngx_http_lua_request_key);
360
lua_rawget(L, LUA_GLOBALSINDEX);
361
r = lua_touserdata(L, -1);
365
return luaL_error(L, "no request found");
368
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
370
return luaL_error(L, "no request ctx found");
373
if (ctx->on_abort_co_ctx) {
375
lua_pushliteral(L, "duplicate call");
379
llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module);
380
if (!llcf->check_client_abort) {
382
lua_pushliteral(L, "lua_check_client_abort is off");
386
ngx_http_lua_coroutine_create_helper(L, r, ctx, &coctx);
388
lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key);
389
lua_rawget(L, LUA_REGISTRYINDEX);
390
lua_pushvalue(L, -2);
392
dd("on_wait thread 1: %p", lua_tothread(L, -1));
394
coctx->co_ref = luaL_ref(L, -2);
397
coctx->is_uthread = 1;
398
ctx->on_abort_co_ctx = coctx;
400
dd("on_wait thread 2: %p", coctx->co);
402
coctx->co_status = NGX_HTTP_LUA_CO_SUSPENDED;
403
coctx->parent_co_ctx = ctx->cur_co_ctx;
405
lua_pushinteger(L, 1);