~ubuntu-branches/ubuntu/precise/nginx/precise-security

« back to all changes in this revision

Viewing changes to debian/modules/nginx-lua/src/ngx_http_lua_subrequest.c

  • Committer: Package Import Robot
  • Author(s): Kartik Mistry, Kartik Mistry, Cyril Lavier
  • Date: 2012-01-01 17:21:02 UTC
  • mfrom: (4.2.42 sid)
  • Revision ID: package-import@ubuntu.com-20120101172102-nqw51zbd4p2wdtdz
Tags: 1.1.12-1
[Kartik Mistry]
* debian/control:
  + Set myself as Maintainer, Jose Parrella as Uploaders with approval from
    team.
* debian/copyright:
  + Fixed DEP5 URL.
  + Updated debian/* copyright.
* debian/modules:
  + Updated nginx-lua module to version 0.3.1rc43

[Cyril Lavier]
* New upstream release.
* debian/conf/sites-available/default:
  + Added a / in the alias directive. (Closes: #653160)
* debian/rules:
  + Added necessary lines for parallel building.

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 
6
6
#include "ngx_http_lua_subrequest.h"
7
7
#include "ngx_http_lua_util.h"
 
8
#include "ngx_http_lua_ctx.h"
8
9
#include "ngx_http_lua_contentby.h"
9
10
 
10
11
 
 
12
#define NGX_HTTP_LUA_SHARE_ALL_VARS     0x01
 
13
#define NGX_HTTP_LUA_COPY_ALL_VARS      0x02
 
14
 
 
15
 
11
16
#define ngx_http_lua_method_name(m) { sizeof(m) - 1, (u_char *) m " " }
12
17
 
13
18
static ngx_str_t  ngx_http_lua_get_method = ngx_http_lua_method_name("GET");
23
28
 
24
29
 
25
30
static ngx_int_t ngx_http_lua_set_content_length_header(ngx_http_request_t *r,
26
 
        off_t len);
 
31
    off_t len);
27
32
static ngx_int_t ngx_http_lua_adjust_subrequest(ngx_http_request_t *sr,
28
 
        ngx_uint_t method, ngx_http_request_body_t *body,
29
 
        unsigned share_all_vars);
 
33
    ngx_uint_t method, ngx_http_request_body_t *body, unsigned vars_action,
 
34
    ngx_array_t *extra_vars);
30
35
static int ngx_http_lua_ngx_location_capture(lua_State *L);
31
36
static int ngx_http_lua_ngx_location_capture_multi(lua_State *L);
 
37
static void ngx_http_lua_process_vars_option(ngx_http_request_t *r,
 
38
    lua_State *L, int table, ngx_array_t **varsp);
 
39
static ngx_int_t ngx_http_lua_subrequest_add_extra_vars(ngx_http_request_t *r,
 
40
    ngx_array_t *extra_vars);
32
41
 
33
42
 
34
43
/* ngx.location.capture is just a thin wrapper around
70
79
    ngx_http_post_subrequest_t      *psr;
71
80
    ngx_http_lua_ctx_t              *sr_ctx;
72
81
    ngx_http_lua_ctx_t              *ctx;
 
82
    ngx_array_t                     *extra_vars;
73
83
    ngx_str_t                        uri;
74
84
    ngx_str_t                        args;
75
85
    ngx_str_t                        extra_args;
84
94
    ngx_http_request_body_t         *body;
85
95
    int                              type;
86
96
    ngx_buf_t                       *b;
87
 
    unsigned                         share_all_vars;
 
97
    unsigned                         vars_action;
88
98
    ngx_uint_t                       nsubreqs;
89
99
    ngx_uint_t                       index;
90
100
    size_t                           sr_statuses_len;
91
101
    size_t                           sr_headers_len;
92
102
    size_t                           sr_bodies_len;
 
103
    unsigned                         custom_ctx;
93
104
 
94
105
    n = lua_gettop(L);
95
106
    if (n != 1) {
143
154
    ctx->done = 0;
144
155
    ctx->waiting = 0;
145
156
 
 
157
    extra_vars = NULL;
 
158
 
146
159
    for (index = 0; index < nsubreqs; index++) {
147
160
        ctx->waiting++;
148
161
 
151
164
            return luaL_error(L, "only array-like tables are allowed");
152
165
        }
153
166
 
 
167
        dd("queries query: top %d", lua_gettop(L));
 
168
 
154
169
        if (lua_type(L, -1) != LUA_TTABLE) {
155
170
            return luaL_error(L, "the query argument %d is not a table, "
156
171
                    "but a %s",
157
172
                    index, lua_typename(L, lua_type(L, -1)));
158
173
        }
159
174
 
160
 
        dd("lua top so far: %d", lua_gettop(L));
161
 
 
162
175
        nargs = lua_objlen(L, -1);
163
176
 
164
177
        if (nargs != 1 && nargs != 2) {
168
181
 
169
182
        lua_rawgeti(L, 2, 1); /* queries query uri */
