~ubuntu-branches/ubuntu/trusty/nginx/trusty-proposed

« back to all changes in this revision

Viewing changes to src/http/ngx_http_special_response.c

  • Committer: Package Import Robot
  • Author(s): Kartik Mistry
  • Date: 2013-04-25 12:51:45 UTC
  • mfrom: (1.3.28)
  • mto: (1.3.29) (15.1.2 experimental)
  • mto: This revision was merged to the branch mainline in revision 64.
  • Revision ID: package-import@ubuntu.com-20130425125145-ugl0wor6bq0u5eae
Tags: upstream-1.4.0
ImportĀ upstreamĀ versionĀ 1.4.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
 
2
2
/*
3
3
 * Copyright (C) Igor Sysoev
 
4
 * Copyright (C) Nginx, Inc.
4
5
 */
5
6
 
6
7
 
31
32
;
32
33
 
33
34
 
34
 
static u_char ngx_http_msie_stub[] =
35
 
"<!-- The padding to disable MSIE's friendly error page -->" CRLF
36
 
"<!-- The padding to disable MSIE's friendly error page -->" CRLF
37
 
"<!-- The padding to disable MSIE's friendly error page -->" CRLF
38
 
"<!-- The padding to disable MSIE's friendly error page -->" CRLF
39
 
"<!-- The padding to disable MSIE's friendly error page -->" CRLF
40
 
"<!-- The padding to disable MSIE's friendly error page -->" CRLF
 
35
static u_char ngx_http_msie_padding[] =
 
36
"<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
 
37
"<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
 
38
"<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
 
39
"<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
 
40
"<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
 
41
"<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
41
42
;
42
43
 
43
44
 
65
66
;
66
67
 
67
68
 
 
69
static char ngx_http_error_303_page[] =
 
70
"<html>" CRLF
 
71
"<head><title>303 See Other</title></head>" CRLF
 
72
"<body bgcolor=\"white\">" CRLF
 
73
"<center><h1>303 See Other</h1></center>" CRLF
 
74
;
 
75
 
 
76
 
 
77
static char ngx_http_error_307_page[] =
 
78
"<html>" CRLF
 
79
"<head><title>307 Temporary Redirect</title></head>" CRLF
 
80
"<body bgcolor=\"white\">" CRLF
 
81
"<center><h1>307 Temporary Redirect</h1></center>" CRLF
 
82
;
 
83
 
 
84
 
68
85
static char ngx_http_error_400_page[] =
69
86
"<html>" CRLF
70
87
"<head><title>400 Bad Request</title></head>" CRLF
193
210
;
194
211
 
195
212
 
 
213
static char ngx_http_error_494_page[] =
 
214
"<html>" CRLF
 
215
"<head><title>400 Request Header Or Cookie Too Large</title></head>"
 
216
CRLF
 
217
"<body bgcolor=\"white\">" CRLF
 
218
"<center><h1>400 Bad Request</h1></center>" CRLF
 
219
"<center>Request Header Or Cookie Too Large</center>" CRLF
 
220
;
 
221
 
 
222
 
196
223
static char ngx_http_error_495_page[] =
197
224
"<html>" CRLF
198
225
"<head><title>400 The SSL certificate error</title></head>"
233
260
 
234
261
static char ngx_http_error_501_page[] =
235
262
"<html>" CRLF
236
 
"<head><title>501 Method Not Implemented</title></head>" CRLF
 
263
"<head><title>501 Not Implemented</title></head>" CRLF
237
264
"<body bgcolor=\"white\">" CRLF
238
 
"<center><h1>501 Method Not Implemented</h1></center>" CRLF
 
265
"<center><h1>501 Not Implemented</h1></center>" CRLF
239
266
;
240
267
 
241
268
 
275
302
 
276
303
    ngx_null_string,                     /* 201, 204 */
277
304
 
278
 
#define NGX_HTTP_LEVEL_200  1
 
305
#define NGX_HTTP_LAST_2XX  202
 
306
#define NGX_HTTP_OFF_3XX   (NGX_HTTP_LAST_2XX - 201)
279
307
 
280
308
    /* ngx_null_string, */               /* 300 */
281
309
    ngx_string(ngx_http_error_301_page),
282
310
    ngx_string(ngx_http_error_302_page),
283
 
    ngx_null_string,                     /* 303 */
 
