~ubuntu-branches/ubuntu/quantal/nginx/quantal-updates

« back to all changes in this revision

Viewing changes to debian/modules/chunkin-nginx-module/src/ngx_http_chunkin_filter_module.c

  • Committer: Package Import Robot
  • Author(s): Kartik Mistry, Kartik Mistry
  • Date: 2011-09-26 10:17:04 UTC
  • mfrom: (4.2.38 sid)
  • Revision ID: package-import@ubuntu.com-20110926101704-x8pxngiujrmkxnn3
Tags: 1.1.4-2
[Kartik Mistry]
* debian/modules:
  + Updated nginx-upload-progress module, Thanks to upstream for fixing issue
    that FTBFS nginx on kFreeBSD-* archs.
  + Updated nginx-lua module to latest upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) agentzh */
 
2
 
 
3
#define DDEBUG 0
 
4
#include "ddebug.h"
 
5
 
 
6
#include <ngx_config.h>
 
7
 
 
8
#include "ngx_http_chunkin_util.h"
 
9
#include "ngx_http_chunkin_filter_module.h"
 
10
#include "ngx_http_chunkin_request_body.h"
 
11
 
 
12
enum {
 
13
    DEFAULT_MAX_CHUNKS_PER_BUF = 512
 
14
};
 
15
 
 
16
static ngx_int_t ngx_http_chunkin_resume_handler(ngx_http_request_t *r);
 
17
 
 
18
static char* ngx_http_chunkin_resume(ngx_conf_t *cf, ngx_command_t *cmd,
 
19
        void *conf);
 
20
 
 
21
static void *ngx_http_chunkin_create_conf(ngx_conf_t *cf);
 
22
static char *ngx_http_chunkin_merge_conf(ngx_conf_t *cf, void *parent,
 
23
    void *child);
 
24
 
 
25
static ngx_int_t ngx_http_chunkin_handler(ngx_http_request_t *r);
 
26
 
 
27
static ngx_int_t ngx_http_chunkin_init(ngx_conf_t *cf);
 
28
 
 
29
static void ngx_http_chunkin_post_read(ngx_http_request_t *r);
 
30
 
 
31
 
 
32
static ngx_command_t  ngx_http_chunkin_commands[] = {
 
33
 
 
34
    { ngx_string("chunkin"),
 
35
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
 
36
      ngx_conf_set_flag_slot,
 
37
      NGX_HTTP_LOC_CONF_OFFSET,
 
38
      offsetof(ngx_http_chunkin_conf_t, enabled),
 
39
      NULL },
 
40
 
 
41
    { ngx_string("chunkin_max_chunks_per_buf"),
 
42
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
 
43
      ngx_conf_set_num_slot,
 
44
      NGX_HTTP_LOC_CONF_OFFSET,
 
45
      offsetof(ngx_http_chunkin_conf_t, max_chunks_per_buf),
 
46
      NULL },
 
47
 
 
48
    { ngx_string("chunkin_resume"),
 
49
      NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
 
50
      ngx_http_chunkin_resume,
 
51
      NGX_HTTP_LOC_CONF_OFFSET,
 
52
      0,
 
53
      NULL },
 
54
 
 
55
    { ngx_string("chunkin_keepalive"),
 
56
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF
 
57
          |NGX_HTTP_LIF_CONF|NGX_CONF_FLAG,
 
58
      ngx_conf_set_flag_slot,
 
59
      NGX_HTTP_LOC_CONF_OFFSET,
 
60
      offsetof(ngx_http_chunkin_conf_t, keepalive),
 
61
      NULL },
 
62
 
 
63
      ngx_null_command
 
64
};
 
