Merge pull request #903 from nghttp2/nghttpx-forward-multiple-header-fields
nghttpx: Forward multiple via, xff, and xfp header fields
This commit is contained in:
commit
bf16fee6e9
158
src/http2.cc
158
src/http2.cc
|
@ -358,15 +358,21 @@ nghttp2_nv make_nv_nocopy(const StringRef &name, const StringRef &value,
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void copy_headers_to_nva_internal(std::vector<nghttp2_nv> &nva,
|
void copy_headers_to_nva_internal(std::vector<nghttp2_nv> &nva,
|
||||||
const HeaderRefs &headers, uint8_t nv_flags) {
|
const HeaderRefs &headers, uint8_t nv_flags,
|
||||||
for (auto &kv : headers) {
|
uint32_t flags) {
|
||||||
if (kv.name.empty() || kv.name[0] == ':') {
|
auto it_forwarded = std::end(headers);
|
||||||
|
auto it_xff = std::end(headers);
|
||||||
|
auto it_xfp = std::end(headers);
|
||||||
|
auto it_via = std::end(headers);
|
||||||
|
|
||||||
|
for (auto it = std::begin(headers); it != std::end(headers); ++it) {
|
||||||
|
auto kv = &(*it);
|
||||||
|
if (kv->name.empty() || kv->name[0] == ':') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switch (kv.token) {
|
switch (kv->token) {
|
||||||
case HD_COOKIE:
|
case HD_COOKIE:
|
||||||
case HD_CONNECTION:
|
case HD_CONNECTION:
|
||||||
case HD_FORWARDED:
|
|
||||||
case HD_HOST:
|
case HD_HOST:
|
||||||
case HD_HTTP2_SETTINGS:
|
case HD_HTTP2_SETTINGS:
|
||||||
case HD_KEEP_ALIVE:
|
case HD_KEEP_ALIVE:
|
||||||
|
@ -375,51 +381,157 @@ void copy_headers_to_nva_internal(std::vector<nghttp2_nv> &nva,
|
||||||
case HD_TE:
|
case HD_TE:
|
||||||
case HD_TRANSFER_ENCODING:
|
case HD_TRANSFER_ENCODING:
|
||||||
case HD_UPGRADE:
|
case HD_UPGRADE:
|
||||||
case HD_VIA:
|
continue;
|
||||||
case HD_X_FORWARDED_FOR:
|
case HD_FORWARDED:
|
||||||
case HD_X_FORWARDED_PROTO:
|
if (flags & HDOP_STRIP_FORWARDED) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
nva.push_back(make_nv_internal(kv.name, kv.value, kv.no_index, nv_flags));
|
|
||||||
|
if (it_forwarded == std::end(headers)) {
|
||||||
|
it_forwarded = it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
kv = &(*it_forwarded);
|
||||||
|
it_forwarded = it;
|
||||||
|
break;
|
||||||
|
case HD_X_FORWARDED_FOR:
|
||||||
|
if (flags & HDOP_STRIP_X_FORWARDED_FOR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it_xff == std::end(headers)) {
|
||||||
|
it_xff = it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
kv = &(*it_xff);
|
||||||
|
it_xff = it;
|
||||||
|
break;
|
||||||
|
case HD_X_FORWARDED_PROTO:
|
||||||
|
if (flags & HDOP_STRIP_X_FORWARDED_PROTO) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it_xfp == std::end(headers)) {
|
||||||
|
it_xfp = it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
kv = &(*it_xfp);
|
||||||
|
it_xfp = it;
|
||||||
|
break;
|
||||||
|
case HD_VIA:
|
||||||
|
if (flags & HDOP_STRIP_VIA) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it_via == std::end(headers)) {
|
||||||
|
it_via = it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
kv = &(*it_via);
|
||||||
|
it_via = it;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
nva.push_back(
|
||||||
|
make_nv_internal(kv->name, kv->value, kv->no_index, nv_flags));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void copy_headers_to_nva(std::vector<nghttp2_nv> &nva,
|
void copy_headers_to_nva(std::vector<nghttp2_nv> &nva,
|
||||||
const HeaderRefs &headers) {
|
const HeaderRefs &headers, uint32_t flags) {
|
||||||
copy_headers_to_nva_internal(nva, headers, NGHTTP2_NV_FLAG_NONE);
|
copy_headers_to_nva_internal(nva, headers, NGHTTP2_NV_FLAG_NONE, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void copy_headers_to_nva_nocopy(std::vector<nghttp2_nv> &nva,
|
void copy_headers_to_nva_nocopy(std::vector<nghttp2_nv> &nva,
|
||||||
const HeaderRefs &headers) {
|
const HeaderRefs &headers, uint32_t flags) {
|
||||||
copy_headers_to_nva_internal(nva, headers, NGHTTP2_NV_FLAG_NO_COPY_NAME |
|
copy_headers_to_nva_internal(nva, headers, NGHTTP2_NV_FLAG_NO_COPY_NAME |
|
||||||
NGHTTP2_NV_FLAG_NO_COPY_VALUE);
|
NGHTTP2_NV_FLAG_NO_COPY_VALUE,
|
||||||
|
flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void build_http1_headers_from_headers(DefaultMemchunks *buf,
|
void build_http1_headers_from_headers(DefaultMemchunks *buf,
|
||||||
const HeaderRefs &headers) {
|
const HeaderRefs &headers,
|
||||||
for (auto &kv : headers) {
|
uint32_t flags) {
|
||||||
if (kv.name.empty() || kv.name[0] == ':') {
|
auto it_forwarded = std::end(headers);
|
||||||
|
auto it_xff = std::end(headers);
|
||||||
|
auto it_xfp = std::end(headers);
|
||||||
|
auto it_via = std::end(headers);
|
||||||
|
|
||||||
|
for (auto it = std::begin(headers); it != std::end(headers); ++it) {
|
||||||
|
auto kv = &(*it);
|
||||||
|
if (kv->name.empty() || kv->name[0] == ':') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switch (kv.token) {
|
switch (kv->token) {
|
||||||
case HD_CONNECTION:
|
case HD_CONNECTION:
|
||||||
case HD_COOKIE:
|
case HD_COOKIE:
|
||||||
case HD_FORWARDED:
|
|
||||||
case HD_HOST:
|
case HD_HOST:
|
||||||
case HD_HTTP2_SETTINGS:
|
case HD_HTTP2_SETTINGS:
|
||||||
case HD_KEEP_ALIVE:
|
case HD_KEEP_ALIVE:
|
||||||
case HD_PROXY_CONNECTION:
|
case HD_PROXY_CONNECTION:
|
||||||
case HD_SERVER:
|
case HD_SERVER:
|
||||||
case HD_UPGRADE:
|
case HD_UPGRADE:
|
||||||
case HD_VIA:
|
continue;
|
||||||
case HD_X_FORWARDED_FOR:
|
case HD_FORWARDED:
|
||||||
case HD_X_FORWARDED_PROTO:
|
if (flags & HDOP_STRIP_FORWARDED) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
capitalize(buf, kv.name);
|
|
||||||
|
if (it_forwarded == std::end(headers)) {
|
||||||
|
it_forwarded = it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
kv = &(*it_forwarded);
|
||||||
|
it_forwarded = it;
|
||||||
|
break;
|
||||||
|
case HD_X_FORWARDED_FOR:
|
||||||
|
if (flags & HDOP_STRIP_X_FORWARDED_FOR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it_xff == std::end(headers)) {
|
||||||
|
it_xff = it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
kv = &(*it_xff);
|
||||||
|
it_xff = it;
|
||||||
|
break;
|
||||||
|
case HD_X_FORWARDED_PROTO:
|
||||||
|
if (flags & HDOP_STRIP_X_FORWARDED_PROTO) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it_xfp == std::end(headers)) {
|
||||||
|
it_xfp = it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
kv = &(*it_xfp);
|
||||||
|
it_xfp = it;
|
||||||
|
break;
|
||||||
|
case HD_VIA:
|
||||||
|
if (flags & HDOP_STRIP_VIA) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it_via == std::end(headers)) {
|
||||||
|
it_via = it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
kv = &(*it_via);
|
||||||
|
it_via = it;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
capitalize(buf, kv->name);
|
||||||
buf->append(": ");
|
buf->append(": ");
|
||||||
buf->append(kv.value);
|
buf->append(kv->value);
|
||||||
buf->append("\r\n");
|
buf->append("\r\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
34
src/http2.h
34
src/http2.h
|
@ -187,24 +187,50 @@ nghttp2_nv make_nv_ls_nocopy(const char (&name)[N], const StringRef &value) {
|
||||||
NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE};
|
NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum HeaderBuildOp {
|
||||||
|
HDOP_NONE,
|
||||||
|
// Forwarded header fields must be stripped. If this flag is not
|
||||||
|
// set, all Forwarded header fields other than last one are added.
|
||||||
|
HDOP_STRIP_FORWARDED = 1,
|
||||||
|
// X-Forwarded-For header fields must be stripped. If this flag is
|
||||||
|
// not set, all X-Forwarded-For header fields other than last one
|
||||||
|
// are added.
|
||||||
|
HDOP_STRIP_X_FORWARDED_FOR = 1 << 1,
|
||||||
|
// X-Forwarded-Proto header fields must be stripped. If this flag
|
||||||
|
// is not set, all X-Forwarded-Proto header fields other than last
|
||||||
|
// one are added.
|
||||||
|
HDOP_STRIP_X_FORWARDED_PROTO = 1 << 2,
|
||||||
|
// Via header fields must be stripped. If this flag is not set, all
|
||||||
|
// Via header fields other than last one are added.
|
||||||
|
HDOP_STRIP_VIA = 1 << 3,
|
||||||
|
// Strip above all header fields.
|
||||||
|
HDOP_STRIP_ALL = HDOP_STRIP_FORWARDED | HDOP_STRIP_X_FORWARDED_FOR |
|
||||||
|
HDOP_STRIP_X_FORWARDED_PROTO | HDOP_STRIP_VIA,
|
||||||
|
};
|
||||||
|
|
||||||
// Appends headers in |headers| to |nv|. |headers| must be indexed
|
// Appends headers in |headers| to |nv|. |headers| must be indexed
|
||||||
// before this call (its element's token field is assigned). Certain
|
// before this call (its element's token field is assigned). Certain
|
||||||
// headers, including disallowed headers in HTTP/2 spec and headers
|
// headers, including disallowed headers in HTTP/2 spec and headers
|
||||||
// which require special handling (i.e. via), are not copied.
|
// which require special handling (i.e. via), are not copied. |flags|
|
||||||
|
// is one or more of HeaderBuildOp flags. They tell function that
|
||||||
|
// certain header fields should not be added.
|
||||||
void copy_headers_to_nva(std::vector<nghttp2_nv> &nva,
|
void copy_headers_to_nva(std::vector<nghttp2_nv> &nva,
|
||||||
const HeaderRefs &headers);
|
const HeaderRefs &headers, uint32_t flags);
|
||||||
|
|
||||||
// Just like copy_headers_to_nva(), but this adds
|
// Just like copy_headers_to_nva(), but this adds
|
||||||
// NGHTTP2_NV_FLAG_NO_COPY_NAME and NGHTTP2_NV_FLAG_NO_COPY_VALUE.
|
// NGHTTP2_NV_FLAG_NO_COPY_NAME and NGHTTP2_NV_FLAG_NO_COPY_VALUE.
|
||||||
void copy_headers_to_nva_nocopy(std::vector<nghttp2_nv> &nva,
|
void copy_headers_to_nva_nocopy(std::vector<nghttp2_nv> &nva,
|
||||||
const HeaderRefs &headers);
|
const HeaderRefs &headers, uint32_t flags);
|
||||||
|
|
||||||
// Appends HTTP/1.1 style header lines to |buf| from headers in
|
// Appends HTTP/1.1 style header lines to |buf| from headers in
|
||||||
// |headers|. |headers| must be indexed before this call (its
|
// |headers|. |headers| must be indexed before this call (its
|
||||||
// element's token field is assigned). Certain headers, which
|
// element's token field is assigned). Certain headers, which
|
||||||
// requires special handling (i.e. via and cookie), are not appended.
|
// requires special handling (i.e. via and cookie), are not appended.
|
||||||
|
// |flags| is one or more of HeaderBuildOp flags. They tell function
|
||||||
|
// that certain header fields should not be added.
|
||||||
void build_http1_headers_from_headers(DefaultMemchunks *buf,
|
void build_http1_headers_from_headers(DefaultMemchunks *buf,
|
||||||
const HeaderRefs &headers);
|
const HeaderRefs &headers,
|
||||||
|
uint32_t flags);
|
||||||
|
|
||||||
// Return positive window_size_increment if WINDOW_UPDATE should be
|
// Return positive window_size_increment if WINDOW_UPDATE should be
|
||||||
// sent for the stream |stream_id|. If |stream_id| == 0, this function
|
// sent for the stream |stream_id|. If |stream_id| == 0, this function
|
||||||
|
|
|
@ -150,11 +150,33 @@ auto headers = HeaderRefs{
|
||||||
{StringRef::from_lit("zulu"), StringRef::from_lit("12")}};
|
{StringRef::from_lit("zulu"), StringRef::from_lit("12")}};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
auto headers2 = HeaderRefs{
|
||||||
|
{StringRef::from_lit("x-forwarded-for"), StringRef::from_lit("xff1"), false,
|
||||||
|
http2::HD_X_FORWARDED_FOR},
|
||||||
|
{StringRef::from_lit("x-forwarded-for"), StringRef::from_lit("xff2"), false,
|
||||||
|
http2::HD_X_FORWARDED_FOR},
|
||||||
|
{StringRef::from_lit("x-forwarded-proto"), StringRef::from_lit("xfp1"),
|
||||||
|
false, http2::HD_X_FORWARDED_PROTO},
|
||||||
|
{StringRef::from_lit("x-forwarded-proto"), StringRef::from_lit("xfp2"),
|
||||||
|
false, http2::HD_X_FORWARDED_PROTO},
|
||||||
|
{StringRef::from_lit("forwarded"), StringRef::from_lit("fwd1"), false,
|
||||||
|
http2::HD_FORWARDED},
|
||||||
|
{StringRef::from_lit("forwarded"), StringRef::from_lit("fwd2"), false,
|
||||||
|
http2::HD_FORWARDED},
|
||||||
|
{StringRef::from_lit("via"), StringRef::from_lit("via1"), false,
|
||||||
|
http2::HD_VIA},
|
||||||
|
{StringRef::from_lit("via"), StringRef::from_lit("via2"), false,
|
||||||
|
http2::HD_VIA},
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
void test_http2_copy_headers_to_nva(void) {
|
void test_http2_copy_headers_to_nva(void) {
|
||||||
auto ans = std::vector<int>{0, 1, 4, 5, 6, 7, 12};
|
auto ans = std::vector<int>{0, 1, 4, 5, 6, 7, 12};
|
||||||
std::vector<nghttp2_nv> nva;
|
std::vector<nghttp2_nv> nva;
|
||||||
|
|
||||||
http2::copy_headers_to_nva_nocopy(nva, headers);
|
http2::copy_headers_to_nva_nocopy(nva, headers,
|
||||||
|
http2::HDOP_STRIP_X_FORWARDED_FOR);
|
||||||
CU_ASSERT(7 == nva.size());
|
CU_ASSERT(7 == nva.size());
|
||||||
for (size_t i = 0; i < ans.size(); ++i) {
|
for (size_t i = 0; i < ans.size(); ++i) {
|
||||||
check_nv(headers[ans[i]], &nva[i]);
|
check_nv(headers[ans[i]], &nva[i]);
|
||||||
|
@ -169,7 +191,7 @@ void test_http2_copy_headers_to_nva(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
nva.clear();
|
nva.clear();
|
||||||
http2::copy_headers_to_nva(nva, headers);
|
http2::copy_headers_to_nva(nva, headers, http2::HDOP_STRIP_X_FORWARDED_FOR);
|
||||||
CU_ASSERT(7 == nva.size());
|
CU_ASSERT(7 == nva.size());
|
||||||
for (size_t i = 0; i < ans.size(); ++i) {
|
for (size_t i = 0; i < ans.size(); ++i) {
|
||||||
check_nv(headers[ans[i]], &nva[i]);
|
check_nv(headers[ans[i]], &nva[i]);
|
||||||
|
@ -180,12 +202,27 @@ void test_http2_copy_headers_to_nva(void) {
|
||||||
CU_ASSERT(NGHTTP2_NV_FLAG_NONE == nva[i].flags);
|
CU_ASSERT(NGHTTP2_NV_FLAG_NONE == nva[i].flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nva.clear();
|
||||||
|
|
||||||
|
auto ans2 = std::vector<int>{0, 2, 4, 6};
|
||||||
|
http2::copy_headers_to_nva(nva, headers2, http2::HDOP_NONE);
|
||||||
|
CU_ASSERT(ans2.size() == nva.size());
|
||||||
|
for (size_t i = 0; i < ans2.size(); ++i) {
|
||||||
|
check_nv(headers2[ans2[i]], &nva[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
nva.clear();
|
||||||
|
|
||||||
|
http2::copy_headers_to_nva(nva, headers2, http2::HDOP_STRIP_ALL);
|
||||||
|
CU_ASSERT(nva.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_http2_build_http1_headers_from_headers(void) {
|
void test_http2_build_http1_headers_from_headers(void) {
|
||||||
MemchunkPool pool;
|
MemchunkPool pool;
|
||||||
DefaultMemchunks buf(&pool);
|
DefaultMemchunks buf(&pool);
|
||||||
http2::build_http1_headers_from_headers(&buf, headers);
|
http2::build_http1_headers_from_headers(&buf, headers,
|
||||||
|
http2::HDOP_STRIP_X_FORWARDED_FOR);
|
||||||
auto hdrs = std::string(buf.head->pos, buf.head->last);
|
auto hdrs = std::string(buf.head->pos, buf.head->last);
|
||||||
CU_ASSERT("Alpha: 0\r\n"
|
CU_ASSERT("Alpha: 0\r\n"
|
||||||
"Bravo: 1\r\n"
|
"Bravo: 1\r\n"
|
||||||
|
@ -196,6 +233,21 @@ void test_http2_build_http1_headers_from_headers(void) {
|
||||||
"Te: 8\r\n"
|
"Te: 8\r\n"
|
||||||
"Te: 9\r\n"
|
"Te: 9\r\n"
|
||||||
"Zulu: 12\r\n" == hdrs);
|
"Zulu: 12\r\n" == hdrs);
|
||||||
|
|
||||||
|
buf.reset();
|
||||||
|
|
||||||
|
http2::build_http1_headers_from_headers(&buf, headers2, http2::HDOP_NONE);
|
||||||
|
hdrs = std::string(buf.head->pos, buf.head->last);
|
||||||
|
CU_ASSERT("X-Forwarded-For: xff1\r\n"
|
||||||
|
"X-Forwarded-Proto: xfp1\r\n"
|
||||||
|
"Forwarded: fwd1\r\n"
|
||||||
|
"Via: via1\r\n" == hdrs);
|
||||||
|
|
||||||
|
buf.reset();
|
||||||
|
|
||||||
|
http2::build_http1_headers_from_headers(&buf, headers2,
|
||||||
|
http2::HDOP_STRIP_ALL);
|
||||||
|
CU_ASSERT(0 == buf.rleft());
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_http2_lws(void) {
|
void test_http2_lws(void) {
|
||||||
|
|
|
@ -203,7 +203,7 @@ ssize_t http2_data_read_callback(nghttp2_session *session, int32_t stream_id,
|
||||||
nva.reserve(trailers.size());
|
nva.reserve(trailers.size());
|
||||||
// We cannot use nocopy version, since nva may be touched after
|
// We cannot use nocopy version, since nva may be touched after
|
||||||
// Downstream object is deleted.
|
// Downstream object is deleted.
|
||||||
http2::copy_headers_to_nva(nva, trailers);
|
http2::copy_headers_to_nva(nva, trailers, http2::HDOP_STRIP_ALL);
|
||||||
if (!nva.empty()) {
|
if (!nva.empty()) {
|
||||||
rv = nghttp2_submit_trailer(session, stream_id, nva.data(), nva.size());
|
rv = nghttp2_submit_trailer(session, stream_id, nva.data(), nva.size());
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
|
@ -310,7 +310,16 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
nva.push_back(http2::make_nv_ls_nocopy(":authority", authority));
|
nva.push_back(http2::make_nv_ls_nocopy(":authority", authority));
|
||||||
}
|
}
|
||||||
|
|
||||||
http2::copy_headers_to_nva_nocopy(nva, req.fs.headers());
|
auto &fwdconf = httpconf.forwarded;
|
||||||
|
auto &xffconf = httpconf.xff;
|
||||||
|
auto &xfpconf = httpconf.xfp;
|
||||||
|
|
||||||
|
uint32_t build_flags =
|
||||||
|
(fwdconf.strip_incoming ? http2::HDOP_STRIP_FORWARDED : 0) |
|
||||||
|
(xffconf.strip_incoming ? http2::HDOP_STRIP_X_FORWARDED_FOR : 0) |
|
||||||
|
(xfpconf.strip_incoming ? http2::HDOP_STRIP_X_FORWARDED_PROTO : 0);
|
||||||
|
|
||||||
|
http2::copy_headers_to_nva_nocopy(nva, req.fs.headers(), build_flags);
|
||||||
|
|
||||||
if (!http2conf.no_cookie_crumbling) {
|
if (!http2conf.no_cookie_crumbling) {
|
||||||
downstream_->crumble_request_cookie(nva);
|
downstream_->crumble_request_cookie(nva);
|
||||||
|
@ -319,8 +328,6 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
auto upstream = downstream_->get_upstream();
|
auto upstream = downstream_->get_upstream();
|
||||||
auto handler = upstream->get_client_handler();
|
auto handler = upstream->get_client_handler();
|
||||||
|
|
||||||
auto &fwdconf = httpconf.forwarded;
|
|
||||||
|
|
||||||
auto fwd =
|
auto fwd =
|
||||||
fwdconf.strip_incoming ? nullptr : req.fs.header(http2::HD_FORWARDED);
|
fwdconf.strip_incoming ? nullptr : req.fs.header(http2::HD_FORWARDED);
|
||||||
|
|
||||||
|
@ -351,8 +358,6 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
nva.push_back(http2::make_nv_ls_nocopy("forwarded", fwd->value));
|
nva.push_back(http2::make_nv_ls_nocopy("forwarded", fwd->value));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &xffconf = httpconf.xff;
|
|
||||||
|
|
||||||
auto xff = xffconf.strip_incoming ? nullptr
|
auto xff = xffconf.strip_incoming ? nullptr
|
||||||
: req.fs.header(http2::HD_X_FORWARDED_FOR);
|
: req.fs.header(http2::HD_X_FORWARDED_FOR);
|
||||||
|
|
||||||
|
@ -371,7 +376,6 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config->http2_proxy && req.method != HTTP_CONNECT) {
|
if (!config->http2_proxy && req.method != HTTP_CONNECT) {
|
||||||
auto &xfpconf = httpconf.xfp;
|
|
||||||
auto xfp = xfpconf.strip_incoming
|
auto xfp = xfpconf.strip_incoming
|
||||||
? nullptr
|
? nullptr
|
||||||
: req.fs.header(http2::HD_X_FORWARDED_PROTO);
|
: req.fs.header(http2::HD_X_FORWARDED_PROTO);
|
||||||
|
|
|
@ -1418,7 +1418,7 @@ ssize_t downstream_data_read_callback(nghttp2_session *session,
|
||||||
if (!trailers.empty()) {
|
if (!trailers.empty()) {
|
||||||
std::vector<nghttp2_nv> nva;
|
std::vector<nghttp2_nv> nva;
|
||||||
nva.reserve(trailers.size());
|
nva.reserve(trailers.size());
|
||||||
http2::copy_headers_to_nva_nocopy(nva, trailers);
|
http2::copy_headers_to_nva_nocopy(nva, trailers, http2::HDOP_STRIP_ALL);
|
||||||
if (!nva.empty()) {
|
if (!nva.empty()) {
|
||||||
rv = nghttp2_submit_trailer(session, stream_id, nva.data(),
|
rv = nghttp2_submit_trailer(session, stream_id, nva.data(),
|
||||||
nva.size());
|
nva.size());
|
||||||
|
@ -1667,7 +1667,8 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
|
||||||
nva.push_back(http2::make_nv_ls_nocopy(":status", response_status));
|
nva.push_back(http2::make_nv_ls_nocopy(":status", response_status));
|
||||||
|
|
||||||
if (downstream->get_non_final_response()) {
|
if (downstream->get_non_final_response()) {
|
||||||
http2::copy_headers_to_nva_nocopy(nva, resp.fs.headers());
|
http2::copy_headers_to_nva_nocopy(nva, resp.fs.headers(),
|
||||||
|
http2::HDOP_STRIP_ALL);
|
||||||
|
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
log_response_headers(downstream, nva);
|
log_response_headers(downstream, nva);
|
||||||
|
@ -1687,7 +1688,8 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
http2::copy_headers_to_nva_nocopy(nva, resp.fs.headers());
|
http2::copy_headers_to_nva_nocopy(
|
||||||
|
nva, resp.fs.headers(), http2::HDOP_STRIP_ALL & ~http2::HDOP_STRIP_VIA);
|
||||||
|
|
||||||
if (!config->http2_proxy && !httpconf.no_server_rewrite) {
|
if (!config->http2_proxy && !httpconf.no_server_rewrite) {
|
||||||
nva.push_back(http2::make_nv_ls_nocopy("server", httpconf.server_name));
|
nva.push_back(http2::make_nv_ls_nocopy("server", httpconf.server_name));
|
||||||
|
|
|
@ -538,7 +538,16 @@ int HttpDownstreamConnection::push_request_headers() {
|
||||||
buf->append(authority);
|
buf->append(authority);
|
||||||
buf->append("\r\n");
|
buf->append("\r\n");
|
||||||
|
|
||||||
http2::build_http1_headers_from_headers(buf, req.fs.headers());
|
auto &fwdconf = httpconf.forwarded;
|
||||||
|
auto &xffconf = httpconf.xff;
|
||||||
|
auto &xfpconf = httpconf.xfp;
|
||||||
|
|
||||||
|
uint32_t build_flags =
|
||||||
|
(fwdconf.strip_incoming ? http2::HDOP_STRIP_FORWARDED : 0) |
|
||||||
|
(xffconf.strip_incoming ? http2::HDOP_STRIP_X_FORWARDED_FOR : 0) |
|
||||||
|
(xfpconf.strip_incoming ? http2::HDOP_STRIP_X_FORWARDED_PROTO : 0);
|
||||||
|
|
||||||
|
http2::build_http1_headers_from_headers(buf, req.fs.headers(), build_flags);
|
||||||
|
|
||||||
auto cookie = downstream_->assemble_request_cookie();
|
auto cookie = downstream_->assemble_request_cookie();
|
||||||
if (!cookie.empty()) {
|
if (!cookie.empty()) {
|
||||||
|
@ -577,8 +586,6 @@ int HttpDownstreamConnection::push_request_headers() {
|
||||||
auto upstream = downstream_->get_upstream();
|
auto upstream = downstream_->get_upstream();
|
||||||
auto handler = upstream->get_client_handler();
|
auto handler = upstream->get_client_handler();
|
||||||
|
|
||||||
auto &fwdconf = httpconf.forwarded;
|
|
||||||
|
|
||||||
auto fwd =
|
auto fwd =
|
||||||
fwdconf.strip_incoming ? nullptr : req.fs.header(http2::HD_FORWARDED);
|
fwdconf.strip_incoming ? nullptr : req.fs.header(http2::HD_FORWARDED);
|
||||||
|
|
||||||
|
@ -611,8 +618,6 @@ int HttpDownstreamConnection::push_request_headers() {
|
||||||
buf->append("\r\n");
|
buf->append("\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &xffconf = httpconf.xff;
|
|
||||||
|
|
||||||
auto xff = xffconf.strip_incoming ? nullptr
|
auto xff = xffconf.strip_incoming ? nullptr
|
||||||
: req.fs.header(http2::HD_X_FORWARDED_FOR);
|
: req.fs.header(http2::HD_X_FORWARDED_FOR);
|
||||||
|
|
||||||
|
@ -630,7 +635,6 @@ int HttpDownstreamConnection::push_request_headers() {
|
||||||
buf->append("\r\n");
|
buf->append("\r\n");
|
||||||
}
|
}
|
||||||
if (!config->http2_proxy && !connect_method) {
|
if (!config->http2_proxy && !connect_method) {
|
||||||
auto &xfpconf = httpconf.xfp;
|
|
||||||
auto xfp = xfpconf.strip_incoming
|
auto xfp = xfpconf.strip_incoming
|
||||||
? nullptr
|
? nullptr
|
||||||
: req.fs.header(http2::HD_X_FORWARDED_PROTO);
|
: req.fs.header(http2::HD_X_FORWARDED_PROTO);
|
||||||
|
@ -740,7 +744,8 @@ int HttpDownstreamConnection::end_upload_data() {
|
||||||
output->append("0\r\n\r\n");
|
output->append("0\r\n\r\n");
|
||||||
} else {
|
} else {
|
||||||
output->append("0\r\n");
|
output->append("0\r\n");
|
||||||
http2::build_http1_headers_from_headers(output, trailers);
|
http2::build_http1_headers_from_headers(output, trailers,
|
||||||
|
http2::HDOP_STRIP_ALL);
|
||||||
output->append("\r\n");
|
output->append("\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1059,9 +1059,10 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
|
||||||
get_client_handler()->get_upstream_scheme());
|
get_client_handler()->get_upstream_scheme());
|
||||||
}
|
}
|
||||||
|
|
||||||
http2::build_http1_headers_from_headers(buf, resp.fs.headers());
|
|
||||||
|
|
||||||
if (downstream->get_non_final_response()) {
|
if (downstream->get_non_final_response()) {
|
||||||
|
http2::build_http1_headers_from_headers(buf, resp.fs.headers(),
|
||||||
|
http2::HDOP_STRIP_ALL);
|
||||||
|
|
||||||
buf->append("\r\n");
|
buf->append("\r\n");
|
||||||
|
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
|
@ -1073,6 +1074,9 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
http2::build_http1_headers_from_headers(
|
||||||
|
buf, resp.fs.headers(), http2::HDOP_STRIP_ALL & ~http2::HDOP_STRIP_VIA);
|
||||||
|
|
||||||
auto worker = handler_->get_worker();
|
auto worker = handler_->get_worker();
|
||||||
|
|
||||||
// after graceful shutdown commenced, add connection: close header
|
// after graceful shutdown commenced, add connection: close header
|
||||||
|
@ -1205,7 +1209,8 @@ int HttpsUpstream::on_downstream_body_complete(Downstream *downstream) {
|
||||||
output->append("0\r\n\r\n");
|
output->append("0\r\n\r\n");
|
||||||
} else {
|
} else {
|
||||||
output->append("0\r\n");
|
output->append("0\r\n");
|
||||||
http2::build_http1_headers_from_headers(output, trailers);
|
http2::build_http1_headers_from_headers(output, trailers,
|
||||||
|
http2::HDOP_STRIP_ALL);
|
||||||
output->append("\r\n");
|
output->append("\r\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue