Commit e32ce9a0 authored by Stefan Eissing's avatar Stefan Eissing
Browse files

*) mod_proxy_http2: adding support for handling trailers in both directions. PR 63502.



git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1861337 13f79535-47bb-0310-9956-ffa450edef68
parent 5f947f60
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
                                                         -*- coding: utf-8 -*-
                                                         -*- coding: utf-8 -*-
Changes with Apache 2.5.1
Changes with Apache 2.5.1


  *) mod_proxy_http2: adding support for handling trailers in both directions. PR 63502.
     [Stefan Eissing]

  *) mod_proxy/ssl: Proxy SSL client certificate configuration and other proxy
  *) mod_proxy/ssl: Proxy SSL client certificate configuration and other proxy
     SSL configurations broken inside <Proxy> context.  PR 63430.
     SSL configurations broken inside <Proxy> context.  PR 63430.
     [Ruediger Pluem, Yann Ylavic]
     [Ruediger Pluem, Yann Ylavic]
+34 −10
Original line number Original line Diff line number Diff line
@@ -45,6 +45,7 @@ typedef struct h2_proxy_stream {
    unsigned int suspended : 1;
    unsigned int suspended : 1;
    unsigned int waiting_on_100 : 1;
    unsigned int waiting_on_100 : 1;
    unsigned int waiting_on_ping : 1;
    unsigned int waiting_on_ping : 1;
    unsigned int headers_ended : 1;
    uint32_t error_code;
    uint32_t error_code;


    apr_bucket_brigade *input;
    apr_bucket_brigade *input;
@@ -61,6 +62,7 @@ static void dispatch_event(h2_proxy_session *session, h2_proxys_event_t ev,
static void ping_arrived(h2_proxy_session *session);
static void ping_arrived(h2_proxy_session *session);
static apr_status_t check_suspended(h2_proxy_session *session);
static apr_status_t check_suspended(h2_proxy_session *session);
static void stream_resume(h2_proxy_stream *stream);
static void stream_resume(h2_proxy_stream *stream);
static apr_status_t submit_trailers(h2_proxy_stream *stream);




static apr_status_t proxy_session_pre_close(void *theconn)
static apr_status_t proxy_session_pre_close(void *theconn)
@@ -241,7 +243,8 @@ static int add_header(void *table, const char *n, const char *v)
    return 1;
    return 1;
}
}