170
183
 
 
184
        dd("queries query uri: %d", lua_gettop(L));
 
185
 
171
186
        dd("first arg in first query: %s", lua_typename(L, lua_type(L, -1)));
172
187
 
173
188
        body = NULL;
175
190
        extra_args.data = NULL;
176
191
        extra_args.len = 0;
177
192
 
178
 
        share_all_vars = 0;
 
193
        if (extra_vars != NULL) {
 
194
            /* flush out existing elements in the array */
 
195
            extra_vars->nelts = 0;
 
196
        }
 
197
 
 
198
        vars_action = 0;
 
199
 
 
200
        custom_ctx = 0;
179
201
 
180
202
        if (nargs == 2) {
181
203
            /* check out the options table */
182
204
 
183
 
            lua_rawgeti(L, 2, 2);
 
205
            lua_rawgeti(L, 2, 2); /* queries query uri opts */
 
206
 
 
207
            dd("queries query uri opts: %d", lua_gettop(L));
184
208
 
185
209
            if (lua_type(L, 4) != LUA_TTABLE) {
186
210
                return luaL_error(L, "expecting table as the 2nd argument for "
187
 
                        "subrequest %d", index);
 
211
                        "subrequest %d, but got %s", index,
 
212
                        luaL_typename(L, 4));
188
213
            }
189
214
 
 
215
            dd("queries query uri opts: %d", lua_gettop(L));
 
216
 
190
217
            /* check the args option */
191
218
 
192
219
            lua_getfield(L, 4, "args");
215
242
 
216
243
            lua_pop(L, 1);
217
244
 
 
245
            dd("queries query uri opts: %d", lua_gettop(L));
 
246
 
 
247
            /* check the vars option */
 
248
 
 
249
            lua_getfield(L, 4, "vars");
 
250
 
 
251
            switch (lua_type(L, -1)) {
 
252
            case LUA_TTABLE:
 
253
                ngx_http_lua_process_vars_option(r, L, -1, &extra_vars);
 
254
 
 
255
                dd("post process vars top: %d", lua_gettop(L));
 
256
                break;
 
257
 
 
258
            case LUA_TNIL:
 
259
                /* do nothing */
 
260
                break;
 
261
 
 
262
            default:
 
263
                return luaL_error(L, "Bad vars option value");
 
264
            }
 
265
 
 
266
            lua_pop(L, 1);
 
267
 
 
268
            dd("queries query uri opts: %d", lua_gettop(L));
 
269
 
218
270
            /* check the share_all_vars option */
219
271
 
220
272
            lua_getfield(L, 4, "share_all_vars");
221
273
 
222
 
            type = lua_type(L, -1);
223
 
 
224
 
            if (type == LUA_TNIL) {
225
 
                /* do nothing */
226
 
 
227
 
            } else {
228
 
                if (type != LUA_TBOOLEAN) {
229
 
                    return luaL_error(L, "Bad share_all_vars option value");
230
 
                }
231
 
 
232
 
                share_all_vars = lua_toboolean(L, -1);
233
 
            }
234
 
 
235
 
            lua_pop(L, 1);
236
 
 
237
 
            /* check the method option */
 
274
            switch (lua_type(L, -1)) {
 
275
            case LUA_TNIL:
 
276
                /* do nothing */
 
277
                break;
 
278
 
 
279
            case LUA_TBOOLEAN:
 
280
                if (lua_toboolean(L, -1)) {
 
281
                    vars_action |= NGX_HTTP_LUA_SHARE_ALL_VARS;
 
282
                }
 
283
                break;
 
284
 
 
285
            default:
 
286
                return luaL_error(L, "Bad share_all_vars option value");
 
287
            }
 
288
 
 
289
            lua_pop(L, 1);
 
290
 
 
291
            dd("queries query uri opts: %d", lua_gettop(L));
 
292
 
 
293
            /* check the copy_all_vars option */
 
294
 
 
295
            lua_getfield(L, 4, "copy_all_vars");
 
