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_subrequest.c (source / functions) Hit Total Coverage
Test: coverage ngix Lines: 8 725 1.1 %
Date: 2020-03-03 04:25:50 Functions: 1 15 6.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : 
       2             : /*
       3             :  * Copyright (C) Xiaozhe Wang (chaoslawful)
       4             :  * Copyright (C) Yichun Zhang (agentzh)
       5             :  */
       6             : 
       7             : 
       8             : #ifndef DDEBUG
       9             : #define DDEBUG 0
      10             : #endif
      11             : #include "ddebug.h"
      12             : 
      13             : 
      14             : #include "ngx_http_lua_subrequest.h"
      15             : #include "ngx_http_lua_util.h"
      16             : #include "ngx_http_lua_ctx.h"
      17             : #include "ngx_http_lua_contentby.h"
      18             : #include "ngx_http_lua_headers_in.h"
      19             : #if defined(NGX_DTRACE) && NGX_DTRACE
      20             : #include "ngx_http_probe.h"
      21             : #endif
      22             : 
      23             : 
      24             : #define NGX_HTTP_LUA_SHARE_ALL_VARS     0x01
      25             : #define NGX_HTTP_LUA_COPY_ALL_VARS      0x02
      26             : 
      27             : 
      28             : #define ngx_http_lua_method_name(m) { sizeof(m) - 1, (u_char *) m " " }
      29             : 
      30             : ngx_str_t  ngx_http_lua_get_method = ngx_http_lua_method_name("GET");
      31             : ngx_str_t  ngx_http_lua_put_method = ngx_http_lua_method_name("PUT");
      32             : ngx_str_t  ngx_http_lua_post_method = ngx_http_lua_method_name("POST");
      33             : ngx_str_t  ngx_http_lua_head_method = ngx_http_lua_method_name("HEAD");
      34             : ngx_str_t  ngx_http_lua_delete_method =
      35             :         ngx_http_lua_method_name("DELETE");
      36             : ngx_str_t  ngx_http_lua_options_method =
      37             :         ngx_http_lua_method_name("OPTIONS");
      38             : ngx_str_t  ngx_http_lua_copy_method = ngx_http_lua_method_name("COPY");
      39             : ngx_str_t  ngx_http_lua_move_method = ngx_http_lua_method_name("MOVE");
      40             : ngx_str_t  ngx_http_lua_lock_method = ngx_http_lua_method_name("LOCK");
      41             : ngx_str_t  ngx_http_lua_mkcol_method =
      42             :         ngx_http_lua_method_name("MKCOL");
      43             : ngx_str_t  ngx_http_lua_propfind_method =
      44             :         ngx_http_lua_method_name("PROPFIND");
      45             : ngx_str_t  ngx_http_lua_proppatch_method =
      46             :         ngx_http_lua_method_name("PROPPATCH");
      47             : ngx_str_t  ngx_http_lua_unlock_method =
      48             :         ngx_http_lua_method_name("UNLOCK");
      49             : ngx_str_t  ngx_http_lua_patch_method =
      50             :         ngx_http_lua_method_name("PATCH");
      51             : ngx_str_t  ngx_http_lua_trace_method =
      52             :         ngx_http_lua_method_name("TRACE");
      53             : 
      54             : 
      55             : static ngx_str_t  ngx_http_lua_content_length_header_key =
      56             :     ngx_string("Content-Length");
      57             : 
      58             : 
      59             : static ngx_int_t ngx_http_lua_set_content_length_header(ngx_http_request_t *r,
      60             :     off_t len);
      61             : static ngx_int_t ngx_http_lua_adjust_subrequest(ngx_http_request_t *sr,
      62             :     ngx_uint_t method, int forward_body,
      63             :     ngx_http_request_body_t *body, unsigned vars_action,
      64             :     ngx_array_t *extra_vars);
      65             : static int ngx_http_lua_ngx_location_capture(lua_State *L);
      66             : static int ngx_http_lua_ngx_location_capture_multi(lua_State *L);
      67             : static void ngx_http_lua_process_vars_option(ngx_http_request_t *r,
      68             :     lua_State *L, int table, ngx_array_t **varsp);
      69             : static ngx_int_t ngx_http_lua_subrequest_add_extra_vars(ngx_http_request_t *r,
      70             :     ngx_array_t *extra_vars);
      71             : static ngx_int_t ngx_http_lua_subrequest(ngx_http_request_t *r,
      72             :     ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **psr,
      73             :     ngx_http_post_subrequest_t *ps, ngx_uint_t flags);
      74             : static ngx_int_t ngx_http_lua_subrequest_resume(ngx_http_request_t *r);
      75             : static void ngx_http_lua_handle_subreq_responses(ngx_http_request_t *r,
      76             :     ngx_http_lua_ctx_t *ctx);
      77             : static void ngx_http_lua_cancel_subreq(ngx_http_request_t *r);
      78             : static ngx_int_t ngx_http_post_request_to_head(ngx_http_request_t *r);
      79             : static ngx_int_t ngx_http_lua_copy_in_file_request_body(ngx_http_request_t *r);
      80             : static ngx_int_t ngx_http_lua_copy_request_headers(ngx_http_request_t *sr,
      81             :     ngx_http_request_t *r);
      82             : 
      83             : 
      84             : /* ngx.location.capture is just a thin wrapper around
      85             :  * ngx.location.capture_multi */
      86             : static int
      87           0 : ngx_http_lua_ngx_location_capture(lua_State *L)
      88             : {
      89             :     int                 n;
      90             : 
      91           0 :     n = lua_gettop(L);
      92             : 
      93           0 :     if (n != 1 && n != 2) {
      94           0 :         return luaL_error(L, "expecting one or two arguments");
      95             :     }
      96             : 
      97           0 :     lua_createtable(L, n, 0); /* uri opts? table  */
      98           0 :     lua_insert(L, 1); /* table uri opts? */
      99           0 :     if (n == 1) { /* table uri */
     100           0 :         lua_rawseti(L, 1, 1); /* table */
     101             : 
     102             :     } else { /* table uri opts */
     103           0 :         lua_rawseti(L, 1, 2); /* table uri */
     104           0 :         lua_rawseti(L, 1, 1); /* table */
     105             :     }
     106             : 
     107           0 :     lua_createtable(L, 1, 0); /* table table' */
     108           0 :     lua_insert(L, 1);   /* table' table */
     109           0 :     lua_rawseti(L, 1, 1); /* table' */
     110             : 
     111           0 :     return ngx_http_lua_ngx_location_capture_multi(L);
     112             : }
     113             : 
     114             : 
     115             : static int
     116           0 : ngx_http_lua_ngx_location_capture_multi(lua_State *L)
     117             : {
     118             :     ngx_http_request_t              *r;
     119           0 :     ngx_http_request_t              *sr = NULL; /* subrequest object */
     120             :     ngx_http_post_subrequest_t      *psr;
     121             :     ngx_http_lua_ctx_t              *sr_ctx;
     122             :     ngx_http_lua_ctx_t              *ctx;
     123             :     ngx_array_t                     *extra_vars;
     124             :     ngx_str_t                        uri;
     125             :     ngx_str_t                        args;
     126             :     ngx_str_t                        extra_args;
     127             :     ngx_uint_t                       flags;
     128             :     u_char                          *p;
     129             :     u_char                          *q;
     130             :     size_t                           len;
     131             :     size_t                           nargs;
     132             :     int                              rc;
     133             :     int                              n;
     134           0 :     int                              always_forward_body = 0;
     135             :     ngx_uint_t                       method;
     136             :     ngx_http_request_body_t         *body;
     137             :     int                              type;
     138             :     ngx_buf_t                       *b;
     139             :     unsigned                         vars_action;
     140             :     ngx_uint_t                       nsubreqs;
     141             :     ngx_uint_t                       index;
     142             :     size_t                           sr_statuses_len;
     143             :     size_t                           sr_headers_len;
     144             :     size_t                           sr_bodies_len;
     145             :     size_t                           sr_flags_len;
     146             :     size_t                           ofs1, ofs2;
     147             :     unsigned                         custom_ctx;
     148             :     ngx_http_lua_co_ctx_t           *coctx;
     149             : 
     150             :     ngx_http_lua_post_subrequest_data_t      *psr_data;
     151             : 
     152           0 :     n = lua_gettop(L);
     153           0 :     if (n != 1) {
     154           0 :         return luaL_error(L, "only one argument is expected, but got %d", n);
     155             :     }
     156             : 
     157           0 :     luaL_checktype(L, 1, LUA_TTABLE);
     158             : 
     159           0 :     nsubreqs = lua_objlen(L, 1);
     160           0 :     if (nsubreqs == 0) {
     161           0 :         return luaL_error(L, "at least one subrequest should be specified");
     162             :     }
     163             : 
     164           0 :     r = ngx_http_lua_get_req(L);
     165           0 :     if (r == NULL) {
     166           0 :         return luaL_error(L, "no request object found");
     167             :     }
     168             : 
     169           0 :     ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
     170           0 :     if (ctx == NULL) {
     171           0 :         return luaL_error(L, "no ctx found");
     172             :     }
     173             : 
     174           0 :     ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
     175             :                                | NGX_HTTP_LUA_CONTEXT_ACCESS
     176             :                                | NGX_HTTP_LUA_CONTEXT_CONTENT);
     177             : 
     178           0 :     coctx = ctx->cur_co_ctx;
     179           0 :     if (coctx == NULL) {
     180           0 :         return luaL_error(L, "no co ctx found");
     181             :     }
     182             : 
     183           0 :     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
     184             :                    "lua location capture, uri:\"%V\" c:%ud", &r->uri,
     185             :                    r->main->count);
     186             : 
     187           0 :     sr_statuses_len = nsubreqs * sizeof(ngx_int_t);
     188           0 :     sr_headers_len  = nsubreqs * sizeof(ngx_http_headers_out_t *);
     189           0 :     sr_bodies_len   = nsubreqs * sizeof(ngx_str_t);
     190           0 :     sr_flags_len    = nsubreqs * sizeof(uint8_t);
     191             : 
     192           0 :     p = ngx_pcalloc(r->pool, sr_statuses_len + sr_headers_len +
     193             :                     sr_bodies_len + sr_flags_len);
     194             : 
     195           0 :     if (p == NULL) {
     196           0 :         return luaL_error(L, "no memory");
     197             :     }
     198             : 
     199           0 :     coctx->sr_statuses = (void *) p;
     200           0 :     p += sr_statuses_len;
     201             : 
     202           0 :     coctx->sr_headers = (void *) p;
     203           0 :     p += sr_headers_len;
     204             : 
     205           0 :     coctx->sr_bodies = (void *) p;
     206           0 :     p += sr_bodies_len;
     207             : 
     208           0 :     coctx->sr_flags = (void *) p;
     209             : 
     210           0 :     coctx->nsubreqs = nsubreqs;
     211             : 
     212           0 :     coctx->pending_subreqs = 0;
     213             : 
     214           0 :     extra_vars = NULL;
     215             : 
     216           0 :     for (index = 0; index < nsubreqs; index++) {
     217           0 :         coctx->pending_subreqs++;
     218             : 
     219           0 :         lua_rawgeti(L, 1, index + 1);
     220           0 :         if (lua_isnil(L, -1)) {
     221           0 :             return luaL_error(L, "only array-like tables are allowed");
     222             :         }
     223             : 
     224             :         dd("queries query: top %d", lua_gettop(L));
     225             : 
     226           0 :         if (lua_type(L, -1) != LUA_TTABLE) {
     227           0 :             return luaL_error(L, "the query argument %d is not a table, "
     228             :                               "but a %s",
     229             :                               index, lua_typename(L, lua_type(L, -1)));
     230             :         }
     231             : 
     232           0 :         nargs = lua_objlen(L, -1);
     233             : 
     234           0 :         if (nargs != 1 && nargs != 2) {
     235           0 :             return luaL_error(L, "query argument %d expecting one or "
     236             :                               "two arguments", index);
     237             :         }
     238             : 
     239           0 :         lua_rawgeti(L, 2, 1); /* queries query uri */
     240             : 
     241             :         dd("queries query uri: %d", lua_gettop(L));
     242             : 
     243             :         dd("first arg in first query: %s", lua_typename(L, lua_type(L, -1)));
     244             : 
     245           0 :         body = NULL;
     246             : 
     247           0 :         ngx_str_null(&extra_args);
     248             : 
     249           0 :         if (extra_vars != NULL) {
     250             :             /* flush out existing elements in the array */
     251           0 :             extra_vars->nelts = 0;
     252             :         }
     253             : 
     254           0 :         vars_action = 0;
     255             : 
     256           0 :         custom_ctx = 0;
     257             : 
     258           0 :         if (nargs == 2) {
     259             :             /* check out the options table */
     260             : 
     261           0 :             lua_rawgeti(L, 2, 2); /* queries query uri opts */
     262             : 
     263             :             dd("queries query uri opts: %d", lua_gettop(L));
     264             : 
     265           0 :             if (lua_type(L, 4) != LUA_TTABLE) {
     266           0 :                 return luaL_error(L, "expecting table as the 2nd argument for "
     267             :                                   "subrequest %d, but got %s", index,
     268             :                                   luaL_typename(L, 4));
     269             :             }
     270             : 
     271             :             dd("queries query uri opts: %d", lua_gettop(L));
     272             : 
     273             :             /* check the args option */
     274             : 
     275           0 :             lua_getfield(L, 4, "args");
     276             : 
     277           0 :             type = lua_type(L, -1);
     278             : 
     279           0 :             switch (type) {
     280           0 :             case LUA_TTABLE:
     281           0 :                 ngx_http_lua_process_args_option(r, L, -1, &extra_args);
     282           0 :                 break;
     283             : 
     284           0 :             case LUA_TNIL:
     285             :                 /* do nothing */
     286           0 :                 break;
     287             : 
     288           0 :             case LUA_TNUMBER:
     289             :             case LUA_TSTRING:
     290           0 :                 extra_args.data = (u_char *) lua_tolstring(L, -1, &len);
     291           0 :                 extra_args.len = len;
     292             : 
     293           0 :                 break;
     294             : 
     295           0 :             default:
     296           0 :                 return luaL_error(L, "Bad args option value");
     297             :             }
     298             : 
     299           0 :             lua_pop(L, 1);
     300             : 
     301             :             dd("queries query uri opts: %d", lua_gettop(L));
     302             : 
     303             :             /* check the vars option */
     304             : 
     305           0 :             lua_getfield(L, 4, "vars");
     306             : 
     307           0 :             switch (lua_type(L, -1)) {
     308           0 :             case LUA_TTABLE:
     309           0 :                 ngx_http_lua_process_vars_option(r, L, -1, &extra_vars);
     310             : 
     311             :                 dd("post process vars top: %d", lua_gettop(L));
     312           0 :                 break;
     313             : 
     314           0 :             case LUA_TNIL:
     315             :                 /* do nothing */
     316           0 :                 break;
     317             : 
     318           0 :             default:
     319           0 :                 return luaL_error(L, "Bad vars option value");
     320             :             }
     321             : 
     322           0 :             lua_pop(L, 1);
     323             : 
     324             :             dd("queries query uri opts: %d", lua_gettop(L));
     325             : 
     326             :             /* check the share_all_vars option */
     327             : 
     328           0 :             lua_getfield(L, 4, "share_all_vars");
     329             : 
     330           0 :             switch (lua_type(L, -1)) {
     331           0 :             case LUA_TNIL:
     332             :                 /* do nothing */
     333           0 :                 break;
     334             : 
     335           0 :             case LUA_TBOOLEAN:
     336           0 :                 if (lua_toboolean(L, -1)) {
     337           0 :                     vars_action |= NGX_HTTP_LUA_SHARE_ALL_VARS;
     338             :                 }
     339           0 :                 break;
     340             : 
     341           0 :             default:
     342           0 :                 return luaL_error(L, "Bad share_all_vars option value");
     343             :             }
     344             : 
     345           0 :             lua_pop(L, 1);
     346             : 
     347             :             dd("queries query uri opts: %d", lua_gettop(L));
     348             : 
     349             :             /* check the copy_all_vars option */
     350             : 
     351           0 :             lua_getfield(L, 4, "copy_all_vars");
     352             : 
     353           0 :             switch (lua_type(L, -1)) {
     354           0 :             case LUA_TNIL:
     355             :                 /* do nothing */
     356           0 :                 break;
     357             : 
     358           0 :             case LUA_TBOOLEAN:
     359           0 :                 if (lua_toboolean(L, -1)) {
     360           0 :                     vars_action |= NGX_HTTP_LUA_COPY_ALL_VARS;
     361             :                 }
     362           0 :                 break;
     363             : 
     364           0 :             default:
     365           0 :                 return luaL_error(L, "Bad copy_all_vars option value");
     366             :             }
     367             : 
     368           0 :             lua_pop(L, 1);
     369             : 
     370             :             dd("queries query uri opts: %d", lua_gettop(L));
     371             : 
     372             :             /* check the "forward_body" option */
     373             : 
     374           0 :             lua_getfield(L, 4, "always_forward_body");
     375           0 :             always_forward_body = lua_toboolean(L, -1);
     376           0 :             lua_pop(L, 1);
     377             : 
     378             :             dd("always forward body: %d", always_forward_body);
     379             : 
     380             :             /* check the "method" option */
     381             : 
     382           0 :             lua_getfield(L, 4, "method");
     383             : 
     384           0 :             type = lua_type(L, -1);
     385             : 
     386           0 :             if (type == LUA_TNIL) {
     387           0 :                 method = NGX_HTTP_GET;
     388             : 
     389             :             } else {
     390           0 :                 if (type != LUA_TNUMBER) {
     391           0 :                     return luaL_error(L, "Bad http request method");
     392             :                 }
     393             : 
     394           0 :                 method = (ngx_uint_t) lua_tonumber(L, -1);
     395             :             }
     396             : 
     397           0 :             lua_pop(L, 1);
     398             : 
     399             :             dd("queries query uri opts: %d", lua_gettop(L));
     400             : 
     401             :             /* check the "ctx" option */
     402             : 
     403           0 :             lua_getfield(L, 4, "ctx");
     404             : 
     405           0 :             type = lua_type(L, -1);
     406             : 
     407           0 :             if (type != LUA_TNIL) {
     408           0 :                 if (type != LUA_TTABLE) {
     409           0 :                     return luaL_error(L, "Bad ctx option value type %s, "
     410             :                                       "expected a Lua table",
     411             :                                       lua_typename(L, type));
     412             :                 }
     413             : 
     414           0 :                 custom_ctx = 1;
     415             : 
     416             :             } else {
     417           0 :                 lua_pop(L, 1);
     418             :             }
     419             : 
     420             :             dd("queries query uri opts ctx?: %d", lua_gettop(L));
     421             : 
     422             :             /* check the "body" option */
     423             : 
     424           0 :             lua_getfield(L, 4, "body");
     425             : 
     426           0 :             type = lua_type(L, -1);
     427             : 
     428           0 :             if (type != LUA_TNIL) {
     429           0 :                 if (type != LUA_TSTRING && type != LUA_TNUMBER) {
     430           0 :                     return luaL_error(L, "Bad http request body");
     431             :                 }
     432             : 
     433           0 :                 body = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));
     434             : 
     435           0 :                 if (body == NULL) {
     436           0 :                     return luaL_error(L, "no memory");
     437             :                 }
     438             : 
     439           0 :                 q = (u_char *) lua_tolstring(L, -1, &len);
     440             : 
     441             :                 dd("request body: [%.*s]", (int) len, q);
     442             : 
     443           0 :                 if (len) {
     444           0 :                     b = ngx_create_temp_buf(r->pool, len);
     445           0 :                     if (b == NULL) {
     446           0 :                         return luaL_error(L, "no memory");
     447             :                     }
     448             : 
     449           0 :                     b->last = ngx_copy(b->last, q, len);
     450             : 
     451           0 :                     body->bufs = ngx_alloc_chain_link(r->pool);
     452           0 :                     if (body->bufs == NULL) {
     453           0 :                         return luaL_error(L, "no memory");
     454             :                     }
     455             : 
     456           0 :                     body->bufs->buf = b;
     457           0 :                     body->bufs->next = NULL;
     458             : 
     459           0 :                     body->buf = b;
     460             :                 }
     461             :             }
     462             : 
     463           0 :             lua_pop(L, 1); /* pop the body */
     464             : 
     465             :             /* stack: queries query uri opts ctx? */
     466             : 
     467           0 :             lua_remove(L, 4);
     468             : 
     469             :             /* stack: queries query uri ctx? */
     470             : 
     471             :             dd("queries query uri ctx?: %d", lua_gettop(L));
     472             : 
     473             :         } else {
     474           0 :             method = NGX_HTTP_GET;
     475             :         }
     476             : 
     477             :         /* stack: queries query uri ctx? */
     478             : 
     479           0 :         p = (u_char *) luaL_checklstring(L, 3, &len);
     480             : 
     481           0 :         uri.data = ngx_palloc(r->pool, len);
     482           0 :         if (uri.data == NULL) {
     483           0 :             return luaL_error(L, "memory allocation error");
     484             :         }
     485             : 
     486           0 :         ngx_memcpy(uri.data, p, len);
     487             : 
     488           0 :         uri.len = len;
     489             : 
     490           0 :         ngx_str_null(&args);
     491             : 
     492           0 :         flags = 0;
     493             : 
     494           0 :         rc = ngx_http_parse_unsafe_uri(r, &uri, &args, &flags);
     495           0 :         if (rc != NGX_OK) {
     496             :             dd("rc = %d", (int) rc);
     497             : 
     498           0 :             return luaL_error(L, "unsafe uri in argument #1: %s", p);
     499             :         }
     500             : 
     501           0 :         if (args.len == 0) {
     502           0 :             if (extra_args.len) {
     503           0 :                 p = ngx_palloc(r->pool, extra_args.len);
     504           0 :                 if (p == NULL) {
     505           0 :                     return luaL_error(L, "no memory");
     506             :                 }
     507             : 
     508           0 :                 ngx_memcpy(p, extra_args.data, extra_args.len);
     509             : 
     510           0 :                 args.data = p;
     511           0 :                 args.len = extra_args.len;
     512             :             }
     513             : 
     514           0 :         } else if (extra_args.len) {
     515             :             /* concatenate the two parts of args together */
     516           0 :             len = args.len + (sizeof("&") - 1) + extra_args.len;
     517             : 
     518           0 :             p = ngx_palloc(r->pool, len);
     519           0 :             if (p == NULL) {
     520           0 :                 return luaL_error(L, "no memory");
     521             :             }
     522             : 
     523           0 :             q = ngx_copy(p, args.data, args.len);
     524           0 :             *q++ = '&';
     525           0 :             ngx_memcpy(q, extra_args.data, extra_args.len);
     526             : 
     527           0 :             args.data = p;
     528           0 :             args.len = len;
     529             :         }
     530             : 
     531           0 :         ofs1 = ngx_align(sizeof(ngx_http_post_subrequest_t), sizeof(void *));
     532           0 :         ofs2 = ngx_align(sizeof(ngx_http_lua_ctx_t), sizeof(void *));
     533             : 
     534           0 :         p = ngx_palloc(r->pool, ofs1 + ofs2
     535             :                        + sizeof(ngx_http_lua_post_subrequest_data_t));
     536           0 :         if (p == NULL) {
     537           0 :             return luaL_error(L, "no memory");
     538             :         }
     539             : 
     540           0 :         psr = (ngx_http_post_subrequest_t *) p;
     541             : 
     542           0 :         p += ofs1;
     543             : 
     544           0 :         sr_ctx = (ngx_http_lua_ctx_t *) p;
     545             : 
     546           0 :         ngx_http_lua_assert((void *) sr_ctx == ngx_align_ptr(sr_ctx,
     547             :                                                              sizeof(void *)));
     548             : 
     549           0 :         p += ofs2;
     550             : 
     551           0 :         psr_data = (ngx_http_lua_post_subrequest_data_t *) p;
     552             : 
     553           0 :         ngx_http_lua_assert((void *) psr_data == ngx_align_ptr(psr_data,
     554             :                                                                sizeof(void *)));
     555             : 
     556           0 :         ngx_memzero(sr_ctx, sizeof(ngx_http_lua_ctx_t));
     557             : 
     558             :         /* set by ngx_memzero:
     559             :          *      sr_ctx->run_post_subrequest = 0
     560             :          *      sr_ctx->free = NULL
     561             :          *      sr_ctx->body = NULL
     562             :          */
     563             : 
     564           0 :         psr_data->ctx = sr_ctx;
     565           0 :         psr_data->pr_co_ctx = coctx;
     566             : 
     567           0 :         psr->handler = ngx_http_lua_post_subrequest;
     568           0 :         psr->data = psr_data;
     569             : 
     570           0 :         rc = ngx_http_lua_subrequest(r, &uri, &args, &sr, psr, 0);
     571             : 
     572           0 :         if (rc != NGX_OK) {
     573           0 :             return luaL_error(L, "failed to issue subrequest: %d", (int) rc);
     574             :         }
     575             : 
     576           0 :         ngx_http_lua_init_ctx(sr, sr_ctx);
     577             : 
     578           0 :         sr_ctx->capture = 1;
     579           0 :         sr_ctx->index = index;
     580           0 :         sr_ctx->last_body = &sr_ctx->body;
     581           0 :         sr_ctx->vm_state = ctx->vm_state;
     582             : 
     583           0 :         ngx_http_set_ctx(sr, sr_ctx, ngx_http_lua_module);
     584             : 
     585           0 :         rc = ngx_http_lua_adjust_subrequest(sr, method, always_forward_body,
     586             :                                             body, vars_action, extra_vars);
     587             : 
     588           0 :         if (rc != NGX_OK) {
     589           0 :             ngx_http_lua_cancel_subreq(sr);
     590           0 :             return luaL_error(L, "failed to adjust the subrequest: %d",
     591             :                               (int) rc);
     592             :         }
     593             : 
     594             :         dd("queries query uri opts ctx? %d", lua_gettop(L));
     595             : 
     596             :         /* stack: queries query uri ctx? */
     597             : 
     598           0 :         if (custom_ctx) {
     599           0 :             ngx_http_lua_ngx_set_ctx_helper(L, sr, sr_ctx, -1);
     600           0 :             lua_pop(L, 3);
     601             : 
     602             :         } else {
     603           0 :             lua_pop(L, 2);
     604             :         }
     605             : 
     606             :         /* stack: queries */
     607             :     }
     608             : 
     609           0 :     if (extra_vars) {
     610           0 :         ngx_array_destroy(extra_vars);
     611             :     }
     612             : 
     613           0 :     ctx->no_abort = 1;
     614             : 
     615           0 :     return lua_yield(L, 0);
     616             : }
     617             : 
     618             : 
     619             : static ngx_int_t
     620           0 : ngx_http_lua_adjust_subrequest(ngx_http_request_t *sr, ngx_uint_t method,
     621             :     int always_forward_body, ngx_http_request_body_t *body,
     622             :     unsigned vars_action, ngx_array_t *extra_vars)
     623             : {
     624             :     ngx_http_request_t          *r;
     625             :     ngx_int_t                    rc;
     626             :     ngx_http_core_main_conf_t   *cmcf;
     627             :     size_t                       size;
     628             : 
     629           0 :     r = sr->parent;
     630             : 
     631           0 :     sr->header_in = r->header_in;
     632             : 
     633           0 :     if (body) {
     634           0 :         sr->request_body = body;
     635             : 
     636           0 :         rc = ngx_http_lua_set_content_length_header(sr,
     637           0 :                                                     body->buf
     638           0 :                                                     ? ngx_buf_size(body->buf)
     639             :                                                     : 0);
     640             : 
     641           0 :         if (rc != NGX_OK) {
     642           0 :             return NGX_ERROR;
     643             :         }
     644             : 
     645           0 :     } else if (!always_forward_body
     646           0 :                && method != NGX_HTTP_PUT
     647           0 :                && method != NGX_HTTP_POST
     648           0 :                && r->headers_in.content_length_n > 0)
     649             :     {
     650           0 :         rc = ngx_http_lua_set_content_length_header(sr, 0);
     651           0 :         if (rc != NGX_OK) {
     652           0 :             return NGX_ERROR;
     653             :         }
     654             : 
     655             : #if 1
     656           0 :         sr->request_body = NULL;
     657             : #endif
     658             : 
     659             :     } else {
     660           0 :         if (ngx_http_lua_copy_request_headers(sr, r) != NGX_OK) {
     661           0 :             return NGX_ERROR;
     662             :         }
     663             : 
     664           0 :         if (sr->request_body) {
     665             : 
     666             :             /* deep-copy the request body */
     667             : 
     668           0 :             if (sr->request_body->temp_file) {
     669           0 :                 if (ngx_http_lua_copy_in_file_request_body(sr) != NGX_OK) {
     670           0 :                     return NGX_ERROR;
     671             :                 }
     672             :             }
     673             :         }
     674             :     }
     675             : 
     676           0 :     sr->method = method;
     677             : 
     678           0 :     switch (method) {
     679           0 :         case NGX_HTTP_GET:
     680           0 :             sr->method_name = ngx_http_lua_get_method;
     681           0 :             break;
     682             : 
     683           0 :         case NGX_HTTP_POST:
     684           0 :             sr->method_name = ngx_http_lua_post_method;
     685           0 :             break;
     686             : 
     687           0 :         case NGX_HTTP_PUT:
     688           0 :             sr->method_name = ngx_http_lua_put_method;
     689           0 :             break;
     690             : 
     691           0 :         case NGX_HTTP_HEAD:
     692           0 :             sr->method_name = ngx_http_lua_head_method;
     693           0 :             break;
     694             : 
     695           0 :         case NGX_HTTP_DELETE:
     696           0 :             sr->method_name = ngx_http_lua_delete_method;
     697           0 :             break;
     698             : 
     699           0 :         case NGX_HTTP_OPTIONS:
     700           0 :             sr->method_name = ngx_http_lua_options_method;
     701           0 :             break;
     702             : 
     703           0 :         case NGX_HTTP_MKCOL:
     704           0 :             sr->method_name = ngx_http_lua_mkcol_method;
     705           0 :             break;
     706             : 
     707           0 :         case NGX_HTTP_COPY:
     708           0 :             sr->method_name = ngx_http_lua_copy_method;
     709           0 :             break;
     710             : 
     711           0 :         case NGX_HTTP_MOVE:
     712           0 :             sr->method_name = ngx_http_lua_move_method;
     713           0 :             break;
     714             : 
     715           0 :         case NGX_HTTP_PROPFIND:
     716           0 :             sr->method_name = ngx_http_lua_propfind_method;
     717           0 :             break;
     718             : 
     719           0 :         case NGX_HTTP_PROPPATCH:
     720           0 :             sr->method_name = ngx_http_lua_proppatch_method;
     721           0 :             break;
     722             : 
     723           0 :         case NGX_HTTP_LOCK:
     724           0 :             sr->method_name = ngx_http_lua_lock_method;
     725           0 :             break;
     726             : 
     727           0 :         case NGX_HTTP_UNLOCK:
     728           0 :             sr->method_name = ngx_http_lua_unlock_method;
     729           0 :             break;
     730             : 
     731           0 :         case NGX_HTTP_PATCH:
     732           0 :             sr->method_name = ngx_http_lua_patch_method;
     733           0 :             break;
     734             : 
     735           0 :         case NGX_HTTP_TRACE:
     736           0 :             sr->method_name = ngx_http_lua_trace_method;
     737           0 :             break;
     738             : 
     739           0 :         default:
     740           0 :             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
     741             :                           "unsupported HTTP method: %u", (unsigned) method);
     742             : 
     743           0 :             return NGX_ERROR;
     744             :     }
     745             : 
     746           0 :     if (!(vars_action & NGX_HTTP_LUA_SHARE_ALL_VARS)) {
     747             :         /* we do not inherit the parent request's variables */
     748           0 :         cmcf = ngx_http_get_module_main_conf(sr, ngx_http_core_module);
     749             : 
     750           0 :         size = cmcf->variables.nelts * sizeof(ngx_http_variable_value_t);
     751             : 
     752           0 :         if (vars_action & NGX_HTTP_LUA_COPY_ALL_VARS) {
     753             : 
     754           0 :             sr->variables = ngx_palloc(sr->pool, size);
     755           0 :             if (sr->variables == NULL) {
     756           0 :                 return NGX_ERROR;
     757             :             }
     758             : 
     759           0 :             ngx_memcpy(sr->variables, r->variables, size);
     760             : 
     761             :         } else {
     762             : 
     763             :             /* we do not inherit the parent request's variables */
     764             : 
     765           0 :             sr->variables = ngx_pcalloc(sr->pool, size);
     766           0 :             if (sr->variables == NULL) {
     767           0 :                 return NGX_ERROR;
     768             :             }
     769             :         }
     770             :     }
     771             : 
     772           0 :     return ngx_http_lua_subrequest_add_extra_vars(sr, extra_vars);
     773             : }
     774             : 
     775             : 
     776             : static ngx_int_t
     777           0 : ngx_http_lua_subrequest_add_extra_vars(ngx_http_request_t *sr,
     778             :     ngx_array_t *extra_vars)
     779             : {
     780             :     ngx_http_core_main_conf_t   *cmcf;
     781             :     ngx_http_variable_t         *v;
     782             :     ngx_http_variable_value_t   *vv;
     783             :     u_char                      *val;
     784             :     u_char                      *p;
     785             :     ngx_uint_t                   i, hash;
     786             :     ngx_str_t                    name;
     787             :     size_t                       len;
     788             :     ngx_hash_t                  *variables_hash;
     789             :     ngx_keyval_t                *var;
     790             : 
     791             :     /* set any extra variables that were passed to the subrequest */
     792             : 
     793           0 :     if (extra_vars == NULL || extra_vars->nelts == 0) {
     794           0 :         return NGX_OK;
     795             :     }
     796             : 
     797           0 :     cmcf = ngx_http_get_module_main_conf(sr, ngx_http_core_module);
     798             : 
     799           0 :     variables_hash = &cmcf->variables_hash;
     800             : 
     801           0 :     var = extra_vars->elts;
     802             : 
     803           0 :     for (i = 0; i < extra_vars->nelts; i++, var++) {
     804             :         /* copy the variable's name and value because they are allocated
     805             :          * by the lua VM */
     806             : 
     807           0 :         len = var->key.len + var->value.len;
     808             : 
     809           0 :         p = ngx_pnalloc(sr->pool, len);
     810           0 :         if (p == NULL) {
     811           0 :             return NGX_ERROR;
     812             :         }
     813             : 
     814           0 :         name.data = p;
     815           0 :         name.len = var->key.len;
     816             : 
     817           0 :         p = ngx_copy(p, var->key.data, var->key.len);
     818             : 
     819           0 :         hash = ngx_hash_strlow(name.data, name.data, name.len);
     820             : 
     821           0 :         val = p;
     822           0 :         len = var->value.len;
     823             : 
     824           0 :         ngx_memcpy(p, var->value.data, len);
     825             : 
     826           0 :         v = ngx_hash_find(variables_hash, hash, name.data, name.len);
     827             : 
     828           0 :         if (v) {
     829           0 :             if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) {
     830           0 :                 ngx_log_error(NGX_LOG_ERR, sr->connection->log, 0,
     831             :                               "variable \"%V\" not changeable", &name);
     832           0 :                 return NGX_HTTP_INTERNAL_SERVER_ERROR;
     833             :             }
     834             : 
     835           0 :             if (v->set_handler) {
     836           0 :                 vv = ngx_palloc(sr->pool, sizeof(ngx_http_variable_value_t));
     837           0 :                 if (vv == NULL) {
     838           0 :                     return NGX_ERROR;
     839             :                 }
     840             : 
     841           0 :                 vv->valid = 1;
     842           0 :                 vv->not_found = 0;
     843           0 :                 vv->no_cacheable = 0;
     844             : 
     845           0 :                 vv->data = val;
     846           0 :                 vv->len = len;
     847             : 
     848           0 :                 v->set_handler(sr, vv, v->data);
     849             : 
     850           0 :                 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sr->connection->log, 0,
     851             :                                "variable \"%V\" set to value \"%v\"", &name,
     852             :                                vv);
     853             : 
     854           0 :                 continue;
     855             :             }
     856             : 
     857           0 :             if (v->flags & NGX_HTTP_VAR_INDEXED) {
     858           0 :                 vv = &sr->variables[v->index];
     859             : 
     860           0 :                 vv->valid = 1;
     861           0 :                 vv->not_found = 0;
     862           0 :                 vv->no_cacheable = 0;
     863             : 
     864           0 :                 vv->data = val;
     865           0 :                 vv->len = len;
     866             : 
     867           0 :                 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sr->connection->log, 0,
     868             :                                "variable \"%V\" set to value \"%v\"",
     869             :                                &name, vv);
     870             : 
     871           0 :                 continue;
     872             :             }
     873             :         }
     874             : 
     875           0 :         ngx_log_error(NGX_LOG_ERR, sr->connection->log, 0,
     876             :                       "variable \"%V\" cannot be assigned a value (maybe you "
     877             :                       "forgot to define it first?) ", &name);
     878             : 
     879           0 :         return NGX_ERROR;
     880             :     }
     881             : 
     882           0 :     return NGX_OK;
     883             : }
     884             : 
     885             : 
     886             : static void
     887           0 : ngx_http_lua_process_vars_option(ngx_http_request_t *r, lua_State *L,
     888             :     int table, ngx_array_t **varsp)
     889             : {
     890             :     ngx_array_t         *vars;
     891             :     ngx_keyval_t        *var;
     892             : 
     893           0 :     if (table < 0) {
     894           0 :         table = lua_gettop(L) + table + 1;
     895             :     }
     896             : 
     897           0 :     vars = *varsp;
     898             : 
     899           0 :     if (vars == NULL) {
     900             : 
     901           0 :         vars = ngx_array_create(r->pool, 4, sizeof(ngx_keyval_t));
     902           0 :         if (vars == NULL) {
     903             :             dd("here");
     904           0 :             luaL_error(L, "no memory");
     905           0 :             return;
     906             :         }
     907             : 
     908           0 :         *varsp = vars;
     909             :     }
     910             : 
     911           0 :     lua_pushnil(L);
     912           0 :     while (lua_next(L, table) != 0) {
     913             : 
     914           0 :         if (lua_type(L, -2) != LUA_TSTRING) {
     915           0 :             luaL_error(L, "attempt to use a non-string key in the "
     916             :                        "\"vars\" option table");
     917           0 :             return;
     918             :         }
     919             : 
     920           0 :         if (!lua_isstring(L, -1)) {
     921           0 :             luaL_error(L, "attempt to use bad variable value type %s",
     922             :                        luaL_typename(L, -1));
     923           0 :             return;
     924             :         }
     925             : 
     926           0 :         var = ngx_array_push(vars);
     927           0 :         if (var == NULL) {
     928             :             dd("here");
     929           0 :             luaL_error(L, "no memory");
     930           0 :             return;
     931             :         }
     932             : 
     933           0 :         var->key.data = (u_char *) lua_tolstring(L, -2, &var->key.len);
     934           0 :         var->value.data = (u_char *) lua_tolstring(L, -1, &var->value.len);
     935             : 
     936           0 :         lua_pop(L, 1);
     937             :     }
     938             : }
     939             : 
     940             : 
     941             : ngx_int_t
     942           0 : ngx_http_lua_post_subrequest(ngx_http_request_t *r, void *data, ngx_int_t rc)
     943             : {
     944             :     ngx_http_request_t            *pr;
     945             :     ngx_http_lua_ctx_t            *pr_ctx;
     946             :     ngx_http_lua_ctx_t            *ctx; /* subrequest ctx */
     947             :     ngx_http_lua_co_ctx_t         *pr_coctx;
     948             :     size_t                         len;
     949             :     ngx_str_t                     *body_str;
     950             :     u_char                        *p;
     951             :     ngx_chain_t                   *cl;
     952             : 
     953           0 :     ngx_http_lua_post_subrequest_data_t    *psr_data = data;
     954             : 
     955           0 :     ctx = psr_data->ctx;
     956             : 
     957           0 :     if (ctx->run_post_subrequest) {
     958           0 :         if (r != r->connection->data) {
     959           0 :             r->connection->data = r;
     960             :         }
     961             : 
     962           0 :         return NGX_OK;
     963             :     }
     964             : 
     965           0 :     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
     966             :                    "lua run post subrequest handler, rc:%i c:%ud", rc,
     967             :                    r->main->count);
     968             : 
     969           0 :     ctx->run_post_subrequest = 1;
     970             : 
     971           0 :     pr = r->parent;
     972             : 
     973           0 :     pr_ctx = ngx_http_get_module_ctx(pr, ngx_http_lua_module);
     974           0 :     if (pr_ctx == NULL) {
     975           0 :         return NGX_ERROR;
     976             :     }
     977             : 
     978           0 :     pr_coctx = psr_data->pr_co_ctx;
     979           0 :     pr_coctx->pending_subreqs--;
     980             : 
     981           0 :     if (pr_coctx->pending_subreqs == 0) {
     982             :         dd("all subrequests are done");
     983             : 
     984           0 :         pr_ctx->no_abort = 0;
     985           0 :         pr_ctx->resume_handler = ngx_http_lua_subrequest_resume;
     986           0 :         pr_ctx->cur_co_ctx = pr_coctx;
     987             :     }
     988             : 
     989           0 :     if (pr_ctx->entered_content_phase) {
     990           0 :         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
     991             :                        "lua restoring write event handler");
     992             : 
     993           0 :         pr->write_event_handler = ngx_http_lua_content_wev_handler;
     994             : 
     995             :     } else {
     996           0 :         pr->write_event_handler = ngx_http_core_run_phases;
     997             :     }
     998             : 
     999             :     dd("status rc = %d", (int) rc);
    1000             :     dd("status headers_out.status = %d", (int) r->headers_out.status);
    1001             :     dd("uri: %.*s", (int) r->uri.len, r->uri.data);
    1002             : 
    1003             :     /*  capture subrequest response status */
    1004             : 
    1005           0 :     pr_coctx->sr_statuses[ctx->index] = r->headers_out.status;
    1006             : 
    1007           0 :     if (pr_coctx->sr_statuses[ctx->index] == 0) {
    1008           0 :         if (rc == NGX_OK) {
    1009           0 :             rc = NGX_HTTP_OK;
    1010             :         }
    1011             : 
    1012           0 :         if (rc == NGX_ERROR) {
    1013           0 :             rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
    1014             :         }
    1015             : 
    1016           0 :         if (rc >= 100) {
    1017           0 :             pr_coctx->sr_statuses[ctx->index] = rc;
    1018             :         }
    1019             :     }
    1020             : 
    1021           0 :     if (!ctx->seen_last_for_subreq) {
    1022           0 :         pr_coctx->sr_flags[ctx->index] |= NGX_HTTP_LUA_SUBREQ_TRUNCATED;
    1023             :     }
    1024             : 
    1025             :     dd("pr_coctx status: %d", (int) pr_coctx->sr_statuses[ctx->index]);
    1026             : 
    1027             :     /* copy subrequest response headers */
    1028             : 
    1029           0 :     pr_coctx->sr_headers[ctx->index] = &r->headers_out;
    1030             : 
    1031             :     /* copy subrequest response body */
    1032             : 
    1033           0 :     body_str = &pr_coctx->sr_bodies[ctx->index];
    1034             : 
    1035           0 :     len = 0;
    1036           0 :     for (cl = ctx->body; cl; cl = cl->next) {
    1037             :         /*  ignore all non-memory buffers */
    1038           0 :         len += cl->buf->last - cl->buf->pos;
    1039             :     }
    1040             : 
    1041           0 :     body_str->len = len;
    1042             : 
    1043           0 :     if (len == 0) {
    1044           0 :         body_str->data = NULL;
    1045             : 
    1046             :     } else {
    1047           0 :         p = ngx_palloc(r->pool, len);
    1048           0 :         if (p == NULL) {
    1049           0 :             return NGX_ERROR;
    1050             :         }
    1051             : 
    1052           0 :         body_str->data = p;
    1053             : 
    1054             :         /* copy from and then free the data buffers */
    1055             : 
    1056           0 :         for (cl = ctx->body; cl; cl = cl->next) {
    1057           0 :             p = ngx_copy(p, cl->buf->pos, cl->buf->last - cl->buf->pos);
    1058             : 
    1059           0 :             cl->buf->last = cl->buf->pos;
    1060             : 
    1061             : #if 0
    1062             :             dd("free body chain link buf ASAP");
    1063             :             ngx_pfree(r->pool, cl->buf->start);
    1064             : #endif
    1065             :         }
    1066             :     }
    1067             : 
    1068           0 :     if (ctx->body) {
    1069             : 
    1070             : #if defined(nginx_version) && nginx_version >= 1001004
    1071           0 :         ngx_chain_update_chains(r->pool,
    1072             : #else
    1073             :         ngx_chain_update_chains(
    1074             : #endif
    1075             :                                 &pr_ctx->free_bufs, &pr_ctx->busy_bufs,
    1076             :                                 &ctx->body,
    1077             :                                 (ngx_buf_tag_t) &ngx_http_lua_module);
    1078             : 
    1079             :         dd("free bufs: %p", pr_ctx->free_bufs);
    1080             :     }
    1081             : 
    1082           0 :     ngx_http_post_request_to_head(pr);
    1083             : 
    1084           0 :     if (r != r->connection->data) {
    1085           0 :         r->connection->data = r;
    1086             :     }
    1087             : 
    1088           0 :     if (rc == NGX_ERROR
    1089           0 :         || rc == NGX_HTTP_CREATED
    1090           0 :         || rc == NGX_HTTP_NO_CONTENT
    1091           0 :         || (rc >= NGX_HTTP_SPECIAL_RESPONSE
    1092           0 :             && rc != NGX_HTTP_CLOSE
    1093           0 :             && rc != NGX_HTTP_REQUEST_TIME_OUT
    1094           0 :             && rc != NGX_HTTP_CLIENT_CLOSED_REQUEST))
    1095             :     {
    1096             :         /* emulate ngx_http_special_response_handler */
    1097             : 
    1098           0 :         if (rc > NGX_OK) {
    1099           0 :             r->err_status = rc;
    1100             : 
    1101           0 :             r->expect_tested = 1;
    1102           0 :             r->headers_out.content_type.len = 0;
    1103           0 :             r->headers_out.content_length_n = 0;
    1104             : 
    1105           0 :             ngx_http_clear_accept_ranges(r);
    1106           0 :             ngx_http_clear_last_modified(r);
    1107             : 
    1108           0 :             rc = ngx_http_lua_send_header_if_needed(r, ctx);
    1109           0 :             if (rc == NGX_ERROR) {
    1110           0 :                 return NGX_ERROR;
    1111             :             }
    1112             :         }
    1113             : 
    1114           0 :         return NGX_OK;
    1115             :     }
    1116             : 
    1117           0 :     return rc;
    1118             : }
    1119             : 
    1120             : 
    1121             : static ngx_int_t
    1122           0 : ngx_http_lua_set_content_length_header(ngx_http_request_t *r, off_t len)
    1123             : {
    1124             :     ngx_table_elt_t                 *h, *header;
    1125             :     u_char                          *p;
    1126             :     ngx_list_part_t                 *part;
    1127             :     ngx_http_request_t              *pr;
    1128             :     ngx_uint_t                       i;
    1129             : 
    1130           0 :     r->headers_in.content_length_n = len;
    1131             : 
    1132           0 :     if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
    1133             :                       sizeof(ngx_table_elt_t)) != NGX_OK)
    1134             :     {
    1135           0 :         return NGX_ERROR;
    1136             :     }
    1137             : 
    1138           0 :     h = ngx_list_push(&r->headers_in.headers);
    1139           0 :     if (h == NULL) {
    1140           0 :         return NGX_ERROR;
    1141             :     }
    1142             : 
    1143           0 :     h->key = ngx_http_lua_content_length_header_key;
    1144           0 :     h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
    1145           0 :     if (h->lowcase_key == NULL) {
    1146           0 :         return NGX_ERROR;
    1147             :     }
    1148             : 
    1149           0 :     ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
    1150             : 
    1151           0 :     r->headers_in.content_length = h;
    1152             : 
    1153           0 :     p = ngx_palloc(r->pool, NGX_OFF_T_LEN);
    1154           0 :     if (p == NULL) {
    1155           0 :         return NGX_ERROR;
    1156             :     }
    1157             : 
    1158           0 :     h->value.data = p;
    1159             : 
    1160           0 :     h->value.len = ngx_sprintf(h->value.data, "%O", len) - h->value.data;
    1161             : 
    1162           0 :     h->hash = ngx_http_lua_content_length_hash;
    1163             : 
    1164             : #if 0
    1165             :     dd("content length hash: %lu == %lu", (unsigned long) h->hash,
    1166             :        ngx_hash_key_lc((u_char *) "Content-Length",
    1167             :                        sizeof("Content-Length") - 1));
    1168             : #endif
    1169             : 
    1170             :     dd("r content length: %.*s",
    1171             :        (int) r->headers_in.content_length->value.len,
    1172             :        r->headers_in.content_length->value.data);
    1173             : 
    1174           0 :     pr = r->parent;
    1175             : 
    1176           0 :     if (pr == NULL) {
    1177           0 :         return NGX_OK;
    1178             :     }
    1179             : 
    1180             :     /* forward the parent request's all other request headers */
    1181             : 
    1182           0 :     part = &pr->headers_in.headers.part;
    1183           0 :     header = part->elts;
    1184             : 
    1185           0 :     for (i = 0; /* void */; i++) {
    1186             : 
    1187           0 :         if (i >= part->nelts) {
    1188           0 :             if (part->next == NULL) {
    1189           0 :                 break;
    1190             :             }
    1191             : 
    1192           0 :             part = part->next;
    1193           0 :             header = part->elts;
    1194           0 :             i = 0;
    1195             :         }
    1196             : 
    1197           0 :         if (header[i].key.len == sizeof("Content-Length") - 1
    1198           0 :             && ngx_strncasecmp(header[i].key.data, (u_char *) "Content-Length",
    1199             :                                sizeof("Content-Length") - 1) == 0)
    1200             :         {
    1201           0 :             continue;
    1202             :         }
    1203             : 
    1204           0 :         if (ngx_http_lua_set_input_header(r, header[i].key,
    1205           0 :                                           header[i].value, 0) == NGX_ERROR)
    1206             :         {
    1207           0 :             return NGX_ERROR;
    1208             :         }
    1209             :     }
    1210             : 
    1211           0 :     return NGX_OK;
    1212             : }
    1213             : 
    1214             : 
    1215             : static void
    1216           0 : ngx_http_lua_handle_subreq_responses(ngx_http_request_t *r,
    1217             :     ngx_http_lua_ctx_t *ctx)
    1218             : {
    1219             :     ngx_uint_t                   i, count;
    1220             :     ngx_uint_t                   index;
    1221             :     lua_State                   *co;
    1222             :     ngx_str_t                   *body_str;
    1223             :     ngx_table_elt_t             *header;
    1224             :     ngx_list_part_t             *part;
    1225             :     ngx_http_headers_out_t      *sr_headers;
    1226             :     ngx_http_lua_co_ctx_t       *coctx;
    1227             : 
    1228             :     u_char                  buf[sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1];
    1229             : 
    1230           0 :     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
    1231             :                    "lua handle subrequest responses");
    1232             : 
    1233           0 :     coctx = ctx->cur_co_ctx;
    1234           0 :     co = coctx->co;
    1235             : 
    1236           0 :     for (index = 0; index < coctx->nsubreqs; index++) {
    1237             :         dd("summary: reqs %d, subquery %d, pending %d, req %.*s",
    1238             :            (int) coctx->nsubreqs,
    1239             :            (int) index,
    1240             :            (int) coctx->pending_subreqs,
    1241             :            (int) r->uri.len, r->uri.data);
    1242             : 
    1243             :         /*  {{{ construct ret value */
    1244           0 :         lua_createtable(co, 0 /* narr */, 4 /* nrec */);
    1245             : 
    1246             :         /*  copy captured status */
    1247           0 :         lua_pushinteger(co, coctx->sr_statuses[index]);
    1248           0 :         lua_setfield(co, -2, "status");
    1249             : 
    1250             :         dd("captured subrequest flags: %d", (int) coctx->sr_flags[index]);
    1251             : 
    1252             :         /* set truncated flag if truncation happens */
    1253           0 :         if (coctx->sr_flags[index] & NGX_HTTP_LUA_SUBREQ_TRUNCATED) {
    1254           0 :             lua_pushboolean(co, 1);
    1255           0 :             lua_setfield(co, -2, "truncated");
    1256             : 
    1257             :         } else {
    1258           0 :             lua_pushboolean(co, 0);
    1259           0 :             lua_setfield(co, -2, "truncated");
    1260             :         }
    1261             : 
    1262             :         /*  copy captured body */
    1263             : 
    1264           0 :         body_str = &coctx->sr_bodies[index];
    1265             : 
    1266           0 :         lua_pushlstring(co, (char *) body_str->data, body_str->len);
    1267           0 :         lua_setfield(co, -2, "body");
    1268             : 
    1269           0 :         if (body_str->data) {
    1270             :             dd("free body buffer ASAP");
    1271           0 :             ngx_pfree(r->pool, body_str->data);
    1272             :         }
    1273             : 
    1274             :         /* copy captured headers */
    1275             : 
    1276           0 :         sr_headers = coctx->sr_headers[index];
    1277             : 
    1278           0 :         part = &sr_headers->headers.part;
    1279           0 :         count = part->nelts;
    1280           0 :         while (part->next) {
    1281           0 :             part = part->next;
    1282           0 :             count += part->nelts;
    1283             :         }
    1284             : 
    1285           0 :         lua_createtable(co, 0, count + 5); /* res.header */
    1286             : 
    1287             :         dd("saving subrequest response headers");
    1288             : 
    1289           0 :         part = &sr_headers->headers.part;
    1290           0 :         header = part->elts;
    1291             : 
    1292           0 :         for (i = 0; /* void */; i++) {
    1293             : 
    1294           0 :             if (i >= part->nelts) {
    1295           0 :                 if (part->next == NULL) {
    1296           0 :                     break;
    1297             :                 }
    1298             : 
    1299           0 :                 part = part->next;
    1300           0 :                 header = part->elts;
    1301           0 :                 i = 0;
    1302             :             }
    1303             : 
    1304             :             dd("checking sr header %.*s", (int) header[i].key.len,
    1305             :                header[i].key.data);
    1306             : 
    1307             : #if 1
    1308           0 :             if (header[i].hash == 0) {
    1309           0 :                 continue;
    1310             :             }
    1311             : #endif
    1312             : 
    1313           0 :             header[i].hash = 0;
    1314             : 
    1315             :             dd("pushing sr header %.*s", (int) header[i].key.len,
    1316             :                header[i].key.data);
    1317             : 
    1318           0 :             lua_pushlstring(co, (char *) header[i].key.data,
    1319           0 :                             header[i].key.len); /* header key */
    1320           0 :             lua_pushvalue(co, -1); /* stack: table key key */
    1321             : 
    1322             :             /* check if header already exists */
    1323           0 :             lua_rawget(co, -3); /* stack: table key value */
    1324             : 
    1325           0 :             if (lua_isnil(co, -1)) {
    1326           0 :                 lua_pop(co, 1); /* stack: table key */
    1327             : 
    1328           0 :                 lua_pushlstring(co, (char *) header[i].value.data,
    1329           0 :                                 header[i].value.len);
    1330             :                     /* stack: table key value */
    1331             : 
    1332           0 :                 lua_rawset(co, -3); /* stack: table */
    1333             : 
    1334             :             } else {
    1335             : 
    1336           0 :                 if (!lua_istable(co, -1)) { /* already inserted one value */
    1337           0 :                     lua_createtable(co, 4, 0);
    1338             :                         /* stack: table key value table */
    1339             : 
    1340           0 :                     lua_insert(co, -2); /* stack: table key table value */
    1341           0 :                     lua_rawseti(co, -2, 1); /* stack: table key table */
    1342             : 
    1343           0 :                     lua_pushlstring(co, (char *) header[i].value.data,
    1344           0 :                                     header[i].value.len);
    1345             :                         /* stack: table key table value */
    1346             : 
    1347           0 :                     lua_rawseti(co, -2, lua_objlen(co, -2) + 1);
    1348             :                         /* stack: table key table */
    1349             : 
    1350           0 :                     lua_rawset(co, -3); /* stack: table */
    1351             : 
    1352             :                 } else {
    1353           0 :                     lua_pushlstring(co, (char *) header[i].value.data,
    1354           0 :                                     header[i].value.len);
    1355             :                         /* stack: table key table value */
    1356             : 
    1357           0 :                     lua_rawseti(co, -2, lua_objlen(co, -2) + 1);
    1358             :                         /* stack: table key table */
    1359             : 
    1360           0 :                     lua_pop(co, 2); /* stack: table */
    1361             :                 }
    1362             :             }
    1363             :         }
    1364             : 
    1365           0 :         if (sr_headers->content_type.len) {
    1366           0 :             lua_pushliteral(co, "Content-Type"); /* header key */
    1367           0 :             lua_pushlstring(co, (char *) sr_headers->content_type.data,
    1368             :                             sr_headers->content_type.len); /* head key value */
    1369           0 :             lua_rawset(co, -3); /* head */
    1370             :         }
    1371             : 
    1372           0 :         if (sr_headers->content_length == NULL
    1373           0 :             && sr_headers->content_length_n >= 0)
    1374             :         {
    1375           0 :             lua_pushliteral(co, "Content-Length"); /* header key */
    1376             : 
    1377           0 :             lua_pushnumber(co, (lua_Number) sr_headers->content_length_n);
    1378             :                 /* head key value */
    1379             : 
    1380           0 :             lua_rawset(co, -3); /* head */
    1381             :         }
    1382             : 
    1383             :         /* to work-around an issue in ngx_http_static_module
    1384             :          * (github issue #41) */
    1385           0 :         if (sr_headers->location && sr_headers->location->value.len) {
    1386           0 :             lua_pushliteral(co, "Location"); /* header key */
    1387           0 :             lua_pushlstring(co, (char *) sr_headers->location->value.data,
    1388           0 :                             sr_headers->location->value.len);
    1389             :             /* head key value */
    1390           0 :             lua_rawset(co, -3); /* head */
    1391             :         }
    1392             : 
    1393           0 :         if (sr_headers->last_modified_time != -1) {
    1394           0 :             if (sr_headers->status != NGX_HTTP_OK
    1395           0 :                 && sr_headers->status != NGX_HTTP_PARTIAL_CONTENT
    1396           0 :                 && sr_headers->status != NGX_HTTP_NOT_MODIFIED
    1397           0 :                 && sr_headers->status != NGX_HTTP_NO_CONTENT)
    1398             :             {
    1399           0 :                 sr_headers->last_modified_time = -1;
    1400           0 :                 sr_headers->last_modified = NULL;
    1401             :             }
    1402             :         }
    1403             : 
    1404           0 :         if (sr_headers->last_modified == NULL
    1405           0 :             && sr_headers->last_modified_time != -1)
    1406             :         {
    1407           0 :             (void) ngx_http_time(buf, sr_headers->last_modified_time);
    1408             : 
    1409           0 :             lua_pushliteral(co, "Last-Modified"); /* header key */
    1410           0 :             lua_pushlstring(co, (char *) buf, sizeof(buf)); /* head key value */
    1411           0 :             lua_rawset(co, -3); /* head */
    1412             :         }
    1413             : 
    1414           0 :         lua_setfield(co, -2, "header");
    1415             : 
    1416             :         /*  }}} */
    1417             :     }
    1418           0 : }
    1419             : 
    1420             : 
    1421             : void
    1422          18 : ngx_http_lua_inject_subrequest_api(lua_State *L)
    1423             : {
    1424          18 :     lua_createtable(L, 0 /* narr */, 2 /* nrec */); /* .location */
    1425             : 
    1426          18 :     lua_pushcfunction(L, ngx_http_lua_ngx_location_capture);
    1427          18 :     lua_setfield(L, -2, "capture");
    1428             : 
    1429          18 :     lua_pushcfunction(L, ngx_http_lua_ngx_location_capture_multi);
    1430          18 :     lua_setfield(L, -2, "capture_multi");
    1431             : 
    1432          18 :     lua_setfield(L, -2, "location");
    1433          18 : }
    1434             : 
    1435             : 
    1436             : static ngx_int_t
    1437           0 : ngx_http_lua_subrequest(ngx_http_request_t *r,
    1438             :     ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **psr,
    1439             :     ngx_http_post_subrequest_t *ps, ngx_uint_t flags)
    1440             : {
    1441             :     ngx_time_t                    *tp;
    1442             :     ngx_connection_t              *c;
    1443             :     ngx_http_request_t            *sr;
    1444             :     ngx_http_core_srv_conf_t      *cscf;
    1445             : 
    1446             : #if nginx_version >= 1009005
    1447             : 
    1448           0 :     if (r->subrequests == 0) {
    1449             : #if defined(NGX_DTRACE) && NGX_DTRACE
    1450             :         ngx_http_probe_subrequest_cycle(r, uri, args);
    1451             : #endif
    1452             : 
    1453           0 :         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
    1454             :                       "lua subrequests cycle while processing \"%V\"", uri);
    1455           0 :         return NGX_ERROR;
    1456             :     }
    1457             : 
    1458             : #else  /* nginx_version <= 1009004 */
    1459             : 
    1460             :     r->main->subrequests--;
    1461             : 
    1462             :     if (r->main->subrequests == 0) {
    1463             : #if defined(NGX_DTRACE) && NGX_DTRACE
    1464             :         ngx_http_probe_subrequest_cycle(r, uri, args);
    1465             : #endif
    1466             : 
    1467             :         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
    1468             :                       "lua subrequests cycle while processing \"%V\"", uri);
    1469             :         r->main->subrequests = 1;
    1470             :         return NGX_ERROR;
    1471             :     }
    1472             : 
    1473             : #endif
    1474             : 
    1475           0 :     sr = ngx_pcalloc(r->pool, sizeof(ngx_http_request_t));
    1476           0 :     if (sr == NULL) {
    1477           0 :         return NGX_ERROR;
    1478             :     }
    1479             : 
    1480           0 :     sr->signature = NGX_HTTP_MODULE;
    1481             : 
    1482           0 :     c = r->connection;
    1483           0 :     sr->connection = c;
    1484             : 
    1485           0 :     sr->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
    1486           0 :     if (sr->ctx == NULL) {
    1487           0 :         return NGX_ERROR;
    1488             :     }
    1489             : 
    1490           0 :     if (ngx_list_init(&sr->headers_out.headers, r->pool, 20,
    1491             :                       sizeof(ngx_table_elt_t))
    1492             :         != NGX_OK)
    1493             :     {
    1494           0 :         return NGX_ERROR;
    1495             :     }
    1496             : 
    1497           0 :     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
    1498           0 :     sr->main_conf = cscf->ctx->main_conf;
    1499           0 :     sr->srv_conf = cscf->ctx->srv_conf;
    1500           0 :     sr->loc_conf = cscf->ctx->loc_conf;
    1501             : 
    1502           0 :     sr->pool = r->pool;
    1503             : 
    1504           0 :     sr->headers_in.content_length_n = -1;
    1505           0 :     sr->headers_in.keep_alive_n = -1;
    1506             : 
    1507           0 :     ngx_http_clear_content_length(sr);
    1508           0 :     ngx_http_clear_accept_ranges(sr);
    1509           0 :     ngx_http_clear_last_modified(sr);
    1510             : 
    1511           0 :     sr->request_body = r->request_body;
    1512             : 
    1513             : #if (NGX_HTTP_SPDY)
    1514             :     sr->spdy_stream = r->spdy_stream;
    1515             : #endif
    1516             : 
    1517             : #if (NGX_HTTP_V2)
    1518           0 :     sr->stream = r->stream;
    1519             : #endif
    1520             : 
    1521             : #ifdef HAVE_ALLOW_REQUEST_BODY_UPDATING_PATCH
    1522             :     sr->content_length_n = -1;
    1523             : #endif
    1524             : 
    1525           0 :     sr->method = NGX_HTTP_GET;
    1526           0 :     sr->http_version = r->http_version;
    1527             : 
    1528           0 :     sr->request_line = r->request_line;
    1529           0 :     sr->uri = *uri;
    1530             : 
    1531           0 :     if (args) {
    1532           0 :         sr->args = *args;
    1533             :     }
    1534             : 
    1535           0 :     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
    1536             :                    "lua http subrequest \"%V?%V\"", uri, &sr->args);
    1537             : 
    1538           0 :     sr->subrequest_in_memory = (flags & NGX_HTTP_SUBREQUEST_IN_MEMORY) != 0;
    1539           0 :     sr->waited = (flags & NGX_HTTP_SUBREQUEST_WAITED) != 0;
    1540             : 
    1541           0 :     sr->unparsed_uri = r->unparsed_uri;
    1542           0 :     sr->method_name = ngx_http_core_get_method;
    1543           0 :     sr->http_protocol = r->http_protocol;
    1544             : 
    1545           0 :     ngx_http_set_exten(sr);
    1546             : 
    1547           0 :     sr->main = r->main;
    1548           0 :     sr->parent = r;
    1549           0 :     sr->post_subrequest = ps;
    1550           0 :     sr->read_event_handler = ngx_http_request_empty_handler;
    1551           0 :     sr->write_event_handler = ngx_http_handler;
    1552             : 
    1553           0 :     sr->variables = r->variables;
    1554             : 
    1555           0 :     sr->log_handler = r->log_handler;
    1556             : 
    1557           0 :     sr->internal = 1;
    1558             : 
    1559           0 :     sr->discard_body = r->discard_body;
    1560           0 :     sr->expect_tested = 1;
    1561           0 :     sr->main_filter_need_in_memory = r->main_filter_need_in_memory;
    1562             : 
    1563           0 :     sr->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
    1564             : 
    1565             : #if nginx_version >= 1009005
    1566           0 :     sr->subrequests = r->subrequests - 1;
    1567             : #endif
    1568             : 
    1569           0 :     tp = ngx_timeofday();
    1570           0 :     sr->start_sec = tp->sec;
    1571           0 :     sr->start_msec = tp->msec;
    1572             : 
    1573           0 :     r->main->count++;
    1574             : 
    1575           0 :     *psr = sr;
    1576             : 
    1577             : #if defined(NGX_DTRACE) && NGX_DTRACE
    1578             :     ngx_http_probe_subrequest_start(sr);
    1579             : #endif
    1580             : 
    1581           0 :     return ngx_http_post_request(sr, NULL);
    1582             : }
    1583             : 
    1584             : 
    1585             : static ngx_int_t
    1586           0 : ngx_http_lua_subrequest_resume(ngx_http_request_t *r)
    1587             : {
    1588             :     lua_State                   *vm;
    1589             :     ngx_int_t                    rc;
    1590             :     ngx_uint_t                   nreqs;
    1591             :     ngx_connection_t            *c;
    1592             :     ngx_http_lua_ctx_t          *ctx;
    1593             :     ngx_http_lua_co_ctx_t       *coctx;
    1594             : 
    1595           0 :     ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
    1596           0 :     if (ctx == NULL) {
    1597           0 :         return NGX_ERROR;
    1598             :     }
    1599             : 
    1600           0 :     ctx->resume_handler = ngx_http_lua_wev_handler;
    1601             : 
    1602           0 :     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
    1603             :                    "lua run subrequests done, resuming lua thread");
    1604             : 
    1605           0 :     coctx = ctx->cur_co_ctx;
    1606             : 
    1607             :     dd("nsubreqs: %d", (int) coctx->nsubreqs);
    1608             : 
    1609           0 :     ngx_http_lua_handle_subreq_responses(r, ctx);
    1610             : 
    1611             :     dd("free sr_statues/headers/bodies memory ASAP");
    1612             : 
    1613             : #if 1
    1614           0 :     ngx_pfree(r->pool, coctx->sr_statuses);
    1615             : 
    1616           0 :     coctx->sr_statuses = NULL;
    1617           0 :     coctx->sr_headers = NULL;
    1618           0 :     coctx->sr_bodies = NULL;
    1619           0 :     coctx->sr_flags = NULL;
    1620             : #endif
    1621             : 
    1622           0 :     c = r->connection;
    1623           0 :     vm = ngx_http_lua_get_lua_vm(r, ctx);
    1624           0 :     nreqs = c->requests;
    1625             : 
    1626           0 :     rc = ngx_http_lua_run_thread(vm, r, ctx, coctx->nsubreqs);
    1627             : 
    1628           0 :     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
    1629             :                    "lua run thread returned %d", rc);
    1630             : 
    1631           0 :     if (rc == NGX_AGAIN) {
    1632           0 :         return ngx_http_lua_run_posted_threads(c, vm, r, ctx, nreqs);
    1633             :     }
    1634             : 
    1635           0 :     if (rc == NGX_DONE) {
    1636           0 :         ngx_http_lua_finalize_request(r, NGX_DONE);
    1637           0 :         return ngx_http_lua_run_posted_threads(c, vm, r, ctx, nreqs);
    1638             :     }
    1639             : 
    1640             :     /* rc == NGX_ERROR || rc >= NGX_OK */
    1641             : 
    1642           0 :     if (ctx->entered_content_phase) {
    1643           0 :         ngx_http_lua_finalize_request(r, rc);
    1644           0 :         return NGX_DONE;
    1645             :     }
    1646             : 
    1647           0 :     return rc;
    1648             : }
    1649             : 
    1650             : 
    1651             : static void
    1652           0 : ngx_http_lua_cancel_subreq(ngx_http_request_t *r)
    1653             : {
    1654             :     ngx_http_posted_request_t   *pr;
    1655             :     ngx_http_posted_request_t  **p;
    1656             : 
    1657             : #if 1
    1658           0 :     r->main->count--;
    1659           0 :     r->main->subrequests++;
    1660             : #endif
    1661             : 
    1662           0 :     p = &r->main->posted_requests;
    1663           0 :     for (pr = r->main->posted_requests; pr->next; pr = pr->next) {
    1664           0 :         p = &pr->next;
    1665             :     }
    1666             : 
    1667           0 :     *p = NULL;
    1668             : 
    1669           0 :     r->connection->data = r->parent;
    1670           0 : }
    1671             : 
    1672             : 
    1673             : static ngx_int_t
    1674           0 : ngx_http_post_request_to_head(ngx_http_request_t *r)
    1675             : {
    1676             :     ngx_http_posted_request_t  *pr;
    1677             : 
    1678           0 :     pr = ngx_palloc(r->pool, sizeof(ngx_http_posted_request_t));
    1679           0 :     if (pr == NULL) {
    1680           0 :         return NGX_ERROR;
    1681             :     }
    1682             : 
    1683           0 :     pr->request = r;
    1684           0 :     pr->next = r->main->posted_requests;
    1685           0 :     r->main->posted_requests = pr;
    1686             : 
    1687           0 :     return NGX_OK;
    1688             : }
    1689             : 
    1690             : 
    1691             : static ngx_int_t
    1692           0 : ngx_http_lua_copy_in_file_request_body(ngx_http_request_t *r)
    1693             : {
    1694             :     ngx_temp_file_t     *tf;
    1695             : 
    1696             :     ngx_http_request_body_t   *body;
    1697             : 
    1698           0 :     tf = r->request_body->temp_file;
    1699             : 
    1700           0 :     if (!tf->persistent || !tf->clean) {
    1701           0 :         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
    1702             :                       "the request body was not read by ngx_lua");
    1703             : 
    1704           0 :         return NGX_ERROR;
    1705             :     }
    1706             : 
    1707           0 :     body = ngx_palloc(r->pool, sizeof(ngx_http_request_body_t));
    1708           0 :     if (body == NULL) {
    1709           0 :         return NGX_ERROR;
    1710             :     }
    1711             : 
    1712           0 :     ngx_memcpy(body, r->request_body, sizeof(ngx_http_request_body_t));
    1713             : 
    1714           0 :     body->temp_file = ngx_palloc(r->pool, sizeof(ngx_temp_file_t));
    1715           0 :     if (body->temp_file == NULL) {
    1716           0 :         return NGX_ERROR;
    1717             :     }
    1718             : 
    1719           0 :     ngx_memcpy(body->temp_file, tf, sizeof(ngx_temp_file_t));
    1720             :     dd("file fd: %d", body->temp_file->file.fd);
    1721             : 
    1722           0 :     r->request_body = body;
    1723             : 
    1724           0 :     return NGX_OK;
    1725             : }
    1726             : 
    1727             : 
    1728             : static ngx_int_t
    1729           0 : ngx_http_lua_copy_request_headers(ngx_http_request_t *sr, ngx_http_request_t *r)
    1730             : {
    1731             :     ngx_table_elt_t                 *header;
    1732             :     ngx_list_part_t                 *part;
    1733             :     ngx_uint_t                       i;
    1734             : 
    1735           0 :     if (ngx_list_init(&sr->headers_in.headers, sr->pool, 20,
    1736             :                       sizeof(ngx_table_elt_t)) != NGX_OK)
    1737             :     {
    1738           0 :         return NGX_ERROR;
    1739             :     }
    1740             : 
    1741             :     dd("before: parent req headers count: %d",
    1742             :        (int) r->headers_in.headers.part.nelts);
    1743             : 
    1744           0 :     part = &r->headers_in.headers.part;
    1745           0 :     header = part->elts;
    1746             : 
    1747           0 :     for (i = 0; /* void */; i++) {
    1748             : 
    1749           0 :         if (i >= part->nelts) {
    1750           0 :             if (part->next == NULL) {
    1751           0 :                 break;
    1752             :             }
    1753             : 
    1754           0 :             part = part->next;
    1755           0 :             header = part->elts;
    1756           0 :             i = 0;
    1757             :         }
    1758             : 
    1759             :         dd("setting request header %.*s: %.*s", (int) header[i].key.len,
    1760             :            header[i].key.data, (int) header[i].value.len,
    1761             :            header[i].value.data);
    1762             : 
    1763           0 :         if (ngx_http_lua_set_input_header(sr, header[i].key,
    1764           0 :                                           header[i].value, 0) == NGX_ERROR)
    1765             :         {
    1766           0 :             return NGX_ERROR;
    1767             :         }
    1768             :     }
    1769             : 
    1770             :     dd("after: parent req headers count: %d",
    1771             :        (int) r->headers_in.headers.part.nelts);
    1772             : 
    1773           0 :     return NGX_OK;
    1774             : }
    1775             : 
    1776             : /* vi:set ft=c ts=4 sw=4 et fdm=marker: */

Generated by: LCOV version 1.13