65
 
 
66
 
 
67
static ngx_http_module_t  ngx_http_chunkin_filter_module_ctx = {
 
68
    NULL,                                 /* preconfiguration */
 
69
    ngx_http_chunkin_init,         /* postconfiguration */
 
70
 
 
71
    NULL,                                  /* create main configuration */
 
72
    NULL,                                  /* init main configuration */
 
73
 
 
74
    NULL,                                  /* create server configuration */
 
75
    NULL,                                  /* merge server configuration */
 
76
 
 
77
    ngx_http_chunkin_create_conf,         /* create location configuration */
 
78
    ngx_http_chunkin_merge_conf           /* merge location configuration */
 
79
};
 
80
 
 
81
 
 
82
ngx_module_t  ngx_http_chunkin_filter_module = {
 
83
    NGX_MODULE_V1,
 
84
    &ngx_http_chunkin_filter_module_ctx,  /* module context */
 
85
    ngx_http_chunkin_commands,            /* module directives */
 
86
    NGX_HTTP_MODULE,                       /* module type */
 
87
    NULL,                                  /* init master */
 
88
    NULL,                                  /* init module */
 
89
    NULL,                                  /* init process */
 
90
    NULL,                                  /* init thread */
 
91
    NULL,                                  /* exit thread */
 
92
    NULL,                                  /* exit process */
 
93
    NULL,                                  /* exit master */
 
94
    NGX_MODULE_V1_PADDING
 
95
};
 
96
 
 
97
 
 
98
static void *
 
99
ngx_http_chunkin_create_conf(ngx_conf_t *cf)
 
100
{
 
101
    ngx_http_chunkin_conf_t  *conf;
 
102
 
 
103
    conf = ngx_palloc(cf->pool, sizeof(ngx_http_chunkin_conf_t));
 
104
    if (conf == NULL) {
 
105
        return NULL;
 
106
    }
 
107
 
 
108
    conf->enabled = NGX_CONF_UNSET;
 
109
    conf->keepalive = NGX_CONF_UNSET;
 
110
    conf->max_chunks_per_buf = NGX_CONF_UNSET_UINT;
 
111
 
 
112
    return conf;
 
113
}
 
114
 
 
115
 
 
116
static char *
 
117
ngx_http_chunkin_merge_conf(ngx_conf_t *cf, void *parent, void *child)
 
118
{
 
119
    ngx_http_chunkin_conf_t *prev = parent;
 
120
    ngx_http_chunkin_conf_t *conf = child;
 
121
 
 
122
    ngx_conf_merge_value(conf->enabled, prev->enabled, 0);
 
123
    ngx_conf_merge_value(conf->keepalive, prev->keepalive, 0);
 
124
    ngx_conf_merge_uint_value(conf->max_chunks_per_buf,
 
125
            prev->max_chunks_per_buf,
 
126
            DEFAULT_MAX_CHUNKS_PER_BUF);
 
127
 
 
128
    return NGX_CONF_OK;
 
129
}
 
130
 
 
131
 
 
132
static ngx_flag_t
 
133
ngx_http_chunkin_is_chunked_encoding(ngx_http_request_t *r)
 
134
{
 
135
    dd("is chunked encoding...");
 
136
 
 
137
    return r->headers_in.transfer_encoding &&
 
138
        r->headers_in.transfer_encoding->value.len >= 7 &&
 
139
        ngx_strcasestrn(r->headers_in.transfer_encoding->value.data,
 
140
                "chunked", 7 - 1);
 
141
}
 
142
 
 
143
 
 
144
static ngx_int_t
 
145
ngx_http_chunkin_init(ngx_conf_t *cf)
 
146
{
 
147
    ngx_http_handler_pt        *h;
 
148
    ngx_http_core_main_conf_t  *cmcf;
 
149
 
 
150
    cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
 
151
 
 
152
    h = ngx_array_push(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers);
 
153
    if (h == NULL) {
 
154
        return NGX_ERROR;
 
155
    }
 
156
 
 
157
    *h = ngx_http_chunkin_handler;
 
158
 
 
159
    return NGX_OK;
 
160
}
 
161
 
 
162
 
 
163
static ngx_int_t
 
164
ngx_http_chunkin_handler(ngx_http_request_t *r)
 
