summaryrefslogtreecommitdiff
path: root/modules/http2/h2_c2.c
diff options
context:
space:
mode:
authorStefan Eissing <icing@apache.org>2023-05-12 11:28:59 +0000
committerStefan Eissing <icing@apache.org>2023-05-12 11:28:59 +0000
commitbdd49d384558257ee89384b5a380f0f042f6d604 (patch)
tree9637b457f058c49f3da8c0a4ee26bceaaecae7d7 /modules/http2/h2_c2.c
parentfca209be5638c1f35e9dd16b1816091b5db38d74 (diff)
downloadhttpd-bdd49d384558257ee89384b5a380f0f042f6d604.tar.gz
*) mod_http2: v2.0.15 with the following fixes and improvements
- New directive 'H2EarlyHint name value' to add headers to a response, picked up already when a "103 Early Hints" response is sent. 'name' and 'value' must comply to the HTTP field restrictions. This directive can be repeated several times and header fields of the same names add. Sending a 'Link' header with 'preload' relation will also cause a HTTP/2 PUSH if enabled and supported by the client. - Fixed an issue where requests were not logged and accounted in a timely fashion when the connection returns to "keepalive" handling, e.g. when the request served was the last outstanding one. This led to late appearance in access logs with wrong duration times reported. - Accurately report the bytes sent for a request in the '%O' Log format. This addresses #203, a long outstanding issue where mod_h2 has reported numbers over-eagerly from internal buffering and not what has actually been placed on the connection. The numbers are now the same with and without H2CopyFiles enabled. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1909769 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'modules/http2/h2_c2.c')
-rw-r--r--modules/http2/h2_c2.c115
1 files changed, 64 insertions, 51 deletions
diff --git a/modules/http2/h2_c2.c b/modules/http2/h2_c2.c
index 44a08d075e..c06438ecff 100644
--- a/modules/http2/h2_c2.c
+++ b/modules/http2/h2_c2.c
@@ -133,10 +133,22 @@ apr_status_t h2_c2_child_init(apr_pool_t *pool, server_rec *s)
APR_PROTO_TCP, pool);
}
+static void h2_c2_log_io(conn_rec *c2, apr_off_t bytes_sent)
+{
+ if (bytes_sent && h2_c_logio_add_bytes_out) {
+ h2_c_logio_add_bytes_out(c2, bytes_sent);
+ }
+}
+
void h2_c2_destroy(conn_rec *c2)
{
+ h2_conn_ctx_t *conn_ctx = h2_conn_ctx_get(c2);
+
ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c2,
"h2_c2(%s): destroy", c2->log_id);
+ if(!c2->aborted && conn_ctx && conn_ctx->bytes_sent) {
+ h2_c2_log_io(c2, conn_ctx->bytes_sent);
+ }
apr_pool_destroy(c2->pool);
}
@@ -146,6 +158,10 @@ void h2_c2_abort(conn_rec *c2, conn_rec *from)
AP_DEBUG_ASSERT(conn_ctx);
AP_DEBUG_ASSERT(conn_ctx->stream_id);
+ if(!c2->aborted && conn_ctx->bytes_sent) {
+ h2_c2_log_io(c2, conn_ctx->bytes_sent);
+ }
+
if (conn_ctx->beam_in) {
h2_beam_abort(conn_ctx->beam_in, from);
}
@@ -326,42 +342,13 @@ receive:
static apr_status_t beam_out(conn_rec *c2, h2_conn_ctx_t *conn_ctx, apr_bucket_brigade* bb)
{
- apr_off_t written, header_len = 0;
+ apr_off_t written = 0;
apr_status_t rv;
- if (h2_c_logio_add_bytes_out) {
- /* mod_logio wants to report the number of bytes written in a
- * response, including header and footer fields. Since h2 converts
- * those during c1 processing into the HPACKed h2 HEADER frames,
- * we need to give mod_logio something here and count just the
- * raw lengths of all headers in the buckets. */
- apr_bucket *b;
- for (b = APR_BRIGADE_FIRST(bb);
- b != APR_BRIGADE_SENTINEL(bb);
- b = APR_BUCKET_NEXT(b)) {
-#if AP_HAS_RESPONSE_BUCKETS
- if (AP_BUCKET_IS_RESPONSE(b)) {
- header_len += (apr_off_t)response_length_estimate(b->data);
- }
- if (AP_BUCKET_IS_HEADERS(b)) {
- header_len += (apr_off_t)headers_length_estimate(b->data);
- }
-#else
- if (H2_BUCKET_IS_HEADERS(b)) {
- header_len += (apr_off_t)h2_bucket_headers_headers_length(b);
- }
-#endif /* AP_HAS_RESPONSE_BUCKETS */
- }
- }
-
rv = h2_beam_send(conn_ctx->beam_out, c2, bb, APR_BLOCK_READ, &written);
-
if (APR_STATUS_IS_EAGAIN(rv)) {
rv = APR_SUCCESS;
}
- if (written && h2_c_logio_add_bytes_out) {
- h2_c_logio_add_bytes_out(c2, written + header_len);
- }
return rv;
}
@@ -403,30 +390,56 @@ static apr_status_t h2_c2_filter_out(ap_filter_t* f, apr_bucket_brigade* bb)
return rv;
}
-static void check_push(request_rec *r, const char *tag)
+static int addn_headers(void *udata, const char *name, const char *value)
{
- apr_array_header_t *push_list = h2_config_push_list(r);
+ apr_table_t *dest = udata;
+ apr_table_addn(dest, name, value);
+ return 1;
+}
- if (!r->expecting_100 && push_list && push_list->nelts > 0) {
- int i, old_status;
- const char *old_line;
+static void check_early_hints(request_rec *r, const char *tag)
+{
+ apr_array_header_t *push_list = h2_config_push_list(r);
+ apr_table_t *early_headers = h2_config_early_headers(r);
+
+ if (!r->expecting_100 &&
+ ((push_list && push_list->nelts > 0) ||
+ (early_headers && !apr_is_empty_table(early_headers)))) {
+ int have_hints = 0, i;
+
+ if (push_list && push_list->nelts > 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
+ "%s, early announcing %d resources for push",
+ tag, push_list->nelts);
+ for (i = 0; i < push_list->nelts; ++i) {
+ h2_push_res *push = &APR_ARRAY_IDX(push_list, i, h2_push_res);
+ apr_table_add(r->headers_out, "Link",
+ apr_psprintf(r->pool, "<%s>; rel=preload%s",
+ push->uri_ref, push->critical? "; critical" : ""));
+ }
+ have_hints = 1;
+ }
+ if (early_headers && !apr_is_empty_table(early_headers)) {
+ apr_table_do(addn_headers, r->headers_out, early_headers, NULL);
+ have_hints = 1;
+ }
- ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
- "%s, early announcing %d resources for push",
- tag, push_list->nelts);
- for (i = 0; i < push_list->nelts; ++i) {
- h2_push_res *push = &APR_ARRAY_IDX(push_list, i, h2_push_res);
- apr_table_add(r->headers_out, "Link",
- apr_psprintf(r->pool, "<%s>; rel=preload%s",
- push->uri_ref, push->critical? "; critical" : ""));
+ if (have_hints) {
+ int old_status;
+ const char *old_line;
+
+ if (h2_config_rgeti(r, H2_CONF_PUSH) == 0 &&
+ h2_config_sgeti(r->server, H2_CONF_PUSH) != 0) {
+ apr_table_setn(r->connection->notes, H2_PUSH_MODE_NOTE, "0");
+ }
+ old_status = r->status;
+ old_line = r->status_line;
+ r->status = 103;
+ r->status_line = "103 Early Hints";
+ ap_send_interim_response(r, 1);
+ r->status = old_status;
+ r->status_line = old_line;
}
- old_status = r->status;
- old_line = r->status_line;
- r->status = 103;
- r->status_line = "103 Early Hints";
- ap_send_interim_response(r, 1);
- r->status = old_status;
- r->status_line = old_line;
}
}
@@ -439,7 +452,7 @@ static int c2_hook_fixups(request_rec *r)
return DECLINED;
}
- check_push(r, "late_fixup");
+ check_early_hints(r, "late_fixup");
return DECLINED;
}