summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorStefan Eissing <icing@apache.org>2023-06-21 11:49:13 +0200
committerStefan Eissing <icing@apache.org>2023-06-21 11:49:13 +0200
commitf3004c8956d262e4164fe7ebe2fc5a18f1d29669 (patch)
tree2aad86b5b975827bb57392c5015beaeaba2e689c /server
parentab: Don't print the banner/copyright when -Q is specified. (diff)
downloadapache2-f3004c8956d262e4164fe7ebe2fc5a18f1d29669.tar.xz
apache2-f3004c8956d262e4164fe7ebe2fc5a18f1d29669.zip
*) http_protocol: if there is a request and an error bucket in the input
brigade, always process the request bucket first. This gives the proper context in which to evaluate the error bucket in. Some error access r->method, for example, in their response body. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1910530 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'server')
-rw-r--r--server/protocol.c133
1 files changed, 71 insertions, 62 deletions
diff --git a/server/protocol.c b/server/protocol.c
index 9ca80f6248..f9ab8b52f0 100644
--- a/server/protocol.c
+++ b/server/protocol.c
@@ -1307,7 +1307,7 @@ AP_DECLARE(request_rec *) ap_read_request(conn_rec *conn)
{
int access_status;
apr_bucket_brigade *tmp_bb;
- apr_bucket *e, *bdata = NULL;
+ apr_bucket *e, *bdata = NULL, *berr = NULL;
ap_bucket_request *breq = NULL;
const char *method, *uri, *protocol;
apr_table_t *headers;
@@ -1337,16 +1337,82 @@ AP_DECLARE(request_rec *) ap_read_request(conn_rec *conn)
if (!breq) breq = e->data;
}
else if (AP_BUCKET_IS_ERROR(e)) {
- access_status = ((ap_bucket_error *)(e->data))->status;
- goto die_unusable_input;
+ if (!berr) berr = e;
}
else if (!APR_BUCKET_IS_METADATA(e) && e->length != 0) {
- if (!bdata) bdata = e;;
+ if (!bdata) bdata = e;
break;
}
}
- if (bdata) {
+ if (!breq && !berr) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10389)
+ "request failed: neither request bucket nor error at start of input");
+ access_status = HTTP_INTERNAL_SERVER_ERROR;
+ goto die_unusable_input;
+ }
+
+ if (breq) {
+ /* If there is a request, we always process it, as it defines
+ * the context in which a potential error bucket is handled. */
+ if (apr_pool_is_ancestor(r->pool, breq->pool)) {
+ method = breq->method;
+ uri = breq->uri;
+ protocol = breq->protocol;
+ headers = breq->headers;
+ }
+ else {
+ method = apr_pstrdup(r->pool, breq->method);
+ uri = apr_pstrdup(r->pool, breq->uri);
+ protocol = apr_pstrdup(r->pool, breq->protocol);
+ headers = breq->headers? apr_table_clone(r->pool, breq->headers) : NULL;
+ }
+
+ if (headers) {
+ r->headers_in = headers;
+ }
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
+ "checking request: %s %s %s",
+ method, uri, protocol);
+
+ if (!ap_assign_request_line(r, method, uri, protocol)) {
+ apr_brigade_cleanup(tmp_bb);
+ switch (r->status) {
+ case HTTP_REQUEST_URI_TOO_LARGE:
+ case HTTP_BAD_REQUEST:
+ case HTTP_VERSION_NOT_SUPPORTED:
+ case HTTP_NOT_IMPLEMENTED:
+ if (r->status == HTTP_REQUEST_URI_TOO_LARGE) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00565)
+ "request failed: client's request-line exceeds LimitRequestLine (longer than %d)",
+ r->server->limit_req_line);
+ }
+ else if (!strcmp("-", r->method)) {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00566)
+ "request failed: malformed request line");
+ }
+ access_status = r->status;
+ goto die_unusable_input;
+
+ case HTTP_REQUEST_TIME_OUT:
+ /* Just log, no further action on this connection. */
+ ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, NULL);
+ if (!r->connection->keepalives)
+ ap_run_log_transaction(r);
+ break;
+ }
+ /* Not worth dying with. */
+ conn->keepalive = AP_CONN_CLOSE;
+ apr_pool_destroy(r->pool);
+ goto ignore;
+ }
+ }
+
+ if (berr) {
+ access_status = ((ap_bucket_error *)(berr->data))->status;
+ goto die_unusable_input;
+ }
+ else if (bdata) {
/* Since processing of a request body depends on knowing the request, we
* cannot handle any data here. For example, chunked-encoding filters are
* added after the request is read, so any data buckets here will not
@@ -1358,64 +1424,7 @@ AP_DECLARE(request_rec *) ap_read_request(conn_rec *conn)
access_status = HTTP_INTERNAL_SERVER_ERROR;
goto die_unusable_input;
}
- else if (!breq) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10389)
- "request failed: neither request bucket nor error at start of input");
- access_status = HTTP_INTERNAL_SERVER_ERROR;
- goto die_unusable_input;
- }
-
- if (apr_pool_is_ancestor(r->pool, breq->pool)) {
- method = breq->method;
- uri = breq->uri;
- protocol = breq->protocol;
- headers = breq->headers;
- }
- else {
- method = apr_pstrdup(r->pool, breq->method);
- uri = apr_pstrdup(r->pool, breq->uri);
- protocol = apr_pstrdup(r->pool, breq->protocol);
- headers = breq->headers? apr_table_clone(r->pool, breq->headers) : NULL;
- }
- if (headers) {
- r->headers_in = headers;
- }
- ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
- "checking request: %s %s %s",
- method, uri, protocol);
-
- if (!ap_assign_request_line(r, method, uri, protocol)) {
- apr_brigade_cleanup(tmp_bb);
- switch (r->status) {
- case HTTP_REQUEST_URI_TOO_LARGE:
- case HTTP_BAD_REQUEST:
- case HTTP_VERSION_NOT_SUPPORTED:
- case HTTP_NOT_IMPLEMENTED:
- if (r->status == HTTP_REQUEST_URI_TOO_LARGE) {
- ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00565)
- "request failed: client's request-line exceeds LimitRequestLine (longer than %d)",
- r->server->limit_req_line);
- }
- else if (!strcmp("-", r->method)) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00566)
- "request failed: malformed request line");
- }
- access_status = r->status;
- goto die_unusable_input;
-
- case HTTP_REQUEST_TIME_OUT:
- /* Just log, no further action on this connection. */
- ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, NULL);
- if (!r->connection->keepalives)
- ap_run_log_transaction(r);
- break;
- }
- /* Not worth dying with. */
- conn->keepalive = AP_CONN_CLOSE;
- apr_pool_destroy(r->pool);
- goto ignore;
- }
apr_brigade_cleanup(tmp_bb);
/* We may have been in keep_alive_timeout mode, so toggle back