diff --git a/src/connections.c b/src/connections.c index 616e18b2..799317a3 100644 --- a/src/connections.c +++ b/src/connections.c @@ -257,6 +257,7 @@ static void connection_handle_response_end_state(server *srv, connection *con) { } } +__attribute_cold__ static void connection_handle_errdoc_init(connection *con) { /* modules that produce headers required with error response should * typically also produce an error document. Make an exception for @@ -278,6 +279,64 @@ static void connection_handle_errdoc_init(connection *con) { } } +__attribute_cold__ +static void connection_handle_errdoc(connection *con) { + if (con->mode == DIRECT + ? con->error_handler_saved_status >= 65535 + : (!con->conf.error_intercept || con->error_handler_saved_status)) + return; + + connection_handle_errdoc_init(con); + con->file_finished = 1; + + server * const srv = con->srv; + + /* try to send static errorfile */ + if (!buffer_string_is_empty(con->conf.errorfile_prefix)) { + buffer_copy_buffer(con->physical.path, con->conf.errorfile_prefix); + buffer_append_int(con->physical.path, con->http_status); + buffer_append_string_len(con->physical.path, CONST_STR_LEN(".html")); + if (0 == http_chunk_append_file(srv, con, con->physical.path)) { + stat_cache_entry *sce = NULL; + if (stat_cache_get_entry(srv, con, con->physical.path, &sce) + != HANDLER_ERROR) { + stat_cache_content_type_get(srv, con, con->physical.path, sce); + http_header_response_set(con, HTTP_HEADER_CONTENT_TYPE, + CONST_STR_LEN("Content-Type"), + CONST_BUF_LEN(sce->content_type)); + } + return; + } + } + + /* build default error-page */ + buffer_reset(con->physical.path); + buffer * const b = srv->tmp_buf; + buffer_copy_string_len(b, CONST_STR_LEN( + "\n" + "\n" + "\n" + " \n" + " ")); + http_status_append(b, con->http_status); + buffer_append_string_len(b, CONST_STR_LEN( + "\n" + " \n" + " \n" + "

")); + http_status_append(b, con->http_status); + buffer_append_string_len(b, CONST_STR_LEN( + "

\n" + " \n" + "\n")); + (void)http_chunk_append_mem(srv, con, CONST_BUF_LEN(b)); + + http_header_response_set(con, HTTP_HEADER_CONTENT_TYPE, + CONST_STR_LEN("Content-Type"), + CONST_STR_LEN("text/html")); +} + static int connection_handle_write_prepare(server *srv, connection *con) { if (con->mode == DIRECT) { /* static files */ @@ -323,65 +382,8 @@ static int connection_handle_write_prepare(server *srv, connection *con) { break; default: /* class: header + body */ /* only custom body for 4xx and 5xx */ - if (con->http_status < 400 || con->http_status >= 600) break; - - if (con->mode != DIRECT && (!con->conf.error_intercept || con->error_handler_saved_status)) break; - if (con->mode == DIRECT && con->error_handler_saved_status >= 65535) break; - - con->file_finished = 0; - - connection_handle_errdoc_init(con); - - /* try to send static errorfile */ - if (!buffer_string_is_empty(con->conf.errorfile_prefix)) { - stat_cache_entry *sce = NULL; - - buffer_copy_buffer(con->physical.path, con->conf.errorfile_prefix); - buffer_append_int(con->physical.path, con->http_status); - buffer_append_string_len(con->physical.path, CONST_STR_LEN(".html")); - - if (0 == http_chunk_append_file(srv, con, con->physical.path)) { - con->file_finished = 1; - if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) { - stat_cache_content_type_get(srv, con, con->physical.path, sce); - http_header_response_set(con, HTTP_HEADER_CONTENT_TYPE, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type)); - } - } - } - - if (!con->file_finished) { - buffer *b = srv->tmp_buf; - - buffer_reset(con->physical.path); - - con->file_finished = 1; - - /* build default error-page */ - buffer_copy_string_len(b, CONST_STR_LEN( - "\n" - "\n" - "\n" - " \n" - " ")); - http_status_append(b, con->http_status); - - buffer_append_string_len(b, CONST_STR_LEN( - "\n" - " \n" - " \n" - "

")); - http_status_append(b, con->http_status); - - buffer_append_string_len(b, CONST_STR_LEN("

\n" - " \n" - "\n" - )); - - (void)http_chunk_append_mem(srv, con, CONST_BUF_LEN(b)); - - http_header_response_set(con, HTTP_HEADER_CONTENT_TYPE, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html")); - } + if (con->http_status >= 400 && con->http_status < 600) + connection_handle_errdoc(con); break; }