diff options
Diffstat (limited to 'modules/http2/h2_headers.c')
-rw-r--r-- | modules/http2/h2_headers.c | 99 |
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 */ |