LCOV - code coverage report
Current view: top level - home/build/openresty-1.13.6.1/build/ngx_lua-0.10.11/src - ngx_http_lua_output.c (source / functions) Hit Total Coverage
Test: coverage ngix Lines: 53 379 14.0 %
Date: 2020-03-03 04:25:50 Functions: 3 11 27.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #ifndef DDEBUG
       2             : #define DDEBUG 0
       3             : #endif
       4             : #include "ddebug.h"
       5             : 
       6             : 
       7             : #include "ngx_http_lua_output.h"
       8             : #include "ngx_http_lua_util.h"
       9             : #include "ngx_http_lua_contentby.h"
      10             : #include <math.h>
      11             : 
      12             : 
      13             : static int ngx_http_lua_ngx_say(lua_State *L);
      14             : static int ngx_http_lua_ngx_print(lua_State *L);
      15             : static int ngx_http_lua_ngx_flush(lua_State *L);
      16             : static int ngx_http_lua_ngx_eof(lua_State *L);
      17             : static int ngx_http_lua_ngx_send_headers(lua_State *L);
      18             : static int ngx_http_lua_ngx_echo(lua_State *L, unsigned newline);
      19             : static void ngx_http_lua_flush_cleanup(void *data);
      20             : 
      21             : 
      22             : static int
      23           0 : ngx_http_lua_ngx_print(lua_State *L)
      24             : {
      25             :     dd("calling lua print");
      26           0 :     return ngx_http_lua_ngx_echo(L, 0);
      27             : }
      28             : 
      29             : 
      30             : static int
      31           1 : ngx_http_lua_ngx_say(lua_State *L)
      32             : {
      33             :     dd("calling");
      34           1 :     return ngx_http_lua_ngx_echo(L, 1);
      35             : }
      36             : 
      37             : 
      38             : static int
      39           1 : ngx_http_lua_ngx_echo(lua_State *L, unsigned newline)
      40             : {
      41             :     ngx_http_request_t          *r;
      42             :     ngx_http_lua_ctx_t          *ctx;
      43             :     const char                  *p;
      44             :     size_t                       len;
      45             :     size_t                       size;
      46             :     ngx_buf_t                   *b;
      47             :     ngx_chain_t                 *cl;
      48             :     ngx_int_t                    rc;
      49             :     int                          i;
      50             :     int                          nargs;
      51             :     int                          type;
      52             :     const char                  *msg;
      53             : 
      54           1 :     r = ngx_http_lua_get_req(L);
      55           1 :     if (r == NULL) {
      56           0 :         return luaL_error(L, "no request object found");
      57             :     }
      58             : 
      59           1 :     ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
      60             : 
      61           1 :     if (ctx == NULL) {
      62           0 :         return luaL_error(L, "no request ctx found");
      63             :     }
      64             : 
      65           1 :     ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
      66             :                                | NGX_HTTP_LUA_CONTEXT_ACCESS
      67             :                                | NGX_HTTP_LUA_CONTEXT_CONTENT);
      68             : 
      69           1 :     if (ctx->acquired_raw_req_socket) {
      70           0 :         lua_pushnil(L);
      71           0 :         lua_pushliteral(L, "raw request socket acquired");
      72           0 :         return 2;
      73             :     }
      74             : 
      75           1 :     if (r->header_only) {
      76           0 :         lua_pushnil(L);
      77           0 :         lua_pushliteral(L, "header only");
      78           0 :         return 2;
      79             :     }
      80             : 
      81           1 :     if (ctx->eof) {
      82           0 :         lua_pushnil(L);
      83           0 :         lua_pushliteral(L, "seen eof");
      84           0 :         return 2;
      85             :     }
      86             : 
      87           1 :     nargs = lua_gettop(L);
      88           1 :     size = 0;
      89             : 
      90           2 :     for (i = 1; i <= nargs; i++) {
      91             : 
      92           1 :         type = lua_type(L, i);
      93             : 
      94           1 :         switch (type) {
      95           1 :             case LUA_TNUMBER:
      96             :             case LUA_TSTRING:
      97             : 
      98           1 :                 lua_tolstring(L, i, &len);
      99           1 :                 size += len;
     100           1 :                 break;
     101             : 
     102           0 :             case LUA_TNIL:
     103             : 
     104           0 :                 size += sizeof("nil") - 1;
     105           0 :                 break;
     106             : 
     107           0 :             case LUA_TBOOLEAN:
     108             : 
     109           0 :                 if (lua_toboolean(L, i)) {
     110           0 :                     size += sizeof("true") - 1;
     111             : 
     112             :                 } else {
     113           0 :                     size += sizeof("false") - 1;
     114             :                 }
     115             : 
     116           0 :                 break;
     117             : 
     118           0 :             case LUA_TTABLE:
     119             : 
     120           0 :                 size += ngx_http_lua_calc_strlen_in_table(L, i, i,
     121             :                                                           0 /* strict */);
     122           0 :                 break;
     123             : 
     124           0 :             case LUA_TLIGHTUSERDATA:
     125             : 
     126             :                 dd("userdata: %p", lua_touserdata(L, i));
     127             : 
     128           0 :                 if (lua_touserdata(L, i) == NULL) {
     129           0 :                     size += sizeof("null") - 1;
     130           0 :                     break;
     131             :                 }
     132             : 
     133           0 :                 continue;
     134             : 
     135           0 :             default:
     136             : 
     137           0 :                 msg = lua_pushfstring(L, "string, number, boolean, nil, "
     138             :                                       "ngx.null, or array table expected, "
     139             :                                       "but got %s", lua_typename(L, type));
     140             : 
     141           0 :                 return luaL_argerror(L, i, msg);
     142             :         }
     143             :     }
     144             : 
     145           1 :     if (newline) {
     146           1 :         size += sizeof("\n") - 1;
     147             :     }
     148             : 
     149           1 :     if (size == 0) {
     150           0 :         rc = ngx_http_lua_send_header_if_needed(r, ctx);
     151           0 :         if (rc == NGX_ERROR || rc > NGX_OK) {
     152           0 :             lua_pushnil(L);
     153           0 :             lua_pushliteral(L, "nginx output filter error");
     154           0 :             return 2;
     155             :         }
     156             : 
     157           0 :         lua_pushinteger(L, 1);
     158           0 :         return 1;
     159             :     }
     160             : 
     161           1 :     ctx->seen_body_data = 1;
     162             : 
     163           1 :     cl = ngx_http_lua_chain_get_free_buf(r->connection->log, r->pool,
     164             :                                          &ctx->free_bufs, size);
     165             : 
     166           1 :     if (cl == NULL) {
     167           0 :         return luaL_error(L, "no memory");
     168             :     }
     169             : 
     170           1 :     b = cl->buf;
     171             : 
     172           2 :     for (i = 1; i <= nargs; i++) {
     173           1 :         type = lua_type(L, i);
     174           1 :         switch (type) {
     175           1 :             case LUA_TNUMBER:
     176             :             case LUA_TSTRING:
     177           1 :                 p = lua_tolstring(L, i, &len);
     178           1 :                 b->last = ngx_copy(b->last, (u_char *) p, len);
     179           1 :                 break;
     180             : 
     181           0 :             case LUA_TNIL:
     182           0 :                 *b->last++ = 'n';
     183           0 :                 *b->last++ = 'i';
     184           0 :                 *b->last++ = 'l';
     185           0 :                 break;
     186             : 
     187           0 :             case LUA_TBOOLEAN:
     188           0 :                 if (lua_toboolean(L, i)) {
     189           0 :                     *b->last++ = 't';
     190           0 :                     *b->last++ = 'r';
     191           0 :                     *b->last++ = 'u';
     192           0 :                     *b->last++ = 'e';
     193             : 
     194             :                 } else {
     195           0 :                     *b->last++ = 'f';
     196           0 :                     *b->last++ = 'a';
     197           0 :                     *b->last++ = 'l';
     198           0 :                     *b->last++ = 's';
     199           0 :                     *b->last++ = 'e';
     200             :                 }
     201             : 
     202           0 :                 break;
     203             : 
     204           0 :             case LUA_TTABLE:
     205           0 :                 b->last = ngx_http_lua_copy_str_in_table(L, i, b->last);
     206           0 :                 break;
     207             : 
     208           0 :             case LUA_TLIGHTUSERDATA:
     209           0 :                 *b->last++ = 'n';
     210           0 :                 *b->last++ = 'u';
     211           0 :                 *b->last++ = 'l';
     212           0 :                 *b->last++ = 'l';
     213           0 :                 break;
     214             : 
     215           0 :             default:
     216           0 :                 return luaL_error(L, "impossible to reach here");
     217             :         }
     218             :     }
     219             : 
     220           1 :     if (newline) {
     221           1 :         *b->last++ = '\n';
     222             :     }
     223             : 
     224             : #if 0
     225             :     if (b->last != b->end) {
     226             :         return luaL_error(L, "buffer error: %p != %p", b->last, b->end);
     227             :     }
     228             : #endif
     229             : 
     230           1 :     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
     231             :                    newline ? "lua say response" : "lua print response");
     232             : 
     233           1 :     rc = ngx_http_lua_send_chain_link(r, ctx, cl);
     234             : 
     235           1 :     if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
     236           0 :         lua_pushnil(L);
     237           0 :         lua_pushliteral(L, "nginx output filter error");
     238           0 :         return 2;
     239             :     }
     240             : 
     241             :     dd("downstream write: %d, buf len: %d", (int) rc,
     242             :        (int) (b->last - b->pos));
     243             : 
     244           1 :     lua_pushinteger(L, 1);
     245           1 :     return 1;
     246             : }
     247             : 
     248             : 
     249             : size_t
     250           0 : ngx_http_lua_calc_strlen_in_table(lua_State *L, int index, int arg_i,
     251             :     unsigned strict)
     252             : {
     253             :     double              key;
     254             :     int                 max;
     255             :     int                 i;
     256             :     int                 type;
     257             :     size_t              size;
     258             :     size_t              len;
     259             :     const char         *msg;
     260             : 
     261           0 :     if (index < 0) {
     262           0 :         index = lua_gettop(L) + index + 1;
     263             :     }
     264             : 
     265             :     dd("table index: %d", index);
     266             : 
     267           0 :     max = 0;
     268             : 
     269           0 :     lua_pushnil(L); /* stack: table key */
     270           0 :     while (lua_next(L, index) != 0) { /* stack: table key value */
     271             :         dd("key type: %s", luaL_typename(L, -2));
     272             : 
     273           0 :         if (lua_type(L, -2) == LUA_TNUMBER) {
     274             : 
     275           0 :             key = lua_tonumber(L, -2);
     276             : 
     277             :             dd("key value: %d", (int) key);
     278             : 
     279           0 :             if (floor(key) == key && key >= 1) {
     280           0 :                 if (key > max) {
     281           0 :                     max = (int) key;
     282             :                 }
     283             : 
     284           0 :                 lua_pop(L, 1); /* stack: table key */
     285           0 :                 continue;
     286             :             }
     287             :         }
     288             : 
     289             :         /* not an array (non positive integer key) */
     290           0 :         lua_pop(L, 2); /* stack: table */
     291             : 
     292           0 :         luaL_argerror(L, arg_i, "non-array table found");
     293           0 :         return 0;
     294             :     }
     295             : 
     296           0 :     size = 0;
     297             : 
     298           0 :     for (i = 1; i <= max; i++) {
     299           0 :         lua_rawgeti(L, index, i); /* stack: table value */
     300           0 :         type = lua_type(L, -1);
     301             : 
     302           0 :         switch (type) {
     303           0 :             case LUA_TNUMBER:
     304             :             case LUA_TSTRING:
     305             : 
     306           0 :                 lua_tolstring(L, -1, &len);
     307           0 :                 size += len;
     308           0 :                 break;
     309             : 
     310           0 :             case LUA_TNIL:
     311             : 
     312           0 :                 if (strict) {
     313           0 :                     goto bad_type;
     314             :                 }
     315             : 
     316           0 :                 size += sizeof("nil") - 1;
     317           0 :                 break;
     318             : 
     319           0 :             case LUA_TBOOLEAN:
     320             : 
     321           0 :                 if (strict) {
     322           0 :                     goto bad_type;
     323             :                 }
     324             : 
     325           0 :                 if (lua_toboolean(L, -1)) {
     326           0 :                     size += sizeof("true") - 1;
     327             : 
     328             :                 } else {
     329           0 :                     size += sizeof("false") - 1;
     330             :                 }
     331             : 
     332           0 :                 break;
     333             : 
     334           0 :             case LUA_TTABLE:
     335             : 
     336           0 :                 size += ngx_http_lua_calc_strlen_in_table(L, -1, arg_i, strict);
     337           0 :                 break;
     338             : 
     339           0 :             case LUA_TLIGHTUSERDATA:
     340             : 
     341           0 :                 if (strict) {
     342           0 :                     goto bad_type;
     343             :                 }
     344             : 
     345           0 :                 if (lua_touserdata(L, -1) == NULL) {
     346           0 :                     size += sizeof("null") - 1;
     347           0 :                     break;
     348             :                 }
     349             : 
     350           0 :                 continue;
     351             : 
     352             :             default:
     353             : 
     354           0 : bad_type:
     355             : 
     356           0 :                 msg = lua_pushfstring(L, "bad data type %s found",
     357             :                                       lua_typename(L, type));
     358           0 :                 return luaL_argerror(L, arg_i, msg);
     359             :         }
     360             : 
     361           0 :         lua_pop(L, 1); /* stack: table */
     362             :     }
     363             : 
     364           0 :     return size;
     365             : }
     366             : 
     367             : 
     368             : u_char *
     369           0 : ngx_http_lua_copy_str_in_table(lua_State *L, int index, u_char *dst)
     370             : {
     371             :     double               key;
     372             :     int                  max;
     373             :     int                  i;
     374             :     int                  type;
     375             :     size_t               len;
     376             :     u_char              *p;
     377             : 
     378           0 :     if (index < 0) {
     379           0 :         index = lua_gettop(L) + index + 1;
     380             :     }
     381             : 
     382           0 :     max = 0;
     383             : 
     384           0 :     lua_pushnil(L); /* stack: table key */
     385           0 :     while (lua_next(L, index) != 0) { /* stack: table key value */
     386           0 :         key = lua_tonumber(L, -2);
     387           0 :         if (key > max) {
     388           0 :             max = (int) key;
     389             :         }
     390             : 
     391           0 :         lua_pop(L, 1); /* stack: table key */
     392             :     }
     393             : 
     394           0 :     for (i = 1; i <= max; i++) {
     395           0 :         lua_rawgeti(L, index, i); /* stack: table value */
     396           0 :         type = lua_type(L, -1);
     397           0 :         switch (type) {
     398           0 :             case LUA_TNUMBER:
     399             :             case LUA_TSTRING:
     400           0 :                 p = (u_char *) lua_tolstring(L, -1, &len);
     401           0 :                 dst = ngx_copy(dst, p, len);
     402           0 :                 break;
     403             : 
     404           0 :             case LUA_TNIL:
     405           0 :                 *dst++ = 'n';
     406           0 :                 *dst++ = 'i';
     407           0 :                 *dst++ = 'l';
     408           0 :                 break;
     409             : 
     410           0 :             case LUA_TBOOLEAN:
     411           0 :                 if (lua_toboolean(L, -1)) {
     412           0 :                     *dst++ = 't';
     413           0 :                     *dst++ = 'r';
     414           0 :                     *dst++ = 'u';
     415           0 :                     *dst++ = 'e';
     416             : 
     417             :                 } else {
     418           0 :                     *dst++ = 'f';
     419           0 :                     *dst++ = 'a';
     420           0 :                     *dst++ = 'l';
     421           0 :                     *dst++ = 's';
     422           0 :                     *dst++ = 'e';
     423             :                 }
     424             : 
     425           0 :                 break;
     426             : 
     427           0 :             case LUA_TTABLE:
     428           0 :                 dst = ngx_http_lua_copy_str_in_table(L, -1, dst);
     429           0 :                 break;
     430             : 
     431           0 :             case LUA_TLIGHTUSERDATA:
     432             : 
     433           0 :                 *dst++ = 'n';
     434           0 :                 *dst++ = 'u';
     435           0 :                 *dst++ = 'l';
     436           0 :                 *dst++ = 'l';
     437           0 :                 break;
     438             : 
     439           0 :             default:
     440           0 :                 luaL_error(L, "impossible to reach here");
     441           0 :                 return NULL;
     442             :         }
     443             : 
     444           0 :         lua_pop(L, 1); /* stack: table */
     445             :     }
     446             : 
     447           0 :     return dst;
     448             : }
     449             : 
     450             : 
     451             : /**
     452             :  * Force flush out response content
     453             :  * */
     454             : static int
     455           0 : ngx_http_lua_ngx_flush(lua_State *L)
     456             : {
     457             :     ngx_http_request_t          *r;
     458             :     ngx_http_lua_ctx_t          *ctx;
     459             :     ngx_chain_t                 *cl;
     460             :     ngx_int_t                    rc;
     461             :     int                          n;
     462           0 :     unsigned                     wait = 0;
     463             :     ngx_event_t                 *wev;
     464             :     ngx_http_core_loc_conf_t    *clcf;
     465             :     ngx_http_lua_co_ctx_t       *coctx;
     466             : 
     467           0 :     n = lua_gettop(L);
     468           0 :     if (n > 1) {
     469           0 :         return luaL_error(L, "attempt to pass %d arguments, but accepted 0 "
     470             :                           "or 1", n);
     471             :     }
     472             : 
     473           0 :     r = ngx_http_lua_get_req(L);
     474             : 
     475           0 :     if (n == 1 && r == r->main) {
     476           0 :         luaL_checktype(L, 1, LUA_TBOOLEAN);
     477           0 :         wait = lua_toboolean(L, 1);
     478             :     }
     479             : 
     480           0 :     ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
     481           0 :     if (ctx == NULL) {
     482           0 :         return luaL_error(L, "no request ctx found");
     483             :     }
     484             : 
     485           0 :     ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
     486             :                                | NGX_HTTP_LUA_CONTEXT_ACCESS
     487             :                                | NGX_HTTP_LUA_CONTEXT_CONTENT);
     488             : 
     489           0 :     if (ctx->acquired_raw_req_socket) {
     490           0 :         lua_pushnil(L);
     491           0 :         lua_pushliteral(L, "raw request socket acquired");
     492           0 :         return 2;
     493             :     }
     494             : 
     495           0 :     coctx = ctx->cur_co_ctx;
     496           0 :     if (coctx == NULL) {
     497           0 :         return luaL_error(L, "no co ctx found");
     498             :     }
     499             : 
     500           0 :     if (r->header_only) {
     501           0 :         lua_pushnil(L);
     502           0 :         lua_pushliteral(L, "header only");
     503           0 :         return 2;
     504             :     }
     505             : 
     506           0 :     if (ctx->eof) {
     507           0 :         lua_pushnil(L);
     508           0 :         lua_pushliteral(L, "seen eof");
     509           0 :         return 2;
     510             :     }
     511             : 
     512           0 :     if (ctx->buffering) {
     513           0 :         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
     514             :                        "lua http 1.0 buffering makes ngx.flush() a no-op");
     515             : 
     516           0 :         lua_pushnil(L);
     517           0 :         lua_pushliteral(L, "buffering");
     518           0 :         return 2;
     519             :     }
     520             : 
     521             : #if 1
     522           0 :     if ((!r->header_sent && !ctx->header_sent)
     523           0 :         || (!ctx->seen_body_data && !wait))
     524             :     {
     525           0 :         lua_pushnil(L);
     526           0 :         lua_pushliteral(L, "nothing to flush");
     527           0 :         return 2;
     528             :     }
     529             : #endif
     530             : 
     531           0 :     cl = ngx_http_lua_get_flush_chain(r, ctx);
     532           0 :     if (cl == NULL) {
     533           0 :         return luaL_error(L, "no memory");
     534             :     }
     535             : 
     536           0 :     rc = ngx_http_lua_send_chain_link(r, ctx, cl);
     537             : 
     538             :     dd("send chain: %d", (int) rc);
     539             : 
     540           0 :     if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
     541           0 :         lua_pushnil(L);
     542           0 :         lua_pushliteral(L, "nginx output filter error");
     543           0 :         return 2;
     544             :     }
     545             : 
     546             :     dd("wait:%d, rc:%d, buffered:0x%x", wait, (int) rc,
     547             :        r->connection->buffered);
     548             : 
     549           0 :     wev = r->connection->write;
     550             : 
     551           0 :     if (wait && (r->connection->buffered & NGX_HTTP_LOWLEVEL_BUFFERED
     552           0 :                  || wev->delayed))
     553             :     {
     554           0 :         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
     555             :                        "lua flush requires waiting: buffered 0x%uxd, "
     556             :                        "delayed:%d", (unsigned) r->connection->buffered,
     557             :                        wev->delayed);
     558             : 
     559           0 :         coctx->flushing = 1;
     560           0 :         ctx->flushing_coros++;
     561             : 
     562           0 :         if (ctx->entered_content_phase) {
     563             :             /* mimic ngx_http_set_write_handler */
     564           0 :             r->write_event_handler = ngx_http_lua_content_wev_handler;
     565             : 
     566             :         } else {
     567           0 :             r->write_event_handler = ngx_http_core_run_phases;
     568             :         }
     569             : 
     570           0 :         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
     571             : 
     572           0 :         if (!wev->delayed) {
     573           0 :             ngx_add_timer(wev, clcf->send_timeout);
     574             :         }
     575             : 
     576           0 :         if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
     577           0 :             if (wev->timer_set) {
     578           0 :                 wev->delayed = 0;
     579           0 :                 ngx_del_timer(wev);
     580             :             }
     581             : 
     582           0 :             lua_pushnil(L);
     583           0 :             lua_pushliteral(L, "connection broken");
     584           0 :             return 2;
     585             :         }
     586             : 
     587           0 :         ngx_http_lua_cleanup_pending_operation(ctx->cur_co_ctx);
     588           0 :         coctx->cleanup = ngx_http_lua_flush_cleanup;
     589           0 :         coctx->data = r;
     590             : 
     591           0 :         return lua_yield(L, 0);
     592             :     }
     593             : 
     594           0 :     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
     595             :                    "lua flush asynchronously");
     596             : 
     597           0 :     lua_pushinteger(L, 1);
     598           0 :     return 1;
     599             : }
     600             : 
     601             : 
     602             : /**
     603             :  * Send last_buf, terminate output stream
     604             :  * */
     605             : static int
     606           0 : ngx_http_lua_ngx_eof(lua_State *L)
     607             : {
     608             :     ngx_http_request_t      *r;
     609             :     ngx_http_lua_ctx_t      *ctx;
     610             :     ngx_int_t                rc;
     611             : 
     612           0 :     r = ngx_http_lua_get_req(L);
     613           0 :     if (r == NULL) {
     614           0 :         return luaL_error(L, "no request object found");
     615             :     }
     616             : 
     617           0 :     if (lua_gettop(L) != 0) {
     618           0 :         return luaL_error(L, "no argument is expected");
     619             :     }
     620             : 
     621           0 :     ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
     622           0 :     if (ctx == NULL) {
     623           0 :         return luaL_error(L, "no ctx found");
     624             :     }
     625             : 
     626           0 :     if (ctx->acquired_raw_req_socket) {
     627           0 :         lua_pushnil(L);
     628           0 :         lua_pushliteral(L, "raw request socket acquired");
     629           0 :         return 2;
     630             :     }
     631             : 
     632           0 :     if (ctx->eof) {
     633           0 :         lua_pushnil(L);
     634           0 :         lua_pushliteral(L, "seen eof");
     635           0 :         return 2;
     636             :     }
     637             : 
     638           0 :     ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
     639             :                                | NGX_HTTP_LUA_CONTEXT_ACCESS
     640             :                                | NGX_HTTP_LUA_CONTEXT_CONTENT);
     641             : 
     642           0 :     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
     643             :                    "lua send eof");
     644             : 
     645           0 :     rc = ngx_http_lua_send_chain_link(r, ctx, NULL /* indicate last_buf */);
     646             : 
     647             :     dd("send chain: %d", (int) rc);
     648             : 
     649           0 :     if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
     650           0 :         lua_pushnil(L);
     651           0 :         lua_pushliteral(L, "nginx output filter error");
     652           0 :         return 2;
     653             :     }
     654             : 
     655           0 :     lua_pushinteger(L, 1);
     656           0 :     return 1;
     657             : }
     658             : 
     659             : 
     660             : void
     661          18 : ngx_http_lua_inject_output_api(lua_State *L)
     662             : {
     663          18 :     lua_pushcfunction(L, ngx_http_lua_ngx_send_headers);
     664          18 :     lua_setfield(L, -2, "send_headers");
     665             : 
     666          18 :     lua_pushcfunction(L, ngx_http_lua_ngx_print);
     667          18 :     lua_setfield(L, -2, "print");
     668             : 
     669          18 :     lua_pushcfunction(L, ngx_http_lua_ngx_say);
     670          18 :     lua_setfield(L, -2, "say");
     671             : 
     672          18 :     lua_pushcfunction(L, ngx_http_lua_ngx_flush);
     673          18 :     lua_setfield(L, -2, "flush");
     674             : 
     675          18 :     lua_pushcfunction(L, ngx_http_lua_ngx_eof);
     676          18 :     lua_setfield(L, -2, "eof");
     677          18 : }
     678             : 
     679             : 
     680             : /**
     681             :  * Send out headers
     682             :  * */
     683             : static int
     684           0 : ngx_http_lua_ngx_send_headers(lua_State *L)
     685             : {
     686             :     ngx_int_t                rc;
     687             :     ngx_http_request_t      *r;
     688             :     ngx_http_lua_ctx_t      *ctx;
     689             : 
     690           0 :     r = ngx_http_lua_get_req(L);
     691           0 :     if (r == NULL) {
     692           0 :         return luaL_error(L, "no request found");
     693             :     }
     694             : 
     695           0 :     ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
     696           0 :     if (ctx == NULL) {
     697           0 :         return luaL_error(L, "no ctx found");
     698             :     }
     699             : 
     700           0 :     ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
     701             :                                | NGX_HTTP_LUA_CONTEXT_ACCESS
     702             :                                | NGX_HTTP_LUA_CONTEXT_CONTENT);
     703             : 
     704           0 :     if (!r->header_sent && !ctx->header_sent) {
     705           0 :         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
     706             :                        "lua send headers");
     707             : 
     708           0 :         rc = ngx_http_lua_send_header_if_needed(r, ctx);
     709           0 :         if (rc == NGX_ERROR || rc > NGX_OK) {
     710           0 :             lua_pushnil(L);
     711           0 :             lua_pushliteral(L, "nginx output filter error");
     712           0 :             return 2;
     713             :         }
     714             :     }
     715             : 
     716           0 :     lua_pushinteger(L, 1);
     717           0 :     return 1;
     718             : }
     719             : 
     720             : 
     721             : ngx_int_t
     722           0 : ngx_http_lua_flush_resume_helper(ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx)
     723             : {
     724             :     int                          n;
     725             :     lua_State                   *vm;
     726             :     ngx_int_t                    rc;
     727             :     ngx_uint_t                   nreqs;
     728             :     ngx_connection_t            *c;
     729             : 
     730           0 :     c = r->connection;
     731             : 
     732           0 :     ctx->cur_co_ctx->cleanup = NULL;
     733             : 
     734             :     /* push the return values */
     735             : 
     736           0 :     if (c->timedout) {
     737           0 :         lua_pushnil(ctx->cur_co_ctx->co);
     738           0 :         lua_pushliteral(ctx->cur_co_ctx->co, "timeout");
     739           0 :         n = 2;
     740             : 
     741           0 :     } else if (c->error) {
     742           0 :         lua_pushnil(ctx->cur_co_ctx->co);
     743           0 :         lua_pushliteral(ctx->cur_co_ctx->co, "client aborted");
     744           0 :         n = 2;
     745             : 
     746             :     } else {
     747           0 :         lua_pushinteger(ctx->cur_co_ctx->co, 1);
     748           0 :         n = 1;
     749             :     }
     750             : 
     751           0 :     vm = ngx_http_lua_get_lua_vm(r, ctx);
     752           0 :     nreqs = c->requests;
     753             : 
     754           0 :     rc = ngx_http_lua_run_thread(vm, r, ctx, n);
     755             : 
     756           0 :     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
     757             :                    "lua run thread returned %d", rc);
     758             : 
     759           0 :     if (rc == NGX_AGAIN) {
     760           0 :         return ngx_http_lua_run_posted_threads(c, vm, r, ctx, nreqs);
     761             :     }
     762             : 
     763           0 :     if (rc == NGX_DONE) {
     764           0 :         ngx_http_lua_finalize_request(r, NGX_DONE);
     765           0 :         return ngx_http_lua_run_posted_threads(c, vm, r, ctx, nreqs);
     766             :     }
     767             : 
     768             :     /* rc == NGX_ERROR || rc >= NGX_OK */
     769             : 
     770           0 :     if (ctx->entered_content_phase) {
     771           0 :         ngx_http_lua_finalize_request(r, rc);
     772           0 :         return NGX_DONE;
     773             :     }
     774             : 
     775           0 :     return rc;
     776             : }
     777             : 
     778             : 
     779             : static void
     780           0 : ngx_http_lua_flush_cleanup(void *data)
     781             : {
     782             :     ngx_http_request_t                      *r;
     783             :     ngx_event_t                             *wev;
     784             :     ngx_http_lua_ctx_t                      *ctx;
     785           0 :     ngx_http_lua_co_ctx_t                   *coctx = data;
     786             : 
     787           0 :     coctx->flushing = 0;
     788             : 
     789           0 :     r = coctx->data;
     790           0 :     if (r == NULL) {
     791           0 :         return;
     792             :     }
     793             : 
     794           0 :     wev = r->connection->write;
     795             : 
     796           0 :     if (wev && wev->timer_set) {
     797           0 :         ngx_del_timer(wev);
     798             :     }
     799             : 
     800           0 :     ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
     801           0 :     if (ctx == NULL) {
     802           0 :         return;
     803             :     }
     804             : 
     805           0 :     ctx->flushing_coros--;
     806             : }
     807             : 
     808             : /* vi:set ft=c ts=4 sw=4 et fdm=marker: */

Generated by: LCOV version 1.13