mirror of
https://github.com/apache/httpd.git
synced 2025-08-07 04:02:58 +03:00
Process early errors via a dummy HTTP/1.1 request as well
Process early errors via a dummy HTTP/1.1 request as well to ensure that the request gets logged correctly and possible custom error pages are considered. The previous way of directly sending a HTTP/2 answer with the HTTP status code appropriate for the error is more efficient, but does not log the request nor sents a possible custom error page. * modules/http2/h2.h: Add http_status to h2_request struct and define H2_HTTP_STATUS_UNSET. * modules/http2/h2_request.c(h2_request_create_rec): Check if http_status is set for the request and die with the status code it contains if set. * modules/http2/h2_session.c(on_header_cb): Adjust the error condition now that we mark early errors via http_status: Only return an error if the status is not success and http_status is not H2_HTTP_STATUS_UNSET. * modules/http2/h2_stream.c(set_error_response): Set http_status on the request instead of creating headers for a response and a respective brigade. Github: closes #137 git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1881620 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -141,8 +141,19 @@ struct h2_request {
|
|||||||
unsigned int chunked : 1; /* iff request body needs to be forwarded as chunked */
|
unsigned int chunked : 1; /* iff request body needs to be forwarded as chunked */
|
||||||
unsigned int serialize : 1; /* iff this request is written in HTTP/1.1 serialization */
|
unsigned int serialize : 1; /* iff this request is written in HTTP/1.1 serialization */
|
||||||
apr_off_t raw_bytes; /* RAW network bytes that generated this request - if known. */
|
apr_off_t raw_bytes; /* RAW network bytes that generated this request - if known. */
|
||||||
|
int http_status; /* Store a possible HTTP status code that gets
|
||||||
|
* defined before creating the dummy HTTP/1.1
|
||||||
|
* request e.g. due to an error already
|
||||||
|
* detected.
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A possible HTTP status code is not defined yet. See the http_status field
|
||||||
|
* in struct h2_request above for further explanation.
|
||||||
|
*/
|
||||||
|
#define H2_HTTP_STATUS_UNSET (0)
|
||||||
|
|
||||||
typedef struct h2_headers h2_headers;
|
typedef struct h2_headers h2_headers;
|
||||||
|
|
||||||
struct h2_headers {
|
struct h2_headers {
|
||||||
|
@@ -84,6 +84,7 @@ apr_status_t h2_request_rcreate(h2_request **preq, apr_pool_t *pool,
|
|||||||
req->authority = authority;
|
req->authority = authority;
|
||||||
req->path = path;
|
req->path = path;
|
||||||
req->headers = apr_table_make(pool, 10);
|
req->headers = apr_table_make(pool, 10);
|
||||||
|
req->http_status = H2_HTTP_STATUS_UNSET;
|
||||||
if (r->server) {
|
if (r->server) {
|
||||||
req->serialize = h2_config_rgeti(r, H2_CONF_SER_HEADERS);
|
req->serialize = h2_config_rgeti(r, H2_CONF_SER_HEADERS);
|
||||||
}
|
}
|
||||||
@@ -294,7 +295,14 @@ request_rec *h2_request_create_rec(const h2_request *req, conn_rec *c)
|
|||||||
if (!ap_parse_request_line(r) || !ap_check_request_header(r)) {
|
if (!ap_parse_request_line(r) || !ap_check_request_header(r)) {
|
||||||
/* we may have switched to another server still */
|
/* we may have switched to another server still */
|
||||||
r->per_dir_config = r->server->lookup_defaults;
|
r->per_dir_config = r->server->lookup_defaults;
|
||||||
|
if (req->http_status != H2_HTTP_STATUS_UNSET) {
|
||||||
|
access_status = req->http_status;
|
||||||
|
/* Be safe and close the connection */
|
||||||
|
c->keepalive = AP_CONN_CLOSE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
access_status = r->status;
|
access_status = r->status;
|
||||||
|
}
|
||||||
r->status = HTTP_OK;
|
r->status = HTTP_OK;
|
||||||
goto die;
|
goto die;
|
||||||
}
|
}
|
||||||
@@ -302,6 +310,14 @@ request_rec *h2_request_create_rec(const h2_request *req, conn_rec *c)
|
|||||||
/* we may have switched to another server */
|
/* we may have switched to another server */
|
||||||
r->per_dir_config = r->server->lookup_defaults;
|
r->per_dir_config = r->server->lookup_defaults;
|
||||||
|
|
||||||
|
if (req->http_status != H2_HTTP_STATUS_UNSET) {
|
||||||
|
access_status = req->http_status;
|
||||||
|
r->status = HTTP_OK;
|
||||||
|
/* Be safe and close the connection */
|
||||||
|
c->keepalive = AP_CONN_CLOSE;
|
||||||
|
goto die;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add the HTTP_IN filter here to ensure that ap_discard_request_body
|
* Add the HTTP_IN filter here to ensure that ap_discard_request_body
|
||||||
* called by ap_die and by ap_send_error_response works correctly on
|
* called by ap_die and by ap_send_error_response works correctly on
|
||||||
|
@@ -311,7 +311,9 @@ static int on_header_cb(nghttp2_session *ngh2, const nghttp2_frame *frame,
|
|||||||
|
|
||||||
status = h2_stream_add_header(stream, (const char *)name, namelen,
|
status = h2_stream_add_header(stream, (const char *)name, namelen,
|
||||||
(const char *)value, valuelen);
|
(const char *)value, valuelen);
|
||||||
if (status != APR_SUCCESS && !h2_stream_is_ready(stream)) {
|
if (status != APR_SUCCESS
|
||||||
|
&& (!stream->rtmp
|
||||||
|
|| stream->rtmp->http_status == H2_HTTP_STATUS_UNSET)) {
|
||||||
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@@ -639,16 +639,7 @@ void h2_stream_set_request(h2_stream *stream, const h2_request *r)
|
|||||||
static void set_error_response(h2_stream *stream, int http_status)
|
static void set_error_response(h2_stream *stream, int http_status)
|
||||||
{
|
{
|
||||||
if (!h2_stream_is_ready(stream)) {
|
if (!h2_stream_is_ready(stream)) {
|
||||||
conn_rec *c = stream->session->c;
|
stream->rtmp->http_status = http_status;
|
||||||
apr_bucket *b;
|
|
||||||
h2_headers *response;
|
|
||||||
|
|
||||||
response = h2_headers_die(http_status, stream->request, stream->pool);
|
|
||||||
prep_output(stream);
|
|
||||||
b = apr_bucket_eos_create(c->bucket_alloc);
|
|
||||||
APR_BRIGADE_INSERT_HEAD(stream->out_buffer, b);
|
|
||||||
b = h2_bucket_headers_create(c->bucket_alloc, response);
|
|
||||||
APR_BRIGADE_INSERT_HEAD(stream->out_buffer, b);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user