static void process_proxy_header(h2_proxy_stream *stream, const char *n, const char *v)
static void process_proxy_header(apr_table_t *headers, h2_proxy_stream *stream, 
                                 const char *n, const char *v)
{
{
    static const struct {
    static const struct {
        const char *name;
        const char *name;
@@ -262,20 +265,18 @@ static void process_proxy_header(h2_proxy_stream *stream, const char *n, const c
    if (!dconf->preserve_host) {
    if (!dconf->preserve_host) {
        for (i = 0; transform_hdrs[i].name; ++i) {
        for (i = 0; transform_hdrs[i].name; ++i) {
            if (!ap_cstr_casecmp(transform_hdrs[i].name, n)) {
            if (!ap_cstr_casecmp(transform_hdrs[i].name, n)) {
                apr_table_add(r->headers_out, n,
                apr_table_add(headers, n, (*transform_hdrs[i].func)(r, dconf, v));
                              (*transform_hdrs[i].func)(r, dconf, v));
                return;
                return;
            }
            }
        }
        }
        if (!ap_cstr_casecmp("Link", n)) {
        if (!ap_cstr_casecmp("Link", n)) {
            dconf = ap_get_module_config(r->per_dir_config, &proxy_module);
            dconf = ap_get_module_config(r->per_dir_config, &proxy_module);
            apr_table_add(r->headers_out, n,
            apr_table_add(headers, n, h2_proxy_link_reverse_map(r, dconf, 
                          h2_proxy_link_reverse_map(r, dconf, 
                            stream->real_server_uri, stream->p_server_uri, v));
                            stream->real_server_uri, stream->p_server_uri, v));
            return;
            return;
        }
        }
    }
    }
    apr_table_add(r->headers_out, n, v);
    apr_table_add(headers, n, v);
}
}


static apr_status_t h2_proxy_stream_add_header_out(h2_proxy_stream *stream,
static apr_status_t h2_proxy_stream_add_header_out(h2_proxy_stream *stream,
@@ -299,8 +300,13 @@ static apr_status_t h2_proxy_stream_add_header_out(h2_proxy_stream *stream,
        return APR_SUCCESS;
        return APR_SUCCESS;
    }
    }
    
    
    ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, stream->session->c, 
                  "h2_proxy_stream(%s-%d): on_header %s: %s", 
                  stream->session->id, stream->id, n, v);
    if (!h2_proxy_res_ignore_header(n, nlen)) {
    if (!h2_proxy_res_ignore_header(n, nlen)) {
        char *hname, *hvalue;
        char *hname, *hvalue;
        apr_table_t *headers = (stream->headers_ended? 
                               stream->r->trailers_out : stream->r->headers_out);
    
    
        hname = apr_pstrndup(stream->pool, n, nlen);
        hname = apr_pstrndup(stream->pool, n, nlen);
        h2_proxy_util_camel_case_header(hname, nlen);
        h2_proxy_util_camel_case_header(hname, nlen);
@@ -309,7 +315,7 @@ static apr_status_t h2_proxy_stream_add_header_out(h2_proxy_stream *stream,
        ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, stream->session->c, 
        ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, stream->session->c, 
                      "h2_proxy_stream(%s-%d): got header %s: %s", 
                      "h2_proxy_stream(%s-%d): got header %s: %s", 
                      stream->session->id, stream->id, hname, hvalue);
                      stream->session->id, stream->id, hname, hvalue);
        process_proxy_header(stream, hname, hvalue);
        process_proxy_header(headers, stream, hname, hvalue);
    }
    }
    return APR_SUCCESS;
    return APR_SUCCESS;
}
}
@@ -374,6 +380,7 @@ static void h2_proxy_stream_end_headers_out(h2_proxy_stream *stream)
                                      server_name, portstr)
                                      server_name, portstr)
                       );
                       );
    }
    }
    if (r->status >= 200) stream->headers_ended = 1;
    
    
    if (APLOGrtrace2(stream->r)) {
    if (APLOGrtrace2(stream->r)) {
        ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, stream->r, 
        ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, stream->r, 
@@ -547,9 +554,14 @@ static ssize_t stream_request_data(nghttp2_session *ngh2, int32_t stream_id,
        stream->data_sent += readlen;
        stream->data_sent += readlen;
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, status, stream->r, APLOGNO(03468) 
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, status, stream->r, APLOGNO(03468) 
                      "h2_proxy_stream(%d): request DATA %ld, %ld"
                      "h2_proxy_stream(%d): request DATA %ld, %ld"
                      " total, flags=%d", 
                      " total, flags=%d", stream->id, (long)readlen, (long)stream->data_sent,
                      stream->id, (long)readlen, (long)stream->data_sent,
                      (int)*data_flags);
                      (int)*data_flags);
        if ((*data_flags & NGHTTP2_DATA_FLAG_EOF) && !apr_is_empty_table(stream->r->trailers_in)) {
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, status, stream->r, APLOGNO(03468) 
                          "h2_proxy_stream(%d): submit trailers", stream->id);
            *data_flags |= NGHTTP2_DATA_FLAG_NO_END_STREAM;
            submit_trailers(stream);
        } 
        return readlen;
        return readlen;
    }
    }
    else if (APR_STATUS_IS_EAGAIN(status)) {
    else if (APR_STATUS_IS_EAGAIN(status)) {
@@ -736,6 +748,8 @@ static apr_status_t open_stream(h2_proxy_session *session, const char *url,
    stream->real_server_uri = apr_psprintf(stream->pool, "%s://%s", scheme, authority); 
    stream->real_server_uri = apr_psprintf(stream->pool, "%s://%s", scheme, authority); 
    stream->p_server_uri = apr_psprintf(stream->pool, "%s://%s", puri.scheme, authority); 
    stream->p_server_uri = apr_psprintf(stream->pool, "%s://%s", puri.scheme, authority); 
    path = apr_uri_unparse(stream->pool, &puri, APR_URI_UNP_OMITSITEPART);
    path = apr_uri_unparse(stream->pool, &puri, APR_URI_UNP_OMITSITEPART);


    h2_proxy_req_make(stream->req, stream->pool, r->method, scheme,
    h2_proxy_req_make(stream->req, stream->pool, r->method, scheme,
                authority, path, r->headers_in);
                authority, path, r->headers_in);


@@ -822,6 +836,16 @@ static apr_status_t submit_stream(h2_proxy_session *session, h2_proxy_stream *st
    return APR_EGENERAL;
    return APR_EGENERAL;
}
}


static apr_status_t submit_trailers(h2_proxy_stream *stream)
{
    h2_proxy_ngheader *hd;
    int rv;

    hd = h2_proxy_util_nghd_make(stream->pool, stream->r->trailers_in);
    rv = nghttp2_submit_trailer(stream->session->ngh2, stream->id, hd->nv, hd->nvlen);
    return rv == 0? APR_SUCCESS: APR_EGENERAL;
}

static apr_status_t feed_brigade(h2_proxy_session *session, apr_bucket_brigade *bb)
static apr_status_t feed_brigade(h2_proxy_session *session, apr_bucket_brigade *bb)
{
{
    apr_status_t status = APR_SUCCESS;
    apr_status_t status = APR_SUCCESS;
+22 −0
Original line number Original line Diff line number Diff line
@@ -452,6 +452,22 @@ h2_proxy_ngheader *h2_proxy_util_nghd_make_req(apr_pool_t *p,
    return ngh;
    return ngh;
}
}


h2_proxy_ngheader *h2_proxy_util_nghd_make(apr_pool_t *p, apr_table_t *headers)
{
    
    h2_proxy_ngheader *ngh;
    size_t n;
    
    n = 0;
    apr_table_do(count_header, &n, headers, NULL);
    
    ngh = apr_pcalloc(p, sizeof(h2_proxy_ngheader));
    ngh->nv =  apr_pcalloc(p, n * sizeof(nghttp2_nv));
    apr_table_do(add_table_header, ngh, headers, NULL);

    return ngh;
}

/*******************************************************************************
/*******************************************************************************
 * header HTTP/1 <-> HTTP/2 conversions
 * header HTTP/1 <-> HTTP/2 conversions
 ******************************************************************************/
 ******************************************************************************/
@@ -609,6 +625,7 @@ apr_status_t h2_proxy_req_make(h2_proxy_request *req, apr_pool_t *pool,
                         apr_table_t *headers)
                         apr_table_t *headers)
{
{
    h1_ctx x;
    h1_ctx x;
    const char *val;


    req->method    = method;
    req->method    = method;
    req->scheme    = scheme;
    req->scheme    = scheme;
@@ -623,6 +640,11 @@ apr_status_t h2_proxy_req_make(h2_proxy_request *req, apr_pool_t *pool,
    x.pool = pool;
    x.pool = pool;
    x.headers = req->headers;
    x.headers = req->headers;
    apr_table_do(set_h1_header, &x, headers, NULL);
    apr_table_do(set_h1_header, &x, headers, NULL);
    if ((val = apr_table_get(headers, "TE")) && ap_find_token(pool, val, "trailers")) {
        /* client accepts trailers, forward this information */
        apr_table_addn(req->headers, "TE", "trailers");
    }
    apr_table_setn(req->headers, "te", "trailers");
    return APR_SUCCESS;
    return APR_SUCCESS;
}
}


+2 −0
Original line number Original line Diff line number Diff line
@@ -168,6 +168,8 @@ typedef struct h2_proxy_ngheader {
h2_proxy_ngheader *h2_proxy_util_nghd_make_req(apr_pool_t *p, 
h2_proxy_ngheader *h2_proxy_util_nghd_make_req(apr_pool_t *p, 
                                               const struct h2_proxy_request *req);
                                               const struct h2_proxy_request *req);


h2_proxy_ngheader *h2_proxy_util_nghd_make(apr_pool_t *p, apr_table_t *headers);

/*******************************************************************************
/*******************************************************************************
 * h2_proxy_request helpers
 * h2_proxy_request helpers
 ******************************************************************************/
 ******************************************************************************/