296
 
 
297
            switch (lua_type(L, -1)) {
 
298
            case LUA_TNIL:
 
299
                /* do nothing */
 
300
                break;
 
301
 
 
302
            case LUA_TBOOLEAN:
 
303
                if (lua_toboolean(L, -1)) {
 
304
                    vars_action |= NGX_HTTP_LUA_COPY_ALL_VARS;
 
305
                }
 
306
                break;
 
307
 
 
308
            default:
 
309
                return luaL_error(L, "Bad copy_all_vars option value");
 
310
            }
 
311
 
 
312
            lua_pop(L, 1);
 
313
 
 
314
            dd("queries query uri opts: %d", lua_gettop(L));
 
315
 
 
316
            /* check the "method" option */
238
317
 
239
318
            lua_getfield(L, 4, "method");
240
319
 
253
332
 
254
333
            lua_pop(L, 1);
255
334
 
256
 
            /* check the body option */
 
335
            dd("queries query uri opts: %d", lua_gettop(L));
 
336
 
 
337
            /* check the "ctx" option */
 
338
 
 
339
            lua_getfield(L, 4, "ctx");
 
340
 
 
341
            type = lua_type(L, -1);
 
342
 
 
343
            if (type != LUA_TNIL) {
 
344
                if (type != LUA_TTABLE) {
 
345
                    return luaL_error(L, "Bad ctx option value type %s, "
 
346
                            "expected a Lua table", lua_typename(L, type));
 
347
                }
 
348
 
 
349
                custom_ctx = 1;
 
350
 
 
351
            } else {
 
352
                lua_pop(L, 1);
 
353
            }
 
354
 
 
355
            dd("queries query uri opts ctx?: %d", lua_gettop(L));
 
356
 
 
357
            /* check the "body" option */
257
358
 
258
359
            lua_getfield(L, 4, "body");
259
360
 
295
396
                }
296
397
            }
297
398
 
298
 
            lua_pop(L, 2); /* pop body and opts table */
 
399
            lua_pop(L, 1); /* pop the body */
 
400
 
 
401
            /* stack: queries query uri opts ctx? */
 
402
 
 
403
            lua_remove(L, 4);
 
404
 
 
405
            /* stack: queries query uri ctx? */
 
406
 
 
407
            dd("queries query uri ctx?: %d", lua_gettop(L));
 
408
 
299
409
        } else {
300
410
            method = NGX_HTTP_GET;
301
411
        }
302
412
 
 
413
        /* stack: queries query uri ctx? */
 
414
 
303
415
        n = lua_gettop(L);
304
416
        dd("top size so far: %d", n);
305
417
 
379
491
 
380
492
        ngx_http_set_ctx(sr, sr_ctx, ngx_http_lua_module);
381
493
 
382
 
        rc = ngx_http_lua_adjust_subrequest(sr, method, body, share_all_vars);
 
494
        rc = ngx_http_lua_adjust_subrequest(sr, method, body, vars_action,
 
495
                extra_vars);
383
496
 
384
497
        if (rc != NGX_OK) {
385
498
            return luaL_error(L, "failed to adjust the subrequest: %d",
386
499
                    (int) rc);
387
500
        }
388
501
 
389
 
        lua_pop(L, 2); /* pop the subrequest argument and uri */
 
502
        dd("queries query uri opts ctx? %d", lua_gettop(L));
 
503
 
 
504
        /* stack: queries query uri ctx? */
 
505
 
 
506
        if (custom_ctx) {
 
507
            ngx_http_lua_ngx_set_ctx_helper(L, sr, sr_ctx, -1);
 
508
            lua_pop(L, 3);
 
509
 
 
510
        } else {
 
511
            lua_pop(L, 2);
 
512
        }
 
513
 
 
514
        /* stack: queries */
 
515
    }
 
516
 
 
517
    if (extra_vars) {
 
518
        ngx_array_destroy(extra_vars);
390
519
    }
391
520
 
392
521
    return lua_yield(L, 0);
395
524
 
396
525
static ngx_int_t
397
526
ngx_http_lua_adjust_subrequest(ngx_http_request_t *sr, ngx_uint_t method,
398
 
        ngx_http_request_body_t *body, unsigned share_all_vars)
 
527
    ngx_http_request_body_t *body, unsigned vars_action,
 
528
    ngx_array_t *extra_vars)
399
529
{
400
530
    ngx_http_request_t          *r;
401
531
    ngx_int_t                    rc;
402
532
    ngx_http_core_main_conf_t   *cmcf;
 
533
    size_t                       size;
403
534
 
404
535
    r = sr->parent;
405
536
 
458
589
        sr->headers_in.headers.last = &sr->headers_in.headers.part;
459
590
    }
460
591
 