311
    ngx_string(ngx_http_error_303_page),
 
312
    ngx_null_string,                     /* 304 */
 
313
    ngx_null_string,                     /* 305 */
 
314
    ngx_null_string,                     /* 306 */
 
315
    ngx_string(ngx_http_error_307_page),
284
316
 
285
 
#define NGX_HTTP_LEVEL_300  3
 
317
#define NGX_HTTP_LAST_3XX  308
 
318
#define NGX_HTTP_OFF_4XX   (NGX_HTTP_LAST_3XX - 301 + NGX_HTTP_OFF_3XX)
286
319
 
287
320
    ngx_string(ngx_http_error_400_page),
288
321
    ngx_string(ngx_http_error_401_page),
302
335
    ngx_string(ngx_http_error_415_page),
303
336
    ngx_string(ngx_http_error_416_page),
304
337
 
305
 
#define NGX_HTTP_LEVEL_400  17
 
338
#define NGX_HTTP_LAST_4XX  417
 
339
#define NGX_HTTP_OFF_5XX   (NGX_HTTP_LAST_4XX - 400 + NGX_HTTP_OFF_4XX)
306
340
 
 
341
    ngx_string(ngx_http_error_494_page), /* 494, request header too large */
307
342
    ngx_string(ngx_http_error_495_page), /* 495, https certificate error */
308
343
    ngx_string(ngx_http_error_496_page), /* 496, https no certificate */
309
344
    ngx_string(ngx_http_error_497_page), /* 497, http to https */
318
353
    ngx_null_string,                     /* 505 */
319
354
    ngx_null_string,                     /* 506 */
320
355
    ngx_string(ngx_http_error_507_page)
 
356
 
 
357
#define NGX_HTTP_LAST_5XX  508
 
358
 
321
359
};
322
360
 
323
361
 
331
369
    ngx_http_err_page_t       *err_page;
332
370
    ngx_http_core_loc_conf_t  *clcf;
333
371
 
334
 
    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
335
 
                   "http special response: %d, \"%V\"", error, &r->uri);
 
372
    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
 
373
                   "http special response: %d, \"%V?%V\"",
 
374
                   error, &r->uri, &r->args);
336
375
 
337
376
    r->err_status = error;
338
377
 