165
{
 
166
    ngx_http_chunkin_ctx_t      *ctx;
 
167
    ngx_http_chunkin_conf_t     *conf;
 
168
    ngx_int_t                   rc;
 
169
 
 
170
    dd("entered chunkin handler...");
 
171
 
 
172
    conf = ngx_http_get_module_loc_conf(r, ngx_http_chunkin_filter_module);
 
173
 
 
174
    if (!conf->enabled || r != r->main) {
 
175
        dd("conf not enabled: %d", (int) conf->enabled);
 
176
 
 
177
        return NGX_DECLINED;
 
178
    }
 
179
 
 
180
    ctx = ngx_http_get_module_ctx(r, ngx_http_chunkin_filter_module);
 
181
 
 
182
    if (ctx == NULL) {
 
183
        dd("ctx not found");
 
184
 
 
185
        return NGX_DECLINED;
 
186
    }
 
187
 
 
188
    if (ctx->done) {
 
189
        return NGX_DECLINED;
 
190
    }
 
191
 
 
192
    if (ctx->waiting_more_body) {
 
193
        return NGX_AGAIN;
 
194
    }
 
195
 
 
196
    dd("reading chunked input eagerly...");
 
197
 
 
198
    /* XXX this is a hack for now */
 
199
 
 
200
    if (conf->keepalive
 
201
            && r->headers_in.connection_type ==
 
202
                NGX_HTTP_CONNECTION_KEEP_ALIVE) {
 
203
        dd("re-enable r->keepalive...");
 
204
        r->keepalive = 1;
 
205
    } else {
 
206
        r->keepalive = 0;
 
207
    }
 
208
 
 
209
    dd_check_read_event_handler(r);
 
210
    dd_check_write_event_handler(r);
 
211
 
 
212
    /*
 
213
    rc = ngx_http_read_client_request_body(r,
 
214
            ngx_http_chunkin_post_read);
 
215
    */
 
216
 
 
217
    ngx_http_chunkin_clear_transfer_encoding(r);
 
218
 
 
219
    r->header_in->pos = r->header_end + sizeof(CRLF) - 1;
 
220
 
 
221
    if (r->header_in->pos > r->header_in->last) {
 
222
        ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
 
223
                      "chunkin: r->header_in->pos overflown");
 
224
 
 
225
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
 
226
    }
 
227
 
 
228
    if (*(r->header_in->pos - 2) != CR || *(r->header_in->pos - 1) != LF) {
 
229
        ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
 
230
                      "chunkin: r->header_in->pos not lead by CRLF");
 
231
 
 
232
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
 
233
    }
 
234
 
 
235
    dd("chunkin handler: header_in->pos: %d", (int)(r->header_in->pos - r->header_in->start));
 
236
 
 
237
    rc = ngx_http_chunkin_read_chunked_request_body(r,
 
238
            ngx_http_chunkin_post_read);
 
239
 
 
240
    if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
 
241
        dd("read client request body returned special response %d", (int) rc);
 
242
        return rc;
 
243
    }
 
244
 
 
245
    dd("read client request body returned %d", (int) rc);
 
246
 
 
247
    if (rc == NGX_AGAIN) {
 
248
        ctx->waiting_more_body = 1;
 
249
 
 
250
        return NGX_AGAIN;
 
251
    }
 
252
 
 
253
    ctx->done = 1;
 
254
 
 
255
    return NGX_DECLINED;
 
256
}
 
257
 
 
258
 
 
259
static void
 
260
ngx_http_chunkin_post_read(ngx_http_request_t *r)
 
