/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.
*/
/* The authority we carry in h2_request is the 'authority' part of * the URL for the request. r->hostname has stripped any port info that * might have been present. Do we need to add it?
*/ if (!ap_strchr_c(authority, ':')) { if (r->parsed_uri.port_str) { /* Yes, it was there, add it again. */
authority = apr_pstrcat(pool, authority, ":", r->parsed_uri.port_str, NULL);
} elseif (!r->parsed_uri.hostname && r->server && r->server->port) { /* If there was no hostname in the parsed URL, the URL was relative. * In that case, we restore port from our server->port, if it
* is known and not the default port for the scheme. */
apr_port_t defport = apr_uri_port_of_scheme(scheme); if (defport != r->server->port) { /* port info missing and port is not default for scheme: append */
authority = apr_psprintf(pool, "%s:%d", authority,
(int)r->server->port);
}
}
}
if (name[0] == ':') { /* pseudo header, see ch. 8.1.2.3, always should come first */ if (!apr_is_empty_table(req->headers)) {
ap_log_perror(APLOG_MARK, APLOG_ERR, 0, pool,
APLOGNO(02917) "h2_request: pseudo header after request start"); return APR_EGENERAL;
}
r->status = HTTP_OK; /* Until further notice */
r->header_only = 0;
r->the_request = NULL;
/* Begin by presuming any module can make its own path_info assumptions, * until some module interjects and changes the value.
*/
r->used_path_info = AP_REQ_DEFAULT_PATH_INFO;
if (req->authority && !is_connect) { /* for internal handling, we have to simulate that :authority * came in as Host:, RFC 9113 ch. says that mismatches between * :authority and Host: SHOULD be rejected as malformed. However, * we are more lenient and just replace any Host: if we have * an :authority.
*/ constchar *orig_host = apr_table_get(req->headers, "Host"); if (orig_host && strcmp(req->authority, orig_host)) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(10401) "overwriting 'Host: %s' with :authority: %s'",
orig_host, req->authority);
apr_table_setn(r->subprocess_env, "H2_ORIGINAL_HOST", orig_host);
}
apr_table_setn(r->headers_in, "Host", req->authority);
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "set 'Host: %s' from :authority", req->authority);
}
/* Unless we open a byte stream via CONNECT, apply content-length guards. */ if (!is_connect) {
cl = apr_table_get(req->headers, "Content-Length"); if (no_body) { if (!cl && apr_table_get(req->headers, "Content-Type")) { /* If we have a content-type, but already seen eos, no more * data will come. Signal a zero content length explicitly.
*/
apr_table_setn(req->headers, "Content-Length", "0");
}
} #if !AP_HAS_RESPONSE_BUCKETS elseif (!cl) { /* there may be a body and we have internal HTTP/1.1 processing. * If the Content-Length is unspecified, we MUST simulate * chunked Transfer-Encoding. * * HTTP/2 does not need a Content-Length for framing. Ideally * all clients set the EOS flag on the header frame if they * do not intent to send a body. However, forwarding proxies * might just no know at the time and send an empty DATA * frame with EOS much later.
*/
apr_table_mergen(r->headers_in, "Transfer-Encoding", "chunked");
} #endif/* else AP_HAS_RESPONSE_BUCKETS */
}
}
request_rec *h2_create_request_rec(const h2_request *req, conn_rec *c, int no_body)
{ int access_status = HTTP_OK; int is_connect = !ap_cstr_casecmp("CONNECT", req->method);
/* Time to populate r with the data we have. */
r->request_time = req->request_time;
AP_DEBUG_ASSERT(req->authority); if (req->http_status != H2_HTTP_STATUS_UNSET) {
access_status = req->http_status; goto die;
} elseif (is_connect) { /* CONNECT MUST NOT have scheme or path */
r->the_request = apr_psprintf(r->pool, "%s %s HTTP/2.0",
req->method, req->authority); if (req->scheme) {
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(10458) "':scheme: %s' header present in CONNECT request",
req->scheme);
access_status = HTTP_BAD_REQUEST; goto die;
} elseif (req->path) {
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(10459) "':path: %s' header present in CONNECT request",
req->path);
access_status = HTTP_BAD_REQUEST; goto die;
}
} elseif (req->protocol) {
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(10470) "':protocol: %s' header present in %s request",
req->protocol, req->method);
access_status = HTTP_BAD_REQUEST; goto die;
} elseif (h2_config_cgeti(c, H2_CONF_PROXY_REQUESTS)) { if (!req->scheme) {
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(10468) "H2ProxyRequests on, but request misses :scheme");
access_status = HTTP_BAD_REQUEST; goto die;
} if (!req->authority) {
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(10469) "H2ProxyRequests on, but request misses :authority");
access_status = HTTP_BAD_REQUEST; goto die;
}
r->the_request = apr_psprintf(r->pool, "%s %s://%s%s HTTP/2.0",
req->method, req->scheme, req->authority,
req->path ? req->path : "");
} elseif (req->scheme && ap_cstr_casecmp(req->scheme, "http")
&& ap_cstr_casecmp(req->scheme, "https")) { /* Client sent a ':scheme' pseudo header for something else
* than what we have on this connection. Make an absolute URI. */
r->the_request = apr_psprintf(r->pool, "%s %s://%s%s HTTP/2.0",
req->method, req->scheme, req->authority,
req->path ? req->path : "");
} elseif (req->path) {
r->the_request = apr_psprintf(r->pool, "%s %s HTTP/2.0",
req->method, req->path);
} else { /* We should only come here on a request that is errored already. * create a request line that passes parsing, we'll die anyway.
*/
AP_DEBUG_ASSERT(req->http_status != H2_HTTP_STATUS_UNSET);
r->the_request = apr_psprintf(r->pool, "%s / HTTP/2.0", req->method);
}
/* Start with r->hostname = NULL, ap_check_request_header() will get it * form Host: header, otherwise we get complains about port numbers.
*/
r->hostname = NULL;
/* Validate HTTP/1 request and select vhost. */ if (!ap_parse_request_line(r) || !ap_check_request_header(r)) { /* we may have switched to another server still */
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;
}
r->status = HTTP_OK; goto die;
} #else
{ constchar *s;
/* Time to populate r with the data we have. */
r->request_time = req->request_time;
r->method = apr_pstrdup(r->pool, req->method); /* Provide quick information about the request method as soon as known */
r->method_number = ap_method_number_of(r->method); if (r->method_number == M_GET && r->method[0] == 'H') {
r->header_only = 1;
}
ap_parse_uri(r, req->path ? req->path : "");
r->protocol = (char*)"HTTP/2.0";
r->proto_num = HTTP_VERSION(2, 0);
r->the_request = apr_psprintf(r->pool, "%s %s HTTP/2.0",
r->method, req->path ? req->path : "");
/* Start with r->hostname = NULL, ap_check_request_header() will get it * form Host: header, otherwise we get complains about port numbers.
*/
r->hostname = NULL;
ap_update_vhost_from_headers(r);
/* we may have switched to another server */
r->per_dir_config = r->server->lookup_defaults;
s = apr_table_get(r->headers_in, "Expect"); if (s && s[0]) { if (ap_cstr_casecmp(s, "100-continue") == 0) {
r->expecting_100 = 1;
} else {
r->status = HTTP_EXPECTATION_FAILED;
access_status = r->status; goto die;
}
}
} #endif
/* we may have switched to another server */
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 * called by ap_die and by ap_send_error_response works correctly on * status codes that do not cause the connection to be dropped and * in situations where the connection should be kept alive.
*/
ap_add_input_filter_handle(ap_http_input_filter_handle,
NULL, r, r->connection);
if ((access_status = ap_post_read_request(r))) { /* Request check post hooks failed. An example of this would be a * request for a vhost where h2 is disabled --> 421.
*/
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(03367) "h2_request: access_status=%d, request_create failed",
access_status); goto die;
}
die: if (!r->method) { /* if we fail early, `r` is not properly initialized for error * processing which accesses fields in message generation.
* Make a best effort. */ if (!r->the_request) {
r->the_request = apr_psprintf(r->pool, "%s %s HTTP/2.0",
req->method, req->path);
}
ap_parse_request_line(r);
}
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, "ap_die(%d) for %s", access_status, r->the_request);
ap_die(access_status, r);
/* ap_die() sent the response through the output filters, we must now * end the request with an EOR bucket for stream/pipeline accounting.
*/
{
apr_bucket_brigade *eor_bb; #if AP_MODULE_MAGIC_AT_LEAST(20180905, 1)
eor_bb = ap_acquire_brigade(c);
APR_BRIGADE_INSERT_TAIL(eor_bb,
ap_bucket_eor_create(c->bucket_alloc, r));
ap_pass_brigade(c->output_filters, eor_bb);
ap_release_brigade(c, eor_bb); #else
eor_bb = apr_brigade_create(c->pool, c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(eor_bb,
ap_bucket_eor_create(c->bucket_alloc, r));
ap_pass_brigade(c->output_filters, eor_bb);
apr_brigade_destroy(eor_bb); #endif
}
r = NULL;
AP_READ_REQUEST_FAILURE((uintptr_t)r); return NULL;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.