request_rec *h2_request_create_rec(const h2_request *req, conn_rec *c)
{
int access_status = HTTP_OK;
- const char *rpath;
+ const char *rpath = req->path ? req->path : "";
const char *s;
#if AP_MODULE_MAGIC_AT_LEAST(20150222, 13)
request_rec *r = my_ap_create_request(c);
#endif
- r->headers_in = apr_table_clone(r->pool, req->headers);
-
ap_run_pre_read_request(r, c);
/* Time to populate r with the data we have. */
if (r->method_number == M_GET && r->method[0] == 'H') {
r->header_only = 1;
}
-
- rpath = (req->path ? req->path : "");
- ap_parse_uri(r, rpath);
- r->protocol = (char*)"HTTP/2.0";
r->proto_num = HTTP_VERSION(2, 0);
-
+ r->protocol = apr_pstrdup(r->pool, "HTTP/2.0");
r->the_request = apr_psprintf(r->pool, "%s %s %s",
r->method, rpath, r->protocol);
-
+ r->headers_in = apr_table_clone(r->pool, req->headers);
+
+ ap_parse_uri(r, rpath);
+ if (r->status != HTTP_OK) {
+ access_status = r->status;
+ r->status = HTTP_OK;
+ goto die;
+ }
+
/* update what we think the virtual host is based on the headers we've
* now read. may update status.
* Leave r->hostname empty, vhost will parse if form our Host: header,
*/
r->hostname = NULL;
ap_update_vhost_from_headers(r);
+ if (r->status != HTTP_OK) {
+ access_status = r->status;
+ r->status = HTTP_OK;
+ goto die;
+ }
/* we may have switched to another server */
r->per_dir_config = r->server->lookup_defaults;
r->expecting_100 = 1;
}
else {
- r->status = HTTP_EXPECTATION_FAILED;
- ap_send_error_response(r, 0);
+ access_status = HTTP_EXPECTATION_FAILED;
+ goto die;
}
}
ap_add_input_filter_handle(ap_http_input_filter_handle,
NULL, r, r->connection);
- if (access_status != HTTP_OK
- || (access_status = ap_run_post_read_request(r))) {
+ if ((access_status = ap_run_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);
- ap_die(access_status, r);
- ap_update_child_status(c->sbh, SERVER_BUSY_LOG, r);
- ap_run_log_transaction(r);
- r = NULL;
- goto traceout;
+ goto die;
}
AP_READ_REQUEST_SUCCESS((uintptr_t)r, (char *)r->method,
(char *)r->uri, (char *)r->server->defn_name,
r->status);
return r;
-traceout:
+
+die:
+ 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 *tmp_bb;
+ tmp_bb = ap_acquire_brigade(c);
+ APR_BRIGADE_INSERT_TAIL(tmp_bb,
+ ap_bucket_eor_create(c->bucket_alloc, r));
+ ap_pass_brigade(c->output_filters, tmp_bb);
+ ap_release_brigade(c, tmp_bb);
+ }
+
+ r = NULL;
AP_READ_REQUEST_FAILURE((uintptr_t)r);
- return r;
+ return NULL;
}
apr_socket_t *csd;
apr_interval_time_t cur_timeout;
core_server_config *conf;
+ int strict_host_check;
request_rec *r = ap_create_request(conn);
/* Get the request... */
if (!read_request_line(r, tmp_bb)) {
+ apr_brigade_cleanup(tmp_bb);
switch (r->status) {
case HTTP_REQUEST_URI_TOO_LARGE:
case HTTP_BAD_REQUEST:
"request failed: malformed request line");
}
access_status = r->status;
- r->status = HTTP_OK;
- ap_die(access_status, r);
- ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
- ap_run_log_transaction(r);
- r = NULL;
- apr_brigade_destroy(tmp_bb);
- goto traceout;
+ goto die_early;
+
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);
- apr_brigade_destroy(tmp_bb);
- goto traceout;
- default:
- apr_brigade_destroy(tmp_bb);
- r = NULL;
- goto traceout;
+ 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
* to the normal timeout mode as we fetch the header lines,
const char *tenc;
ap_get_mime_headers_core(r, tmp_bb);
+ apr_brigade_cleanup(tmp_bb);
if (r->status != HTTP_OK) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00567)
"request failed: error reading the headers");
- ap_send_error_response(r, 0);
- ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
- ap_run_log_transaction(r);
- apr_brigade_destroy(tmp_bb);
- goto traceout;
+ access_status = r->status;
+ goto die_early;
}
tenc = apr_table_get(r->headers_in, "Transfer-Encoding");
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02539)
"client sent unknown Transfer-Encoding "
"(%s): %s", tenc, r->uri);
- r->status = HTTP_BAD_REQUEST;
- conn->keepalive = AP_CONN_CLOSE;
- ap_send_error_response(r, 0);
- ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
- ap_run_log_transaction(r);
- apr_brigade_destroy(tmp_bb);
- goto traceout;
+ access_status = HTTP_BAD_REQUEST;
+ goto die_early;
}
/* http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-23
}
}
- apr_brigade_destroy(tmp_bb);
-
/* update what we think the virtual host is based on the headers we've
* now read. may update status.
*/
-
- access_status = ap_update_vhost_from_headers_ex(r, conf->strict_host_check == AP_CORE_CONFIG_ON);
- if (conf->strict_host_check == AP_CORE_CONFIG_ON && access_status != HTTP_OK) {
+ strict_host_check = (conf->strict_host_check == AP_CORE_CONFIG_ON);
+ access_status = ap_update_vhost_from_headers_ex(r, strict_host_check);
+ if (strict_host_check && access_status != HTTP_OK) {
if (r->server == ap_server_conf) {
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10156)
"Requested hostname '%s' did not match any ServerName/ServerAlias "
"current connection is %s:%u)",
r->hostname, r->server->defn_name, r->server->defn_line_number);
}
- r->status = access_status;
+ goto die_early;
}
-
- access_status = r->status;
-
- /* Toggle to the Host:-based vhost's timeout mode to fetch the
- * request body and send the response body, if needed.
- */
- if (cur_timeout != r->server->timeout) {
- apr_socket_timeout_set(csd, r->server->timeout);
- cur_timeout = r->server->timeout;
+ if (r->status != HTTP_OK) {
+ access_status = r->status;
+ goto die_early;
}
- /* we may have switched to another server */
- r->per_dir_config = r->server->lookup_defaults;
-
if ((!r->hostname && (r->proto_num >= HTTP_VERSION(1, 1)))
|| ((r->proto_num == HTTP_VERSION(1, 1))
&& !apr_table_get(r->headers_in, "Host"))) {
* HTTP/1.1 mentions twice (S9, S14.23) that a request MUST contain
* a Host: header, and the server MUST respond with 400 if it doesn't.
*/
- access_status = HTTP_BAD_REQUEST;
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00569)
"client sent HTTP/1.1 request without hostname "
"(see RFC2616 section 14.23): %s", r->uri);
+ access_status = HTTP_BAD_REQUEST;
+ goto die_early;
+ }
+
+ /* we may have switched to another server */
+ r->per_dir_config = r->server->lookup_defaults;
+ conf = ap_get_core_module_config(r->server->module_config);
+
+ /* Toggle to the Host:-based vhost's timeout mode to fetch the
+ * request body and send the response body, if needed.
+ */
+ if (cur_timeout != r->server->timeout) {
+ apr_socket_timeout_set(csd, r->server->timeout);
+ cur_timeout = r->server->timeout;
}
/*
* 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 != HTTP_OK
- || (access_status = ap_run_post_read_request(r))) {
- ap_die(access_status, r);
- ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
- ap_run_log_transaction(r);
- r = NULL;
- goto traceout;
+ if ((access_status = ap_run_post_read_request(r))) {
+ goto die;
}
if (((expect = apr_table_get(r->headers_in, "Expect")) != NULL)
}
else {
if (conf->http_expect_strict != AP_HTTP_EXPECT_STRICT_DISABLE) {
- r->status = HTTP_EXPECTATION_FAILED;
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00570)
"client sent an unrecognized expectation value "
"of Expect: %s", expect);
- ap_send_error_response(r, 0);
- ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
- ap_run_log_transaction(r);
- goto traceout;
+ access_status = HTTP_EXPECTATION_FAILED;
+ goto die;
}
else {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02595)
}
}
- AP_READ_REQUEST_SUCCESS((uintptr_t)r, (char *)r->method, (char *)r->uri, (char *)r->server->defn_name, r->status);
+ AP_READ_REQUEST_SUCCESS((uintptr_t)r, (char *)r->method,
+ (char *)r->uri, (char *)r->server->defn_name,
+ r->status);
return r;
- traceout:
+
+die_early:
+ /* Input filters are in an undeterminate state, cleanup (including
+ * CORE_IN's socket) such that any further attempt to read is EOF.
+ */
+ {
+ ap_filter_t *f = conn->input_filters;
+ while (f) {
+ ap_filter_reinstate_brigade(f, tmp_bb, NULL);
+ apr_brigade_cleanup(tmp_bb);
+ if (f->frec == ap_core_input_filter_handle) {
+ break;
+ }
+ ap_remove_input_filter(f);
+ f = f->next;
+ }
+ conn->input_filters = r->input_filters = f;
+ conn->keepalive = AP_CONN_CLOSE;
+ }
+
+ /* fallthru ap_die() (non recursive) */
+ r->status = HTTP_OK;
+die:
+ 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.
+ */
+ tmp_bb = ap_acquire_brigade(conn);
+ APR_BRIGADE_INSERT_TAIL(tmp_bb,
+ ap_bucket_eor_create(conn->bucket_alloc, r));
+ ap_pass_brigade(conn->output_filters, tmp_bb);
+ ap_release_brigade(conn, tmp_bb);
+
+ /* fallthru */
+ignore:
+ r = NULL;
AP_READ_REQUEST_FAILURE((uintptr_t)r);
- return r;
+ return NULL;
}
/* if a request with a body creates a subrequest, remove original request's