nghttpx: Parse te header field a bit more properly
This commit is contained in:
parent
f5a4c9d971
commit
8471c9e92e
25
src/http2.cc
25
src/http2.cc
|
@ -1665,6 +1665,31 @@ StringRef copy_lower(BlockAllocator &balloc, const StringRef &src) {
|
||||||
return StringRef{iov.base, p};
|
return StringRef{iov.base, p};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool contains_trailers(const StringRef &s) {
|
||||||
|
constexpr auto trailers = StringRef::from_lit("trailers");
|
||||||
|
|
||||||
|
for (auto p = std::begin(s), end = std::end(s);; ++p) {
|
||||||
|
p = std::find_if(p, end, [](char c) { return c != ' ' && c != '\t'; });
|
||||||
|
if (p == end || end - p < trailers.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (util::strieq(trailers, StringRef{p, p + trailers.size()})) {
|
||||||
|
// Make sure that there is no character other than white spaces
|
||||||
|
// before next "," or end of string.
|
||||||
|
p = std::find_if(p + trailers.size(), end,
|
||||||
|
[](char c) { return c != ' ' && c != '\t'; });
|
||||||
|
if (p == end || *p == ',') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Skip to next ",".
|
||||||
|
p = std::find_if(p, end, [](char c) { return c == ','; });
|
||||||
|
if (p == end) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace http2
|
} // namespace http2
|
||||||
|
|
||||||
} // namespace nghttp2
|
} // namespace nghttp2
|
||||||
|
|
|
@ -384,6 +384,9 @@ int construct_push_component(BlockAllocator &balloc, StringRef &scheme,
|
||||||
// Copies |src| and return its lower-cased version.
|
// Copies |src| and return its lower-cased version.
|
||||||
StringRef copy_lower(BlockAllocator &balloc, const StringRef &src);
|
StringRef copy_lower(BlockAllocator &balloc, const StringRef &src);
|
||||||
|
|
||||||
|
// Returns true if te header field value |s| contains "trailers".
|
||||||
|
bool contains_trailers(const StringRef &s);
|
||||||
|
|
||||||
} // namespace http2
|
} // namespace http2
|
||||||
|
|
||||||
} // namespace nghttp2
|
} // namespace nghttp2
|
||||||
|
|
|
@ -962,4 +962,20 @@ void test_http2_construct_push_component(void) {
|
||||||
CU_ASSERT("/b/?q=a" == path);
|
CU_ASSERT("/b/?q=a" == path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_http2_contains_trailers(void) {
|
||||||
|
CU_ASSERT(!http2::contains_trailers(StringRef::from_lit("")));
|
||||||
|
CU_ASSERT(http2::contains_trailers(StringRef::from_lit("trailers")));
|
||||||
|
// Match must be case-insensitive.
|
||||||
|
CU_ASSERT(http2::contains_trailers(StringRef::from_lit("TRAILERS")));
|
||||||
|
CU_ASSERT(!http2::contains_trailers(StringRef::from_lit("trailer")));
|
||||||
|
CU_ASSERT(!http2::contains_trailers(StringRef::from_lit("trailers 3")));
|
||||||
|
CU_ASSERT(http2::contains_trailers(StringRef::from_lit("trailers,")));
|
||||||
|
CU_ASSERT(http2::contains_trailers(StringRef::from_lit("trailers,foo")));
|
||||||
|
CU_ASSERT(http2::contains_trailers(StringRef::from_lit("foo,trailers")));
|
||||||
|
CU_ASSERT(http2::contains_trailers(StringRef::from_lit("foo,trailers,bar")));
|
||||||
|
CU_ASSERT(
|
||||||
|
http2::contains_trailers(StringRef::from_lit("foo, trailers ,bar")));
|
||||||
|
CU_ASSERT(http2::contains_trailers(StringRef::from_lit(",trailers")));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -46,6 +46,7 @@ void test_http2_normalize_path(void);
|
||||||
void test_http2_rewrite_clean_path(void);
|
void test_http2_rewrite_clean_path(void);
|
||||||
void test_http2_get_pure_path_component(void);
|
void test_http2_get_pure_path_component(void);
|
||||||
void test_http2_construct_push_component(void);
|
void test_http2_construct_push_component(void);
|
||||||
|
void test_http2_contains_trailers(void);
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
||||||
|
|
|
@ -102,6 +102,8 @@ int main(int argc, char *argv[]) {
|
||||||
shrpx::test_http2_get_pure_path_component) ||
|
shrpx::test_http2_get_pure_path_component) ||
|
||||||
!CU_add_test(pSuite, "http2_construct_push_component",
|
!CU_add_test(pSuite, "http2_construct_push_component",
|
||||||
shrpx::test_http2_construct_push_component) ||
|
shrpx::test_http2_construct_push_component) ||
|
||||||
|
!CU_add_test(pSuite, "http2_contains_trailers",
|
||||||
|
shrpx::test_http2_contains_trailers) ||
|
||||||
!CU_add_test(pSuite, "downstream_field_store_append_last_header",
|
!CU_add_test(pSuite, "downstream_field_store_append_last_header",
|
||||||
shrpx::test_downstream_field_store_append_last_header) ||
|
shrpx::test_downstream_field_store_append_last_header) ||
|
||||||
!CU_add_test(pSuite, "downstream_field_store_header",
|
!CU_add_test(pSuite, "downstream_field_store_header",
|
||||||
|
|
|
@ -402,7 +402,7 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
// HTTP/1 upstream request can contain keyword other than
|
// HTTP/1 upstream request can contain keyword other than
|
||||||
// "trailers". We just forward "trailers".
|
// "trailers". We just forward "trailers".
|
||||||
// TODO more strict handling required here.
|
// TODO more strict handling required here.
|
||||||
if (te && util::strifind(te->value, StringRef::from_lit("trailers"))) {
|
if (te && http2::contains_trailers(te->value)) {
|
||||||
nva.push_back(http2::make_nv_ll("te", "trailers"));
|
nva.push_back(http2::make_nv_ll("te", "trailers"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue