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 "<html><head><title>Error</title></head>" 20 "<body>Error.</body></html>\r\n"; 21 22 23 void 24 nxt_http_request_error(nxt_task_t *task, nxt_http_request_t *r, 25 nxt_http_status_t status) 26 { 27 nxt_http_field_t *content_type; 28 29 nxt_debug(task, "http request error: %d", status); 30 31 if (r->header_sent || r->error) { 32 goto fail; 33 } 34 35 r->error = (status == NXT_HTTP_INTERNAL_SERVER_ERROR); 36 37 r->status = status; 38 39 r->resp.fields = nxt_list_create(r->mem_pool, 8, sizeof(nxt_http_field_t)); 40 if (nxt_slow_path(r->resp.fields == NULL)) { 41 goto fail; 42 } 43 44 content_type = nxt_list_zero_add(r->resp.fields); 45 if (nxt_slow_path(content_type == NULL)) { 46 goto fail; 47 } 48 49 nxt_http_field_set(content_type, "Content-Type", "text/html"); 50 51 r->resp.content_length = NULL; 52 r->resp.content_length_n = nxt_length(error); 53 54 nxt_http_request_header_send(task, r); 55 56 r->state = &nxt_http_request_send_error_body_state; 57 58 nxt_work_queue_add(&task->thread->engine->fast_work_queue, 59 nxt_http_request_send_error_body, task, r, NULL); 60 return; 61 62 fail: 63 64 nxt_http_request_error_handler(task, r, r->proto.any); 65 } 66 67 68 static const nxt_http_request_state_t nxt_http_request_send_error_body_state 69 nxt_aligned(64) = 70 { 71 .error_handler = nxt_http_request_error_handler, 72 }; 73 74 75 static void 76 nxt_http_request_send_error_body(nxt_task_t *task, void *obj, void *data) 77 { 78 nxt_buf_t *out; 79 nxt_http_request_t *r; 80 81 r = obj; 82 83 nxt_debug(task, "http request send error body"); 84 85 out = nxt_http_buf_mem(task, r, 0); 86 if (nxt_slow_path(out == NULL)) { 87 goto fail; 88 } 89 90 out->mem.start = (u_char *) error; 91 out->mem.pos = out->mem.start; 92 out->mem.free = out->mem.start + nxt_length(error); 93 out->mem.end = out->mem.free; 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