static ngx_int_t ngx_http_lua_set_by_lua_init(ngx_http_request_t *r) { lua_State *L; ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { ctx = ngx_http_lua_create_ctx(r); if (ctx == NULL) { return NGX_ERROR; } } else { L = ngx_http_lua_get_lua_vm(r, ctx); ngx_http_lua_reset_ctx(r, L, ctx); } if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_http_lua_request_cleanup_handler; cln->data = ctx; ctx->cleanup = &cln->handler; } ctx->context = NGX_HTTP_LUA_CONTEXT_SET; return NGX_OK; }
static ngx_int_t ngx_http_lua_rewrite_by_chunk(lua_State *L, ngx_http_request_t *r) { int co_ref; lua_State *co; ngx_int_t rc; ngx_connection_t *c; ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; ngx_http_lua_loc_conf_t *llcf; /* {{{ new coroutine to handle request */ co = ngx_http_lua_new_thread(r, L, &co_ref); if (co == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "lua: failed to create new coroutine to handle request"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* move code closure to new coroutine */ lua_xmove(L, co, 1); /* set closure's env table to new coroutine's globals table */ lua_pushvalue(co, LUA_GLOBALSINDEX); lua_setfenv(co, -2); /* save nginx request in coroutine globals table */ lua_pushlightuserdata(co, &ngx_http_lua_request_key); lua_pushlightuserdata(co, r); lua_rawset(co, LUA_GLOBALSINDEX); /* }}} */ /* {{{ initialize request context */ ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); dd("ctx = %p", ctx); if (ctx == NULL) { return NGX_ERROR; } ngx_http_lua_reset_ctx(r, L, ctx); ctx->entered_rewrite_phase = 1; ctx->cur_co_ctx = &ctx->entry_co_ctx; ctx->cur_co_ctx->co = co; ctx->cur_co_ctx->co_ref = co_ref; /* }}} */ /* {{{ register request cleanup hooks */ if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cln->handler = ngx_http_lua_request_cleanup; cln->data = r; ctx->cleanup = &cln->handler; } /* }}} */ ctx->context = NGX_HTTP_LUA_CONTEXT_REWRITE; llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); if (llcf->check_client_abort) { r->read_event_handler = ngx_http_lua_rd_check_broken_connection; } else { r->read_event_handler = ngx_http_block_reading; } rc = ngx_http_lua_run_thread(L, r, ctx, 0); if (rc == NGX_ERROR || rc > NGX_OK) { return rc; } c = r->connection; if (rc == NGX_AGAIN) { rc = ngx_http_lua_run_posted_threads(c, L, r, ctx); if (rc == NGX_OK) { return NGX_DECLINED; } return rc; } if (rc == NGX_DONE) { ngx_http_finalize_request(r, NGX_DONE); rc = ngx_http_lua_run_posted_threads(c, L, r, ctx); if (rc == NGX_OK) { return NGX_DECLINED; } return rc; } return NGX_DECLINED; }
static ngx_int_t ngx_http_lua_access_by_chunk(lua_State *L, ngx_http_request_t *r) { int cc_ref; ngx_int_t rc; lua_State *cc; ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; /* {{{ new coroutine to handle request */ cc = ngx_http_lua_new_thread(r, L, &cc_ref); if (cc == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "lua: failed to create new coroutine " "to handle request"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* move code closure to new coroutine */ lua_xmove(L, cc, 1); /* set closure's env table to new coroutine's globals table */ lua_pushvalue(cc, LUA_GLOBALSINDEX); lua_setfenv(cc, -2); /* save reference of code to ease forcing stopping */ lua_pushvalue(cc, -1); lua_setglobal(cc, GLOBALS_SYMBOL_RUNCODE); /* save nginx request in coroutine globals table */ lua_pushlightuserdata(cc, r); lua_setglobal(cc, GLOBALS_SYMBOL_REQUEST); /* }}} */ /* {{{ initialize request context */ ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); dd("ctx = %p", ctx); if (ctx == NULL) { return NGX_ERROR; } ngx_http_lua_reset_ctx(r, L, ctx); ctx->entered_access_phase = 1; ctx->cc = cc; ctx->cc_ref = cc_ref; /* }}} */ /* {{{ register request cleanup hooks */ if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cln->handler = ngx_http_lua_request_cleanup; cln->data = r; ctx->cleanup = &cln->handler; } /* }}} */ rc = ngx_http_lua_run_thread(L, r, ctx, 0); dd("returned %d", (int) rc); if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } if (rc == NGX_AGAIN) { return NGX_DONE; } if (rc == NGX_DONE) { ngx_http_finalize_request(r, NGX_DONE); return NGX_DONE; } if (rc >= NGX_HTTP_OK && rc < NGX_HTTP_SPECIAL_RESPONSE) { return rc; } if (rc == NGX_OK) { return NGX_OK; } return NGX_DECLINED; }
static ngx_int_t ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) { lua_State *L; ngx_int_t rc; ngx_http_request_t *r; ngx_http_lua_ctx_t *ctx; ngx_http_lua_srv_conf_t *lscf; ngx_http_lua_main_conf_t *lmcf; ngx_http_lua_balancer_peer_data_t *bp = data; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "lua balancer peer, tries: %ui", pc->tries); lscf = bp->conf; r = bp->request; ngx_http_lua_assert(lscf->balancer.handler && r); ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { ctx = ngx_http_lua_create_ctx(r); if (ctx == NULL) { return NGX_ERROR; } L = ngx_http_lua_get_lua_vm(r, ctx); } else { L = ngx_http_lua_get_lua_vm(r, ctx); dd("reset ctx"); ngx_http_lua_reset_ctx(r, L, ctx); } ctx->context = NGX_HTTP_LUA_CONTEXT_BALANCER; bp->sockaddr = NULL; bp->socklen = 0; bp->more_tries = 0; bp->total_tries++; lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); /* balancer_by_lua does not support yielding and * there cannot be any conflicts among concurrent requests, * thus it is safe to store the peer data in the main conf. */ lmcf->balancer_peer_data = bp; rc = lscf->balancer.handler(r, lscf, L); if (rc == NGX_ERROR) { return NGX_ERROR; } if (ctx->exited && ctx->exit_code != NGX_OK) { rc = ctx->exit_code; if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED #ifdef HAVE_BALANCER_STATUS_CODE_PATCH || rc >= NGX_HTTP_SPECIAL_RESPONSE #endif ) { return rc; } if (rc > NGX_OK) { return NGX_ERROR; } } if (bp->sockaddr && bp->socklen) { pc->sockaddr = bp->sockaddr; pc->socklen = bp->socklen; pc->cached = 0; pc->connection = NULL; pc->name = bp->host; bp->rrp.peers->single = 0; if (bp->more_tries) { r->upstream->peer.tries += bp->more_tries; } dd("tries: %d", (int) r->upstream->peer.tries); return NGX_OK; } return ngx_http_upstream_get_round_robin_peer(pc, &bp->rrp); }
ngx_int_t ngx_http_lua_content_by_chunk(lua_State *L, ngx_http_request_t *r) { int cc_ref; lua_State *cc; ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; dd("content by chunk"); ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_lua_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } dd("setting new ctx, ctx = %p", ctx); ctx->cc_ref = LUA_NOREF; ctx->ctx_ref = LUA_NOREF; ngx_http_set_ctx(r, ctx, ngx_http_lua_module); } else { dd("reset ctx"); ngx_http_lua_reset_ctx(r, L, ctx); } ctx->entered_content_phase = 1; /* {{{ new coroutine to handle request */ cc = ngx_http_lua_new_thread(r, L, &cc_ref); if (cc == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "(lua-content-by-chunk) failed to create new coroutine " "to handle request"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* move code closure to new coroutine */ lua_xmove(L, cc, 1); /* set closure's env table to new coroutine's globals table */ lua_pushvalue(cc, LUA_GLOBALSINDEX); lua_setfenv(cc, -2); /* save reference of code to ease forcing stopping */ lua_pushvalue(cc, -1); lua_setglobal(cc, GLOBALS_SYMBOL_RUNCODE); /* save nginx request in coroutine globals table */ lua_pushlightuserdata(cc, r); lua_setglobal(cc, GLOBALS_SYMBOL_REQUEST); /* }}} */ ctx->cc = cc; ctx->cc_ref = cc_ref; /* {{{ register request cleanup hooks */ if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cln->handler = ngx_http_lua_request_cleanup; cln->data = r; ctx->cleanup = &cln->handler; } /* }}} */ return ngx_http_lua_run_thread(L, r, ctx, 0); }
ngx_int_t ngx_http_lua_set_by_chunk(lua_State *L, ngx_http_request_t *r, ngx_str_t *val, ngx_http_variable_value_t *args, size_t nargs, ngx_str_t *script) { size_t i; ngx_int_t rc; u_char *err_msg; size_t len; u_char *data; #if (NGX_PCRE) ngx_pool_t *old_pool; #endif ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; dd("nargs: %d", (int) nargs); ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { ctx = ngx_http_lua_create_ctx(r); if (ctx == NULL) { return NGX_ERROR; } } else { ngx_http_lua_reset_ctx(r, L, ctx); } if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_http_lua_request_cleanup; cln->data = r; ctx->cleanup = &cln->handler; } ctx->context = NGX_HTTP_LUA_CONTEXT_SET; dd("set Lua VM panic handler"); lua_atpanic(L, ngx_http_lua_atpanic); NGX_LUA_EXCEPTION_TRY { dd("initialize nginx context in Lua VM, code chunk at " "stack top sp = 1"); ngx_http_lua_set_by_lua_env(L, r, nargs, args); /* passing directive arguments to the user code */ for (i = 0; i < nargs; i++) { lua_pushlstring(L, (const char *) args[i].data, args[i].len); } #if (NGX_PCRE) /* XXX: work-around to nginx regex subsystem */ old_pool = ngx_http_lua_pcre_malloc_init(r->pool); #endif lua_pushcfunction(L, ngx_http_lua_traceback); lua_insert(L, 1); /* put it under chunk and args */ dd("protected call user code"); rc = lua_pcall(L, nargs, 1, 1); dd("after protected call user code"); lua_remove(L, 1); /* remove traceback function */ #if (NGX_PCRE) /* XXX: work-around to nginx regex subsystem */ ngx_http_lua_pcre_malloc_done(old_pool); #endif if (rc != 0) { /* error occured when running loaded code */ err_msg = (u_char *) lua_tolstring(L, -1, &len); if (err_msg == NULL) { err_msg = (u_char *) "unknown reason"; len = sizeof("unknown reason") - 1; } ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to run set_by_lua*: %*s", len, err_msg); lua_settop(L, 0); /* clear remaining elems on stack */ return NGX_ERROR; } data = (u_char *) lua_tolstring(L, -1, &len); if (data) { val->data = ngx_palloc(r->pool, len); if (val->data == NULL) { return NGX_ERROR; } ngx_memcpy(val->data, data, len); val->len = len; } else { val->data = NULL; val->len = 0; } } NGX_LUA_EXCEPTION_CATCH { dd("nginx execution restored"); return NGX_ERROR; } /* clear Lua stack */ lua_settop(L, 0); return NGX_OK; }
/* initialize lua coroutine for caching new SSL session */ static ngx_int_t ngx_http_lua_ssl_sess_store_by_chunk(lua_State *L, ngx_http_request_t *r) { size_t len; u_char *err_msg; ngx_int_t rc; ngx_http_lua_ctx_t *ctx; ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { ctx = ngx_http_lua_create_ctx(r); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } } else { dd("reset ctx"); ngx_http_lua_reset_ctx(r, L, ctx); } ctx->entered_content_phase = 1; ctx->context = NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE; /* init nginx context in Lua VM */ ngx_http_lua_set_req(L, r); ngx_http_lua_create_new_globals_table(L, 0 /* narr */, 1 /* nrec */); /* {{{ make new env inheriting main thread's globals table */ lua_createtable(L, 0, 1 /* nrec */); /* the metatable for the new env */ ngx_http_lua_get_globals_table(L); lua_setfield(L, -2, "__index"); lua_setmetatable(L, -2); /* setmetatable({}, {__index = _G}) */ /* }}} */ lua_setfenv(L, -2); /* set new running env for the code closure */ lua_pushcfunction(L, ngx_http_lua_traceback); lua_insert(L, 1); /* put it under chunk and args */ /* protected call user code */ rc = lua_pcall(L, 0, 1, 1); lua_remove(L, 1); /* remove traceback function */ dd("rc == %d", (int) rc); if (rc != 0) { /* error occured when running loaded code */ err_msg = (u_char *) lua_tolstring(L, -1, &len); if (err_msg == NULL) { err_msg = (u_char *) "unknown reason"; len = sizeof("unknown reason") - 1; } ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to run session_store_by_lua*: %*s", len, err_msg); lua_settop(L, 0); /* clear remaining elems on stack */ ngx_http_lua_finalize_request(r, rc); return NGX_ERROR; } lua_settop(L, 0); /* clear remaining elems on stack */ ngx_http_lua_finalize_request(r, rc); return rc; }
ngx_int_t ngx_http_lua_content_by_chunk(lua_State *L, ngx_http_request_t *r) { int co_ref; ngx_int_t rc; lua_State *co; ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; dd("content by chunk"); ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { ctx = ngx_http_lua_create_ctx(r); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } } else { dd("reset ctx"); ngx_http_lua_reset_ctx(r, L, ctx); } ctx->entered_content_phase = 1; /* {{{ new coroutine to handle request */ co = ngx_http_lua_new_thread(r, L, &co_ref); if (co == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "lua: failed to create new coroutine to handle request"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* move code closure to new coroutine */ lua_xmove(L, co, 1); /* set closure's env table to new coroutine's globals table */ lua_pushvalue(co, LUA_GLOBALSINDEX); lua_setfenv(co, -2); /* save nginx request in coroutine globals table */ lua_pushlightuserdata(co, &ngx_http_lua_request_key); lua_pushlightuserdata(co, r); lua_rawset(co, LUA_GLOBALSINDEX); /* }}} */ ctx->cur_co_ctx = &ctx->entry_co_ctx; ctx->cur_co_ctx->co = co; ctx->cur_co_ctx->co_ref = co_ref; /* {{{ register request cleanup hooks */ if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cln->handler = ngx_http_lua_request_cleanup; cln->data = r; ctx->cleanup = &cln->handler; } /* }}} */ ctx->context = NGX_HTTP_LUA_CONTEXT_CONTENT; rc = ngx_http_lua_run_thread(L, r, ctx, 0); if (rc == NGX_ERROR || rc >= NGX_OK) { return rc; } if (rc == NGX_AGAIN) { return ngx_http_lua_content_run_posted_threads(L, r, ctx, 0); } if (rc == NGX_DONE) { return ngx_http_lua_content_run_posted_threads(L, r, ctx, 1); } return NGX_OK; }
ngx_int_t ngx_http_lua_content_by_chunk(lua_State *L, ngx_http_request_t *r) { int co_ref; ngx_int_t rc; lua_State *co; ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; ngx_http_lua_loc_conf_t *llcf; dd("content by chunk"); ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { ctx = ngx_http_lua_create_ctx(r); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } } else { dd("reset ctx"); ngx_http_lua_reset_ctx(r, L, ctx); } ctx->entered_content_phase = 1; /* {{{ new coroutine to handle request */ co = ngx_http_lua_new_thread(r, L, &co_ref); if (co == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "lua: failed to create new coroutine to handle request"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* move code closure to new coroutine */ lua_xmove(L, co, 1); /* set closure's env table to new coroutine's globals table */ ngx_http_lua_get_globals_table(co); lua_setfenv(co, -2); /* save nginx request in coroutine globals table */ ngx_http_lua_set_req(co, r); ctx->cur_co_ctx = &ctx->entry_co_ctx; ctx->cur_co_ctx->co = co; ctx->cur_co_ctx->co_ref = co_ref; #ifdef ngx_http_lua_assert ctx->cur_co_ctx->co_top = 1; #endif /* {{{ register request cleanup hooks */ if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cln->handler = ngx_http_lua_request_cleanup_handler; cln->data = ctx; ctx->cleanup = &cln->handler; } /* }}} */ ctx->context = NGX_HTTP_LUA_CONTEXT_CONTENT; llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); if (llcf->check_client_abort) { r->read_event_handler = ngx_http_lua_rd_check_broken_connection; } else { r->read_event_handler = ngx_http_block_reading; } rc = ngx_http_lua_run_thread(L, r, ctx, 0); if (rc == NGX_ERROR || rc >= NGX_OK) { return rc; } if (rc == NGX_AGAIN) { return ngx_http_lua_content_run_posted_threads(L, r, ctx, 0); } if (rc == NGX_DONE) { return ngx_http_lua_content_run_posted_threads(L, r, ctx, 1); } return NGX_OK; }
/* initialize lua coroutine for fetching cached session */ static ngx_int_t ngx_http_lua_ssl_sess_fetch_by_chunk(lua_State *L, ngx_http_request_t *r) { int co_ref; ngx_int_t rc; lua_State *co; ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { ctx = ngx_http_lua_create_ctx(r); if (ctx == NULL) { rc = NGX_ERROR; ngx_http_lua_finalize_request(r, rc); return rc; } } else { dd("reset ctx"); ngx_http_lua_reset_ctx(r, L, ctx); } ctx->entered_content_phase = 1; /* {{{ new coroutine to handle request */ co = ngx_http_lua_new_thread(r, L, &co_ref); if (co == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "lua: failed to create new coroutine to handle request"); rc = NGX_ERROR; ngx_http_lua_finalize_request(r, rc); return rc; } /* move code closure to new coroutine */ lua_xmove(L, co, 1); /* set closure's env table to new coroutine's globals table */ ngx_http_lua_get_globals_table(co); lua_setfenv(co, -2); /* save nginx request in coroutine globals table */ ngx_http_lua_set_req(co, r); ctx->cur_co_ctx = &ctx->entry_co_ctx; ctx->cur_co_ctx->co = co; ctx->cur_co_ctx->co_ref = co_ref; #ifdef NGX_LUA_USE_ASSERT ctx->cur_co_ctx->co_top = 1; #endif /* register request cleanup hooks */ if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { rc = NGX_ERROR; ngx_http_lua_finalize_request(r, rc); return rc; } cln->handler = ngx_http_lua_request_cleanup_handler; cln->data = ctx; ctx->cleanup = &cln->handler; } ctx->context = NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH; rc = ngx_http_lua_run_thread(L, r, ctx, 0); if (rc == NGX_ERROR || rc >= NGX_OK) { /* do nothing */ } else if (rc == NGX_AGAIN) { rc = ngx_http_lua_content_run_posted_threads(L, r, ctx, 0); } else if (rc == NGX_DONE) { rc = ngx_http_lua_content_run_posted_threads(L, r, ctx, 1); } else { rc = NGX_OK; } ngx_http_lua_finalize_request(r, rc); return rc; }
static ngx_int_t ngx_http_lua_rewrite_by_chunk(lua_State *L, ngx_http_request_t *r) { int co_ref; lua_State *co; ngx_int_t rc; ngx_connection_t *c; ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; ngx_http_lua_loc_conf_t *llcf; /* {{{ new coroutine to handle request */ co = ngx_http_lua_new_thread(r, L, &co_ref); if (co == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "lua: failed to create new coroutine to handle request"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* move code closure to new coroutine */ lua_xmove(L, co, 1); /* set closure's env table to new coroutine's globals table */ ngx_http_lua_get_globals_table(co); lua_setfenv(co, -2); /* save nginx request in coroutine globals table */ ngx_http_lua_set_req(co, r); /* {{{ initialize request context */ ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); dd("ctx = %p", ctx); if (ctx == NULL) { return NGX_ERROR; } ngx_http_lua_reset_ctx(r, L, ctx); ctx->entered_rewrite_phase = 1; ctx->cur_co_ctx = &ctx->entry_co_ctx; ctx->cur_co_ctx->co = co; ctx->cur_co_ctx->co_ref = co_ref; #ifdef NGX_LUA_USE_ASSERT ctx->cur_co_ctx->co_top = 1; #endif /* }}} */ /* {{{ register request cleanup hooks */ if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cln->handler = ngx_http_lua_request_cleanup_handler; cln->data = ctx; ctx->cleanup = &cln->handler; } /* }}} */ ctx->context = NGX_HTTP_LUA_CONTEXT_REWRITE; llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); if (llcf->check_client_abort) { r->read_event_handler = ngx_http_lua_rd_check_broken_connection; } else { r->read_event_handler = ngx_http_block_reading; } rc = ngx_http_lua_run_thread(L, r, ctx, 0); if (rc == NGX_ERROR || rc > NGX_OK) { return rc; } c = r->connection; if (rc == NGX_AGAIN) { rc = ngx_http_lua_run_posted_threads(c, L, r, ctx); } else if (rc == NGX_DONE) { ngx_http_lua_finalize_request(r, NGX_DONE); rc = ngx_http_lua_run_posted_threads(c, L, r, ctx); } if (rc == NGX_OK || rc == NGX_DECLINED) { if (r->header_sent) { dd("header already sent"); /* response header was already generated in access_by_lua*, * so it is no longer safe to proceed to later phases * which may generate responses again */ if (!ctx->eof) { dd("eof not yet sent"); rc = ngx_http_lua_send_chain_link(r, ctx, NULL /* indicate last_buf */); if (rc == NGX_ERROR || rc > NGX_OK) { return rc; } } return NGX_HTTP_OK; } return NGX_DECLINED; } return rc; }
ngx_int_t ngx_http_lua_set_by_chunk(lua_State *L, ngx_http_request_t *r, ngx_str_t *val, ngx_http_variable_value_t *args, size_t nargs, ngx_str_t *script) { size_t i; ngx_int_t rc; u_char *err_msg; size_t rlen; u_char *rdata; #if (NGX_PCRE) ngx_pool_t *old_pool; #endif ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; dd("nargs: %d", (int) nargs); ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_lua_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } dd("setting new ctx: ctx = %p", ctx); ctx->cc_ref = LUA_NOREF; ctx->ctx_ref = LUA_NOREF; ngx_http_set_ctx(r, ctx, ngx_http_lua_module); } else { ngx_http_lua_reset_ctx(r, L, ctx); } if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_http_lua_request_cleanup; cln->data = r; ctx->cleanup = &cln->handler; } /* set Lua VM panic handler */ lua_atpanic(L, ngx_http_lua_atpanic); /* initialize nginx context in Lua VM, code chunk at stack top sp = 1 */ ngx_http_lua_set_by_lua_env(L, r, nargs, args); /* passing directive arguments to the user code */ for (i = 0; i < nargs; i++) { lua_pushlstring(L, (const char *) args[i].data, args[i].len); } #if (NGX_PCRE) /* XXX: work-around to nginx regex subsystem */ old_pool = ngx_http_lua_pcre_malloc_init(r->pool); #endif /* protected call user code */ rc = lua_pcall(L, nargs, 1, 0); #if (NGX_PCRE) /* XXX: work-around to nginx regex subsystem */ ngx_http_lua_pcre_malloc_done(old_pool); #endif if (rc != 0) { /* error occured when running loaded code */ err_msg = (u_char *) lua_tostring(L, -1); if (err_msg != NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "(lua-error) %s", err_msg); lua_settop(L, 0); /* clear remaining elems on stack */ } return NGX_ERROR; } NGX_LUA_EXCEPTION_TRY { rdata = (u_char *) lua_tolstring(L, -1, &rlen); if (rdata) { val->data = ngx_pcalloc(r->pool, rlen); if (val->data == NULL) { return NGX_ERROR; } ngx_memcpy(val->data, rdata, rlen); val->len = rlen; } else { val->data = NULL; val->len = 0; } } NGX_LUA_EXCEPTION_CATCH { dd("nginx execution restored"); } /* clear Lua stack */ lua_settop(L, 0); return NGX_OK; }