339
 
    if (r->keepalive != 0) {
 
378
    if (r->keepalive) {
340
379
        switch (error) {
341
380
            case NGX_HTTP_BAD_REQUEST:
342
381
            case NGX_HTTP_REQUEST_ENTITY_TOO_LARGE:
345
384
            case NGX_HTTPS_CERT_ERROR:
346
385
            case NGX_HTTPS_NO_CERT:
347
386
            case NGX_HTTP_INTERNAL_SERVER_ERROR:
 
387
            case NGX_HTTP_NOT_IMPLEMENTED:
348
388
                r->keepalive = 0;
349
389
        }
350
390
    }
351
391
 
352
 
    if (r->lingering_close == 1) {
 
392
    if (r->lingering_close) {
353
393
        switch (error) {
354
394
            case NGX_HTTP_BAD_REQUEST:
355
395
            case NGX_HTTP_TO_HTTPS:
378
418
        }
379
419
    }
380
420
 
 
421
    r->expect_tested = 1;
 
422
 
381
423
    if (ngx_http_discard_request_body(r) != NGX_OK) {
382
 
        error = NGX_HTTP_INTERNAL_SERVER_ERROR;
 
424
        r->keepalive = 0;
383
425
    }
384
426
 
385
427
    if (clcf->msie_refresh
393
435
    if (error == NGX_HTTP_CREATED) {
394
436
        /* 201 */
395
437
        err = 0;
396
 
        r->header_only = 1;
397
438
 
398
439
    } else if (error == NGX_HTTP_NO_CONTENT) {
399
440
        /* 204 */
400
441
        err = 0;
401
442
 
402
 
    } else if (error < NGX_HTTP_BAD_REQUEST) {
 
443
    } else if (error >= NGX_HTTP_MOVED_PERMANENTLY
 
444
               && error < NGX_HTTP_LAST_3XX)
 
445
    {
403
446
        /* 3XX */
404
 
        err = error - NGX_HTTP_MOVED_PERMANENTLY + NGX_HTTP_LEVEL_200;
 
447
        err = error - NGX_HTTP_MOVED_PERMANENTLY + NGX_HTTP_OFF_3XX;
405
448
 
406
 
    } else if (error < NGX_HTTP_OWN_CODES) {
 
449
    } else if (error >= NGX_HTTP_BAD_REQUEST
 
450
               && error < NGX_HTTP_LAST_4XX)
 
451
    {
407
452
        /* 4XX */
408
 
        err = error - NGX_HTTP_BAD_REQUEST + NGX_HTTP_LEVEL_200
409
 
                                           + NGX_HTTP_LEVEL_300;
 
453
        err = error - NGX_HTTP_BAD_REQUEST + NGX_HTTP_OFF_4XX;
410
454
 
411
 
    } else {
 
455
    } else if (error >= NGX_HTTP_NGINX_CODES
 
456
               && error < NGX_HTTP_LAST_5XX)
 
457
    {
412
458
        /* 49X, 5XX */
413
 
        err = error - NGX_HTTP_OWN_CODES + NGX_HTTP_LEVEL_200
414
 
                                         + NGX_HTTP_LEVEL_300
415
 
                                         + NGX_HTTP_LEVEL_400;
 
459
        err = error - NGX_HTTP_NGINX_CODES + NGX_HTTP_OFF_5XX;
416
460
        switch (error) {
417
461
            case NGX_HTTP_TO_HTTPS:
418
462
            case NGX_HTTPS_CERT_ERROR:
419
463
            case NGX_HTTPS_NO_CERT:
 
464
            case NGX_HTTP_REQUEST_HEADER_TOO_LARGE:
420
465
                r->err_status = NGX_HTTP_BAD_REQUEST;
421
466
                break;
422
467
        }
 
468
 
 
469
    } else {
 
470
        /* unknown code, zero body */
 
471
        err = 0;
423
472
    }
424
473
 
425
474
    return ngx_http_send_special_response(r, clcf, err);
426
475
}
427
476
 
428
477
 
 
478
ngx_int_t
 
479
ngx_http_filter_finalize_request(ngx_http_request_t *r, ngx_module_t *m,
 
480
    ngx_int_t error)
 
481
{
 
482
    void       *ctx;
 
483
    ngx_int_t   rc;
 
484
 
 
485
    ngx_http_clean_header(r);
 
486
 
 
487
    ctx = NULL;
 
488
 
 
489
    if (m) {
 
490
        ctx = r->ctx[m->ctx_index];
 
491
    }
 
492
 
 
493
    /* clear the modules contexts */
 
494
    ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module);
 
495
 
 
496
    if (m) {
 
497
        r->ctx[m->ctx_index] = ctx;
 
498
    }
 
499
 
 
500
    r->filter_finalize = 1;
 
501
 
 
502
    rc = ngx_http_special_response_handler(r, error);
 
503
 
 
504
    /* NGX_ERROR resets any pending data */
 
505
 
 
506
    switch (rc) {
 
507
 
 
508
    case NGX_OK:
 
509
    case NGX_DONE:
 
510
        return NGX_ERROR;
 
511
 
 
512
    default:
 
513
        return rc;
 
514
    }
 
515
}
 
516
 
 
517
 
 
518
void
 
519
ngx_http_clean_header(ngx_http_request_t *r)
 
520
{
 
521
    ngx_memzero(&r->headers_out.status,
 
522
                sizeof(ngx_http_headers_out_t)
 
523
                    - offsetof(ngx_http_headers_out_t, status));
 
524
 
 
525
    r->headers_out.headers.part.nelts = 0;
 
526
    r->headers_out.headers.part.next = NULL;
 
527
    r->headers_out.headers.last = &r->headers_out.headers.part;
 
528
 
 
529
    r->headers_out.content_length_n = -1;
 
530
    r->headers_out.last_modified_time = -1;
 
531
}
 
532
 
 
533
 
429
534
static ngx_int_t
430
535
ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page)
431
536
{
432
 
    u_char                     ch, *p, *last;
433
 
    ngx_str_t                 *uri, *args, u, a;
 
537
    ngx_int_t                  overwrite;
 
538
    ngx_str_t                  uri, args;
434
539
    ngx_table_elt_t           *location;
435
540
    ngx_http_core_loc_conf_t  *clcf;
436
541
 
437
 
    r->err_status = err_page->overwrite;
438
 
 
439
 
    r->zero_in_uri = 0;
440
 
 
441
 
    if (err_page->uri_lengths) {
442
 
        if (ngx_http_script_run(r, &u, err_page->uri_lengths->elts, 0,
443
 
                                err_page->uri_values->elts)
444
 
            == NULL)
445
 
        {
446
 
            return NGX_ERROR;
447
 
        }
448
 
 
449
 
        p = u.data;
450
 
        uri = &u;
451
 
        args = NULL;
452
 
 
453
 
        if (*p == '/') {
454
 
 
455
 
            last = p + uri->len;
456
 
 
457
 
            while (p < last) {
458
 
 
459
 
                ch = *p++;
460
 
 
461
 
                if (ch == '?') {
462
 
                    a.len = last - p;
463
 
                    a.data = p;
464
 
                    args = &a;
465
 
 
466
 
                    u.len = p - 1 - u.data;
467
 
 
468
 
                    while (p < last) {
469
 
                        if (*p++ == '\0') {
470
 
                            r->zero_in_uri = 1;
471
 
                            break;
472
 
                        }
473
 
                    }
474
 
 
475
 
                    break;
476
 
                }
477
 
 
478
 
                if (ch == '\0') {
479
 
                    r->zero_in_uri = 1;
480
 
                    continue;
481
 
                }
482
 
            }
483
 
        }
484
 
 
485
 
    } else {
486
 
        uri = &err_page->uri;
487
 
        args = &err_page->args;
488
 
    }
489
 
 
490
 
    if (uri->data[0] == '/') {
 
542
    overwrite = err_page->overwrite;
 
543
 
 
544
    if (overwrite && overwrite != NGX_HTTP_OK) {
 
545
        r->expect_tested = 1;
 
546
    }
 
547
 
 
548
    if (overwrite >= 0) {
 
549
        r->err_status = overwrite;
 
550
    }
 
551
 
 
552
    if (ngx_http_complex_value(r, &err_page->value, &uri) != NGX_OK) {
 
553
        return NGX_ERROR;
 
554
    }
 
555
 
 
556
    if (uri.data[0] == '/') {
 
557
 
 
558
        if (err_page->value.lengths) {
 
559
            ngx_http_split_args(r, &uri, &args);
 
560
 
 
561
        } else {
 
562
            args = err_page->args;
 
563
        }
491
564
 
492
565
        if (r->method != NGX_HTTP_HEAD) {
493
566
            r->method = NGX_HTTP_GET;
494
567
            r->method_name = ngx_http_get_name;
495
568
        }
496
569
 
497
 
        return ngx_http_internal_redirect(r, uri, args);
 
570
        return ngx_http_internal_redirect(r, &uri, &args);
498
571
    }
499
572
 
500
 
    if (uri->data[0] == '@') {
501
 
        return ngx_http_named_location(r, uri);
 
573
    if (uri.data[0] == '@') {
 
574
        return ngx_http_named_location(r, &uri);
502
575
    }
503
576
 
504
577
    location = ngx_list_push(&r->headers_out.headers);
507
580
        return NGX_ERROR;
508
581
    }
509
582
 
510
 
    r->err_status = NGX_HTTP_MOVED_TEMPORARILY;
 
583
    if (overwrite != NGX_HTTP_MOVED_PERMANENTLY
 
584
        && overwrite != NGX_HTTP_MOVED_TEMPORARILY
 
585
        && overwrite != NGX_HTTP_SEE_OTHER
 
586
        && overwrite != NGX_HTTP_TEMPORARY_REDIRECT)
 
587
    {
 
588
        r->err_status = NGX_HTTP_MOVED_TEMPORARILY;
 
589
    }
511
590
 
512
591
    location->hash = 1;
513
 
    location->key.len = sizeof("Location") - 1;
514
 
    location->key.data = (u_char *) "Location";
515
 
    location->value = *uri;
 
592
    ngx_str_set(&location->key, "Location");
 
593
    location->value = uri;
 
594
 
 
595
    ngx_http_clear_location(r);
516
596
 
517
597
    r->headers_out.location = location;
518
598
 
522
602
        return ngx_http_send_refresh(r);
523
603
    }
524
604
 
525
 
    return ngx_http_send_special_response(r, clcf, NGX_HTTP_MOVED_TEMPORARILY
 
605
    return ngx_http_send_special_response(r, clcf, r->err_status
526
606
                                                   - NGX_HTTP_MOVED_PERMANENTLY
527
 
                                                   + NGX_HTTP_LEVEL_200);
 
607
                                                   + NGX_HTTP_OFF_3XX);
528
608
}
529
609
 
