1431Sigor@sysoev.ru
2431Sigor@sysoev.ru /*
3431Sigor@sysoev.ru * Copyright (C) Igor Sysoev
4431Sigor@sysoev.ru * Copyright (C) NGINX, Inc.
5431Sigor@sysoev.ru */
6431Sigor@sysoev.ru
7431Sigor@sysoev.ru #include <nxt_router.h>
8431Sigor@sysoev.ru #include <nxt_http.h>
9431Sigor@sysoev.ru
10431Sigor@sysoev.ru
11431Sigor@sysoev.ru static void nxt_http_request_send_error_body(nxt_task_t *task, void *r,
12431Sigor@sysoev.ru void *data);
13431Sigor@sysoev.ru
14431Sigor@sysoev.ru
15608Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_request_send_error_body_state;
16431Sigor@sysoev.ru
17431Sigor@sysoev.ru
18431Sigor@sysoev.ru static const char error[] =
191218Svbart@nginx.com "<!DOCTYPE html>"
201218Svbart@nginx.com "<title>Error %03d</title>"
211218Svbart@nginx.com "<p>Error %03d.\r\n";
221218Svbart@nginx.com
231218Svbart@nginx.com /* Two %03d (4 chars) patterns are replaced by status code (3 chars). */
241218Svbart@nginx.com #define NXT_HTTP_ERROR_LEN (nxt_length(error) - 2)
25431Sigor@sysoev.ru
26431Sigor@sysoev.ru
27431Sigor@sysoev.ru void
nxt_http_request_error(nxt_task_t * task,nxt_http_request_t * r,nxt_http_status_t status)28431Sigor@sysoev.ru nxt_http_request_error(nxt_task_t *task, nxt_http_request_t *r,
29431Sigor@sysoev.ru nxt_http_status_t status)
30431Sigor@sysoev.ru {
31431Sigor@sysoev.ru nxt_http_field_t *content_type;
32431Sigor@sysoev.ru
33431Sigor@sysoev.ru nxt_debug(task, "http request error: %d", status);
34431Sigor@sysoev.ru
35608Sigor@sysoev.ru if (r->header_sent || r->error) {
36431Sigor@sysoev.ru goto fail;
37431Sigor@sysoev.ru }
38431Sigor@sysoev.ru
39608Sigor@sysoev.ru r->error = (status == NXT_HTTP_INTERNAL_SERVER_ERROR);
40608Sigor@sysoev.ru
41431Sigor@sysoev.ru r->status = status;
42431Sigor@sysoev.ru
43431Sigor@sysoev.ru r->resp.fields = nxt_list_create(r->mem_pool, 8, sizeof(nxt_http_field_t));
44906Sigor@sysoev.ru if (nxt_slow_path(r->resp.fields == NULL)) {
45431Sigor@sysoev.ru goto fail;
46431Sigor@sysoev.ru }
47431Sigor@sysoev.ru
48431Sigor@sysoev.ru content_type = nxt_list_zero_add(r->resp.fields);
49431Sigor@sysoev.ru if (nxt_slow_path(content_type == NULL)) {
50431Sigor@sysoev.ru goto fail;
51431Sigor@sysoev.ru }
52431Sigor@sysoev.ru
53431Sigor@sysoev.ru nxt_http_field_set(content_type, "Content-Type", "text/html");
54431Sigor@sysoev.ru
55431Sigor@sysoev.ru r->resp.content_length = NULL;
561218Svbart@nginx.com r->resp.content_length_n = NXT_HTTP_ERROR_LEN;
57431Sigor@sysoev.ru
58608Sigor@sysoev.ru r->state = &nxt_http_request_send_error_body_state;
59431Sigor@sysoev.ru
60*1270Sigor@sysoev.ru nxt_http_request_header_send(task, r,
61*1270Sigor@sysoev.ru nxt_http_request_send_error_body, NULL);
62431Sigor@sysoev.ru return;
63431Sigor@sysoev.ru
64431Sigor@sysoev.ru fail:
65431Sigor@sysoev.ru
66608Sigor@sysoev.ru nxt_http_request_error_handler(task, r, r->proto.any);
67431Sigor@sysoev.ru }
68431Sigor@sysoev.ru
69431Sigor@sysoev.ru
70608Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_request_send_error_body_state
71431Sigor@sysoev.ru nxt_aligned(64) =
72431Sigor@sysoev.ru {
73608Sigor@sysoev.ru .error_handler = nxt_http_request_error_handler,
74431Sigor@sysoev.ru };
75431Sigor@sysoev.ru
76431Sigor@sysoev.ru
77431Sigor@sysoev.ru static void
nxt_http_request_send_error_body(nxt_task_t * task,void * obj,void * data)78431Sigor@sysoev.ru nxt_http_request_send_error_body(nxt_task_t *task, void *obj, void *data)
79431Sigor@sysoev.ru {
80608Sigor@sysoev.ru nxt_buf_t *out;
81431Sigor@sysoev.ru nxt_http_request_t *r;
82431Sigor@sysoev.ru
83431Sigor@sysoev.ru r = obj;
84431Sigor@sysoev.ru
85431Sigor@sysoev.ru nxt_debug(task, "http request send error body");
86431Sigor@sysoev.ru
871218Svbart@nginx.com out = nxt_http_buf_mem(task, r, NXT_HTTP_ERROR_LEN);
88431Sigor@sysoev.ru if (nxt_slow_path(out == NULL)) {
89431Sigor@sysoev.ru goto fail;
90431Sigor@sysoev.ru }
91431Sigor@sysoev.ru
921218Svbart@nginx.com out->mem.free = nxt_sprintf(out->mem.pos, out->mem.end, error,
931218Svbart@nginx.com r->status, r->status);
94431Sigor@sysoev.ru
95608Sigor@sysoev.ru out->next = nxt_http_buf_last(r);
96431Sigor@sysoev.ru
97431Sigor@sysoev.ru nxt_http_request_send(task, r, out);
98431Sigor@sysoev.ru
99431Sigor@sysoev.ru return;
100431Sigor@sysoev.ru
101431Sigor@sysoev.ru fail:
102608Sigor@sysoev.ru
103608Sigor@sysoev.ru nxt_http_request_error_handler(task, r, r->proto.any);
104431Sigor@sysoev.ru }
105