461
 
    if (! share_all_vars) {
 
592
    if (!(vars_action & NGX_HTTP_LUA_SHARE_ALL_VARS)) {
462
593
        /* we do not inherit the parent request's variables */
463
594
        cmcf = ngx_http_get_module_main_conf(sr, ngx_http_core_module);
464
595
 
465
 
        sr->variables = ngx_pcalloc(sr->pool, cmcf->variables.nelts
466
 
                                * sizeof(ngx_http_variable_value_t));
467
 
 
468
 
        if (sr->variables == NULL) {
469
 
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
470
 
        }
 
596
        size = cmcf->variables.nelts * sizeof(ngx_http_variable_value_t);
 
597
 
 
598
        if (vars_action & NGX_HTTP_LUA_COPY_ALL_VARS) {
 
599
 
 
600
            sr->variables = ngx_palloc(sr->pool, size);
 
601
            if (sr->variables == NULL) {
 
602
                return NGX_ERROR;
 
603
            }
 
604
 
 
605
            ngx_memcpy(sr->variables, r->variables, size);
 
606
 
 
607
        } else {
 
608
 
 
609
            /* we do not inherit the parent request's variables */
 
610
 
 
611
            sr->variables = ngx_pcalloc(sr->pool, size);
 
612
            if (sr->variables == NULL) {
 
613
                return NGX_ERROR;
 
614
            }
 
615
        }
 
616
    }
 
617
 
 
618
    return ngx_http_lua_subrequest_add_extra_vars(sr, extra_vars);
 
619
}
 
620
 
 
621
 
 
622
static ngx_int_t
 
623
ngx_http_lua_subrequest_add_extra_vars(ngx_http_request_t *sr,
 
624
       ngx_array_t *extra_vars)
 
625
{
 
626
    ngx_http_core_main_conf_t   *cmcf;
 
627
    ngx_http_variable_t         *v;
 
628
    ngx_http_variable_value_t   *vv;
 
629
    u_char                      *val;
 
630
    u_char                      *p;
 
631
    ngx_uint_t                   i, hash;
 
632
    ngx_str_t                    name;
 
633
    size_t                       len;
 
634
    ngx_hash_t                  *variables_hash;
 
635
    ngx_keyval_t                *var;
 
636
 
 
637
    /* set any extra variables that were passed to the subrequest */
 
638
 
 
639
    if (extra_vars == NULL || extra_vars->nelts == 0) {
 
640
        return NGX_OK;
 
641
    }
 
642
 
 
643
    cmcf = ngx_http_get_module_main_conf(sr, ngx_http_core_module);
 
644
 
 
645
    variables_hash = &cmcf->variables_hash;
 
646
 
 
647
    var = extra_vars->elts;
 
648
 
 
649
    for (i = 0; i < extra_vars->nelts; i++, var++) {
 
650
        /* copy the variable's name and value because they are allocated
 
651
         * by the lua VM */
 
652
 
 
653
        len = var->key.len + var->value.len;
 
654
 
 
655
        p = ngx_pnalloc(sr->pool, len);
 
656
        if (p == NULL) {
 
657
            return NGX_ERROR;
 
658
        }
 
659
 
 
660
        name.data = p;
 
661
        name.len = var->key.len;
 
662
 
 
663
        p = ngx_copy(p, var->key.data, var->key.len);
 
664
 
 
665
        hash = ngx_hash_strlow(name.data, name.data, name.len);
 
666
 
 
667
        val = p;
 
668
        len = var->value.len;
 
669
 
 
670
        ngx_memcpy(p, var->value.data, len);
 
671
 
 
672
        v = ngx_hash_find(variables_hash, hash, name.data, name.len);
 
673
 
 
674
        if (v) {
 
675
            if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) {
 
676
                ngx_log_error(NGX_LOG_ERR, sr->connection->log, 0,
 
677
                              "variable \"%V\" not changeable", &name);
 
678
                return NGX_HTTP_INTERNAL_SERVER_ERROR;
 
679
            }
 
680
 
 
681
            if (v->set_handler) {
 
682
                vv = ngx_palloc(sr->pool, sizeof(ngx_http_variable_value_t));
 
683
                if (vv == NULL) {
 
684
                    return NGX_ERROR;
 
685
                }
 
686
 
 
687
                vv->valid = 1;
 
688
                vv->not_found = 0;
 
689
                vv->no_cacheable = 0;
 
690
 
 
691
                vv->data = val;
 
692
                vv->len = len;
 
693
 
 
694
                v->set_handler(sr, vv, v->data);
 
695
 
 
696
                ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sr->connection->log, 0,
 
697
                      "variable \"%V\" set to value \"%v\"", &name, vv);
 
698
 
 
699
                continue;
 
700
            }
 
701
 
 
702
            if (v->flags & NGX_HTTP_VAR_INDEXED) {
 
703
                vv = &sr->variables[v->index];
 
704
 
 
705
                vv->valid = 1;
 
706
                vv->not_found = 0;
 
707
                vv->no_cacheable = 0;
 
708
 
 
709
                vv->data = val;
 
710
                vv->len = len;
 
711
 
 
712
                ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sr->connection->log, 0,
 
713
                      "variable \"%V\" set to value \"%v\"", &name, vv);
 
714
 
 
715
                continue;
 
716
            }
 
