summaryrefslogtreecommitdiffstats
path: root/modules/http2/h2_headers.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/http2/h2_headers.c')
-rw-r--r--modules/http2/h2_headers.c99
1 files changed, 70 insertions, 29 deletions
diff --git a/modules/http2/h2_headers.c b/modules/http2/h2_headers.c
index 8b7add6..d9b3fd0 100644
--- a/modules/http2/h2_headers.c
+++ b/modules/http2/h2_headers.c
@@ -27,11 +27,13 @@
#include <nghttp2/nghttp2.h>
#include "h2_private.h"
-#include "h2_h2.h"
+#include "h2_protocol.h"
+#include "h2_config.h"
#include "h2_util.h"
#include "h2_request.h"
#include "h2_headers.h"
+#if !AP_HAS_RESPONSE_BUCKETS
static int is_unsafe(server_rec *s)
{
@@ -63,6 +65,7 @@ apr_bucket * h2_bucket_headers_make(apr_bucket *b, h2_headers *r)
b = apr_bucket_shared_make(b, br, 0, 0);
b->type = &h2_bucket_type_headers;
+ b->length = 0;
return b;
}
@@ -87,32 +90,35 @@ h2_headers *h2_bucket_headers_get(apr_bucket *b)
return NULL;
}
+static void bucket_destroy(void *data)
+{
+ h2_bucket_headers *h = data;
+
+ if (apr_bucket_shared_destroy(h)) {
+ apr_bucket_free(h);
+ }
+}
+
const apr_bucket_type_t h2_bucket_type_headers = {
"H2HEADERS", 5, APR_BUCKET_METADATA,
- apr_bucket_destroy_noop,
+ bucket_destroy,
bucket_read,
apr_bucket_setaside_noop,
apr_bucket_split_notimpl,
apr_bucket_shared_copy
};
-apr_bucket *h2_bucket_headers_beam(struct h2_bucket_beam *beam,
- apr_bucket_brigade *dest,
- const apr_bucket *src)
+apr_bucket *h2_bucket_headers_clone(apr_bucket *b, apr_pool_t *pool,
+ apr_bucket_alloc_t *list)
{
- if (H2_BUCKET_IS_HEADERS(src)) {
- h2_headers *r = ((h2_bucket_headers *)src->data)->headers;
- apr_bucket *b = h2_bucket_headers_create(dest->bucket_alloc, r);
- APR_BRIGADE_INSERT_TAIL(dest, b);
- return b;
- }
- return NULL;
+ h2_headers *hdrs = ((h2_bucket_headers *)b->data)->headers;
+ return h2_bucket_headers_create(list, h2_headers_clone(pool, hdrs));
}
-h2_headers *h2_headers_create(int status, apr_table_t *headers_in,
- apr_table_t *notes, apr_off_t raw_bytes,
- apr_pool_t *pool)
+h2_headers *h2_headers_create(int status, const apr_table_t *headers_in,
+ const apr_table_t *notes, apr_off_t raw_bytes,
+ apr_pool_t *pool)
{
h2_headers *headers = apr_pcalloc(pool, sizeof(h2_headers));
headers->status = status;
@@ -123,26 +129,55 @@ h2_headers *h2_headers_create(int status, apr_table_t *headers_in,
return headers;
}
+static int add_header_lengths(void *ctx, const char *name, const char *value)
+{
+ apr_size_t *plen = ctx;
+ *plen += strlen(name) + strlen(value);
+ return 1;
+}
+
+apr_size_t h2_headers_length(h2_headers *headers)
+{
+ apr_size_t len = 0;
+ apr_table_do(add_header_lengths, &len, headers->headers, NULL);
+ return len;
+}
+
+apr_size_t h2_bucket_headers_headers_length(apr_bucket *b)
+{
+ h2_headers *h = h2_bucket_headers_get(b);
+ return h? h2_headers_length(h) : 0;
+}
+
h2_headers *h2_headers_rcreate(request_rec *r, int status,
- apr_table_t *header, apr_pool_t *pool)
+ const apr_table_t *header, apr_pool_t *pool)
{
h2_headers *headers = h2_headers_create(status, header, r->notes, 0, pool);
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, headers->status, r,
+ "h2_headers_rcreate(%ld): status=%d",
+ (long)r->connection->id, status);
if (headers->status == HTTP_FORBIDDEN) {
- const char *cause = apr_table_get(r->notes, "ssl-renegotiate-forbidden");
- if (cause) {
- /* This request triggered a TLS renegotiation that is now allowed
- * in HTTP/2. Tell the client that it should use HTTP/1.1 for this.
- */
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, headers->status, r,
- APLOGNO(03061)
- "h2_headers(%ld): renegotiate forbidden, cause: %s",
- (long)r->connection->id, cause);
- headers->status = H2_ERR_HTTP_1_1_REQUIRED;
+ request_rec *r_prev;
+ for (r_prev = r; r_prev != NULL; r_prev = r_prev->prev) {
+ const char *cause = apr_table_get(r_prev->notes, "ssl-renegotiate-forbidden");
+ if (cause) {
+ /* This request triggered a TLS renegotiation that is not allowed
+ * in HTTP/2. Tell the client that it should use HTTP/1.1 for this.
+ */
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, headers->status, r,
+ APLOGNO(10399)
+ "h2_headers(%ld): renegotiate forbidden, cause: %s",
+ (long)r->connection->id, cause);
+ headers->status = H2_ERR_HTTP_1_1_REQUIRED;
+ break;
+ }
}
}
if (is_unsafe(r->server)) {
- apr_table_setn(headers->notes, H2_HDR_CONFORMANCE,
- H2_HDR_CONFORMANCE_UNSAFE);
+ apr_table_setn(headers->notes, H2_HDR_CONFORMANCE, H2_HDR_CONFORMANCE_UNSAFE);
+ }
+ if (h2_config_rgeti(r, H2_CONF_PUSH) == 0 && h2_config_sgeti(r->server, H2_CONF_PUSH) != 0) {
+ apr_table_setn(headers->notes, H2_PUSH_MODE_NOTE, "0");
}
return headers;
}
@@ -152,6 +187,11 @@ h2_headers *h2_headers_copy(apr_pool_t *pool, h2_headers *h)
return h2_headers_create(h->status, h->headers, h->notes, h->raw_bytes, pool);
}
+h2_headers *h2_headers_clone(apr_pool_t *pool, h2_headers *h)
+{
+ return h2_headers_create(h->status, h->headers, h->notes, h->raw_bytes, pool);
+}
+
h2_headers *h2_headers_die(apr_status_t type,
const h2_request *req, apr_pool_t *pool)
{
@@ -171,8 +211,9 @@ h2_headers *h2_headers_die(apr_status_t type,
return headers;
}
-int h2_headers_are_response(h2_headers *headers)
+int h2_headers_are_final_response(h2_headers *headers)
{
return headers->status >= 200;
}
+#endif /* !AP_HAS_RESPONSE_BUCKETS */