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 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 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