261
{
 
262
    ngx_http_chunkin_ctx_t          *ctx;
 
263
 
 
264
    dd("post read");
 
265
 
 
266
    dd_check_read_event_handler(r);
 
267
    dd_check_write_event_handler(r);
 
268
 
 
269
    r->read_event_handler = ngx_http_block_reading;
 
270
 
 
271
    ctx = ngx_http_get_module_ctx(r, ngx_http_chunkin_filter_module);
 
272
 
 
273
    ctx->done = 1;
 
274
 
 
275
    if (ctx->waiting_more_body) {
 
276
        ctx->waiting_more_body = 0;
 
277
        ngx_http_core_run_phases(r);
 
278
    }
 
279
}
 
280
 
 
281
 
 
282
static char* ngx_http_chunkin_resume(ngx_conf_t *cf, ngx_command_t *cmd,
 
283
        void *conf)
 
284
{
 
285
    ngx_http_core_loc_conf_t        *clcf;
 
286
 
 
287
    clcf = ngx_http_conf_get_module_loc_conf(cf,
 
288
                ngx_http_core_module);
 
289
 
 
290
    clcf->handler = ngx_http_chunkin_resume_handler;
 
291
 
 
292
    return NGX_CONF_OK;
 
293
}
 
294
 
 
295
 
 
296
static ngx_int_t
 
297
ngx_http_chunkin_resume_handler(ngx_http_request_t *r) {
 
298
    ngx_int_t                   rc;
 
299
    ngx_http_chunkin_conf_t     *conf;
 
300
    ngx_http_chunkin_ctx_t      *ctx;
 
301
 
 
302
    conf = ngx_http_get_module_loc_conf(r, ngx_http_chunkin_filter_module);
 
303
 
 
304
    dd("method: %.*s (%d)", (int) r->method_name.len, r->method_name.data, (int) r->method);
 
305
 
 
306
    if (!conf->enabled || r != r->main
 
307
            || (r->method != NGX_HTTP_PUT && r->method != NGX_HTTP_POST &&
 
308
                r->method != NGX_HTTP_DELETE))
 
309
    {
 
310
        dd("conf not enabled or in subrequest or not POST nor PUT requests");
 
311
 
 
312
        return NGX_HTTP_LENGTH_REQUIRED;
 
313
    }
 
314
 
 
315
    if (r->method == NGX_HTTP_POST &&
 
316
                ! ngx_http_chunkin_is_chunked_encoding(r->main))
 
317
    {
 
318
        dd("found POST request, but not chunked");
 
319
        return NGX_HTTP_LENGTH_REQUIRED;
 
320
    }
 
321
 
 
322
    dd("chunked request test passed");
 
323
 
 
324
    /* XXX just to fool the nginx core */
 
325
    r->headers_in.content_length_n = 1;
 
326
 
 
327
    ngx_http_chunkin_clear_transfer_encoding(r);
 
328
 
 
329
    ctx = ngx_http_get_module_ctx(r, ngx_http_chunkin_filter_module);
 
330
 
 
331
    if (ctx == NULL) {
 
332
        ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_chunkin_ctx_t));
 
333
        if (ctx == NULL) {
 
334
            return NGX_ERROR;
 
335
        }
 
336
 
 
337
        /* ctx->ignore_body is set to 0 */
 
338
    }
 
339
 
 
340
    r->discard_body = 0;
 
341
    r->error_page = 0;
 
342
    r->err_status = 0;
 
343
 
 
344
#if 0
 
345
    r->method = NGX_HTTP_PUT;
 
346
    r->headers_in.content_length = NULL;
 
347
    r->headers_in.content_length_n = -1;
 
348
#endif
 
349
 
 
350
    rc = ngx_http_chunkin_process_request_header(r);
 
351
    if (rc != NGX_OK) {
 
352
        return rc;
 
353
    }
 
354
 
 
355
#if 0
 
356
    r->plain_http = 1;
 
357
#endif
 
358
 
 
359
    rc = ngx_http_chunkin_process_request(r);
 
360
    if (rc != NGX_OK) {
 
361
        return rc;
 
362
    }
 
363
 
 
364
    return ngx_http_chunkin_internal_redirect(r, &r->main->uri, &r->main->args,
 
365
            ctx);
 
366
}
 
367