530
610
 
550
630
 
551
631
    msie_padding = 0;
552
632
 
553
 
    if (!r->zero_body) {
554
 
        if (ngx_http_error_pages[err].len) {
555
 
            r->headers_out.content_length_n = ngx_http_error_pages[err].len
556
 
                                              + len;
557
 
            if (clcf->msie_padding
558
 
                && r->headers_in.msie
559
 
                && r->http_version >= NGX_HTTP_VERSION_10
560
 
                && err >= NGX_HTTP_LEVEL_300)
561
 
            {
562
 
                r->headers_out.content_length_n +=
563
 
                                                sizeof(ngx_http_msie_stub) - 1;
564
 
                msie_padding = 1;
565
 
            }
566
 
 
567
 
            r->headers_out.content_type_len = sizeof("text/html") - 1;
568
 
            r->headers_out.content_type.len = sizeof("text/html") - 1;
569
 
            r->headers_out.content_type.data = (u_char *) "text/html";
570
 
 
571
 
        } else {
572
 
            r->headers_out.content_length_n = -1;
 
633
    if (ngx_http_error_pages[err].len) {
 
634
        r->headers_out.content_length_n = ngx_http_error_pages[err].len + len;
 
635
        if (clcf->msie_padding
 
636
            && (r->headers_in.msie || r->headers_in.chrome)
 
637
            && r->http_version >= NGX_HTTP_VERSION_10
 
638
            && err >= NGX_HTTP_OFF_4XX)
 
639
        {
 
640
            r->headers_out.content_length_n +=
 
641
                                         sizeof(ngx_http_msie_padding) - 1;
 
642
            msie_padding = 1;
573
643
        }
574
644
 
 
645
        r->headers_out.content_type_len = sizeof("text/html") - 1;
 
646
        ngx_str_set(&r->headers_out.content_type, "text/html");
 
647
        r->headers_out.content_type_lowcase = NULL;
 
648
 
575
649
    } else {
576
650
        r->headers_out.content_length_n = 0;
577
 
        err = 0;
578
651
    }
579
652
 
580
653
    if (r->headers_out.content_length) {
584
657
 
585
658
    ngx_http_clear_accept_ranges(r);
586
659
    ngx_http_clear_last_modified(r);
 
660
    ngx_http_clear_etag(r);
587
661
 
588
662
    rc = ngx_http_send_header(r);
589
663
 
592
666
    }
593
667
 
594
668
    if (ngx_http_error_pages[err].len == 0) {
595
 
        return NGX_OK;
 
669
        return ngx_http_send_special(r, NGX_HTTP_LAST);
596
670
    }
597
671
 
598
672
    b = ngx_calloc_buf(r->pool);
627
701
        }
628
702
 
629
703
        b->memory = 1;
630
 
        b->pos = ngx_http_msie_stub;
631
 
        b->last = ngx_http_msie_stub + sizeof(ngx_http_msie_stub) - 1;
 
704
        b->pos = ngx_http_msie_padding;
 
705
        b->last = ngx_http_msie_padding + sizeof(ngx_http_msie_padding) - 1;
632
706
 
633
707
        out[1].next = &out[2];
634
708
        out[2].buf = b;
667
741
    r->err_status = NGX_HTTP_OK;
668
742
 
669
743
    r->headers_out.content_type_len = sizeof("text/html") - 1;
670
 
    r->headers_out.content_type.len = sizeof("text/html") - 1;
671
 
    r->headers_out.content_type.data = (u_char *) "text/html";
 
744
    ngx_str_set(&r->headers_out.content_type, "text/html");
 
745
    r->headers_out.content_type_lowcase = NULL;
672
746
 
673
747
    r->headers_out.location->hash = 0;
674
748
    r->headers_out.location = NULL;
682
756
 
683
757
    ngx_http_clear_accept_ranges(r);
684
758
    ngx_http_clear_last_modified(r);
 
759
    ngx_http_clear_etag(r);
685
760
 
686
761
    rc = ngx_http_send_header(r);
687
762