717
        }
 
718
 
 
719
        ngx_log_error(NGX_LOG_ERR, sr->connection->log, 0,
 
720
                      "variable \"%V\" cannot be assigned a value (maybe you "
 
721
                      "forgot to define it first?) ", &name);
 
722
 
 
723
        return NGX_ERROR;
471
724
    }
472
725
 
473
726
    return NGX_OK;
474
727
}
475
728
 
476
729
 
 
730
static void
 
731
ngx_http_lua_process_vars_option(ngx_http_request_t *r, lua_State *L,
 
732
        int table, ngx_array_t **varsp)
 
733
{
 
734
    ngx_array_t         *vars;
 
735
    ngx_keyval_t        *var;
 
736
 
 
737
    if (table < 0) {
 
738
        table = lua_gettop(L) + table + 1;
 
739
    }
 
740
 
 
741
    vars = *varsp;
 
742
 
 
743
    if (vars == NULL) {
 
744
 
 
745
        vars = ngx_array_create(r->pool, 4, sizeof(ngx_keyval_t));
 
746
        if (vars == NULL) {
 
747
            dd("here");
 
748
            luaL_error(L, "out of memory");
 
749
            return;
 
750
        }
 
751
 
 
752
        *varsp = vars;
 
753
    }
 
754
 
 
755
    lua_pushnil(L);
 
756
    while (lua_next(L, table) != 0) {
 
757
 
 
758
        if (lua_type(L, -2) != LUA_TSTRING) {
 
759
            luaL_error(L, "attempt to use a non-string key in the "
 
760
                    "\"vars\" option table");
 
761
            return;
 
762
        }
 
763
 
 
764
        if (!lua_isstring(L, -1)) {
 
765
            luaL_error(L, "attempt to use bad variable value type %s",
 
766
                       luaL_typename(L, -1));
 
767
        }
 
768
 
 
769
        var = ngx_array_push(vars);
 
770
        if (var == NULL) {
 
771
            dd("here");
 
772
            luaL_error(L, "out of memory");
 
773
            return;
 
774
        }
 
775
 
 
776
        var->key.data = (u_char *) lua_tolstring(L, -2, &var->key.len);
 
777
        var->value.data = (u_char *) lua_tolstring(L, -1, &var->value.len);
 
778
 
 
779
        lua_pop(L, 1);
 
780
    }
 
781
}
 
782
 
 
783
 
477
784
ngx_int_t
478
785
ngx_http_lua_post_subrequest(ngx_http_request_t *r, void *data, ngx_int_t rc)
479
786
{
669
976
 
670
977
    h->value.len = ngx_sprintf(h->value.data, "%O", len) - h->value.data;
671
978
 
672
 
    h->hash = 1;
 
979
    h->hash = ngx_hash(ngx_hash(ngx_hash(ngx_hash(ngx_hash(ngx_hash(ngx_hash(
 
980
            ngx_hash(ngx_hash(ngx_hash(ngx_hash(ngx_hash(
 
981
            ngx_hash('c', 'o'), 'n'), 't'), 'e'), 'n'), 't'), '-'), 'l'), 'e'),
 
982
            'n'), 'g'), 't'), 'h');
 
983
 
 
984
#if 0
 
985
    dd("content length hash: %lu == %lu", (unsigned long) h->hash,
 
986
            ngx_hash_key_lc((u_char *) "Content-Length",
 
987
            sizeof("Content-Length") - 1));
 
988
#endif
673
989
 
674
990
    dd("r content length: %.*s",
675
991
            (int)r->headers_in.content_length->value.len,
734
1050
 
735
1051
    u_char                  buf[sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1];
736
1052
 
 
1053
    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
 
1054
            "lua handle subrequest responses");
 
1055
 
737
1056
    for (index = 0; index < ctx->nsubreqs; index++) {
738
1057
        dd("summary: reqs %d, subquery %d, waiting %d, req %.*s",
739
1058
                (int) ctx->nsubreqs,