1
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) NGINX, Inc.
5 */
6
7 #include <nxt_router.h>
8 #include <nxt_http.h>
9
10
11 static void nxt_http_request_send_error_body(nxt_task_t *task, void *r,
12 void *data);
13
14
15 static const nxt_http_request_state_t nxt_http_request_send_error_body_state;
16
17
18 static const char error[] =
19 "<!DOCTYPE html>"
20 "<title>Error %03d</title>"
21 "<p>Error %03d.\r\n";
22
23 /* Two %03d (4 chars) patterns are replaced by status code (3 chars). */
24 #define NXT_HTTP_ERROR_LEN (nxt_length(error) - 2)
25
26
27 void
nxt_http_request_error(nxt_task_t * task,nxt_http_request_t * r,nxt_http_status_t status)28 nxt_http_request_error(nxt_task_t *task, nxt_http_request_t *r,
29 nxt_http_status_t status)
30 {
31 nxt_http_field_t *content_type;
32
33 nxt_debug(task, "http request error: %d", status);
34
35 if (r->header_sent || r->error) {
36 goto fail;
37 }
38
39 r->error = (status == NXT_HTTP_INTERNAL_SERVER_ERROR);
40
41 r->status = status;
42
43 r->resp.fields = nxt_list_create(r->mem_pool, 8, sizeof(nxt_http_field_t));
44 if (nxt_slow_path(r->resp.fields == NULL)) {
45 goto fail;
46 }
47
48 content_type = nxt_list_zero_add(r->resp.fields);
49 if (nxt_slow_path(content_type == NULL)) {
50 goto fail;
51 }
52
53 nxt_http_field_set(content_type, "Content-Type", "text/html");
54
55 r->resp.content_length = NULL;
56 r->resp.content_length_n = NXT_HTTP_ERROR_LEN;
57
58 r->state = &nxt_http_request_send_error_body_state;
59
60 nxt_http_request_header_send(task, r,
61 nxt_http_request_send_error_body, NULL);
62 return;
63
64 fail:
65
66 nxt_http_request_error_handler(task, r, r->proto.any);
67 }
68
69
70 static const nxt_http_request_state_t nxt_http_request_send_error_body_state
71 nxt_aligned(64) =
72 {
73 .error_handler = nxt_http_request_error_handler,
74 };
75
76
77 static void
nxt_http_request_send_error_body(nxt_task_t * task,void * obj,void * data)78 nxt_http_request_send_error_body(nxt_task_t *task, void *obj, void *data)
79 {
80 nxt_buf_t *out;
81 nxt_http_request_t *r;
82
83 r = obj;
84
85 nxt_debug(task, "http request send error body");
86
87 out = nxt_http_buf_mem(task, r, NXT_HTTP_ERROR_LEN);
88 if (nxt_slow_path(out == NULL)) {
89 goto fail;
90 }
91
92 out->mem.free = nxt_sprintf(out->mem.pos, out->mem.end, error,
93 r->status, r->status);
94
95 out->next = nxt_http_buf_last(r);
96
97 nxt_http_request_send(task, r, out);
98
99 return;
100
101 fail:
102
103 nxt_http_request_error_handler(task, r, r->proto.any);
104 }
105