static apr_status_t add_h1_header(h2_request *req, apr_pool_t *pool, const char *name, size_t nlen, const char *value, size_t vlen) { char *hname, *hvalue; if (h2_req_ignore_header(name, nlen)) { return APR_SUCCESS; } else if (H2_HD_MATCH_LIT("cookie", name, nlen)) { const char *existing = apr_table_get(req->headers, "cookie"); if (existing) { char *nval; /* Cookie header come separately in HTTP/2, but need * to be merged by "; " (instead of default ", ") */ hvalue = apr_pstrndup(pool, value, vlen); nval = apr_psprintf(pool, "%s; %s", existing, hvalue); apr_table_setn(req->headers, "Cookie", nval); return APR_SUCCESS; } } else if (H2_HD_MATCH_LIT("host", name, nlen)) { if (apr_table_get(req->headers, "Host")) { return APR_SUCCESS; /* ignore duplicate */ } } hname = apr_pstrndup(pool, name, nlen); hvalue = apr_pstrndup(pool, value, vlen); h2_util_camel_case_header(hname, nlen); apr_table_mergen(req->headers, hname, hvalue); return APR_SUCCESS; }
apr_status_t h2_to_h1_add_header(h2_to_h1 *to_h1, const char *name, size_t nlen, const char *value, size_t vlen) { if (H2_HD_MATCH_LIT("transfer-encoding", name, nlen)) { if (!apr_strnatcasecmp("chunked", value)) { /* This should never arrive here in a HTTP/2 request */ ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_BADARG, h2_mplx_get_conn(to_h1->m), "h2_to_h1: 'transfer-encoding: chunked' received"); return APR_BADARG; } } else if (H2_HD_MATCH_LIT("content-length", name, nlen)) { char *end; to_h1->content_len = apr_strtoi64(value, &end, 10); if (value == end) { ap_log_cerror(APLOG_MARK, APLOG_WARNING, APR_EINVAL, h2_mplx_get_conn(to_h1->m), "h2_request(%d): content-length value not parsed: %s", to_h1->stream_id, value); return APR_EINVAL; } to_h1->remain_len = to_h1->content_len; to_h1->chunked = 0; } else if (H2_HD_MATCH_LIT("content-type", name, nlen)) { /* If we see a content-type and have no length (yet), * we need to chunk. */ to_h1->chunked = (to_h1->content_len == -1); } else if ((to_h1->seen_host && H2_HD_MATCH_LIT("host", name, nlen)) || H2_HD_MATCH_LIT("expect", name, nlen) || H2_HD_MATCH_LIT("upgrade", name, nlen) || H2_HD_MATCH_LIT("connection", name, nlen) || H2_HD_MATCH_LIT("proxy-connection", name, nlen) || H2_HD_MATCH_LIT("keep-alive", name, nlen) || H2_HD_MATCH_LIT("http2-settings", name, nlen)) { // ignore these. return APR_SUCCESS; } else if (H2_HD_MATCH_LIT("cookie", name, nlen)) { const char *existing = apr_table_get(to_h1->headers, "cookie"); if (existing) { /* Cookie headers come separately in HTTP/2, but need * to be merged by "; " (instead of default ", ") */ char *hvalue = apr_pstrndup(to_h1->pool, value, vlen); char *nval = apr_psprintf(to_h1->pool, "%s; %s", existing, hvalue); apr_table_setn(to_h1->headers, "Cookie", nval); return APR_SUCCESS; } } else if (H2_HD_MATCH_LIT("host", name, nlen)) { to_h1->seen_host = 1; } char *hname = apr_pstrndup(to_h1->pool, name, nlen); char *hvalue = apr_pstrndup(to_h1->pool, value, vlen); h2_util_camel_case_header(hname, nlen); apr_table_mergen(to_h1->headers, hname, hvalue); return APR_SUCCESS; }