nghttpx: Use HeaderRefs for add_request_headers and add_response_headers

This commit is contained in:
Tatsuhiro Tsujikawa 2016-10-02 22:04:04 +09:00
parent 99a91e3172
commit fdc1eb526b
3 changed files with 32 additions and 23 deletions

View File

@ -272,29 +272,35 @@ std::string read_passwd_from_file(const StringRef &opt,
} }
} // namespace } // namespace
Headers::value_type parse_header(const StringRef &optarg) { HeaderRefs::value_type parse_header(BlockAllocator &balloc,
const StringRef &optarg) {
auto colon = std::find(std::begin(optarg), std::end(optarg), ':'); auto colon = std::find(std::begin(optarg), std::end(optarg), ':');
if (colon == std::end(optarg) || colon == std::begin(optarg)) { if (colon == std::end(optarg) || colon == std::begin(optarg)) {
return {"", ""}; return {};
} }
auto value = colon + 1; auto value = colon + 1;
for (; *value == '\t' || *value == ' '; ++value) for (; *value == '\t' || *value == ' '; ++value)
; ;
auto p = Header(std::string{std::begin(optarg), colon}, auto name_iov =
std::string{value, std::end(optarg)}); make_byte_ref(balloc, std::distance(std::begin(optarg), colon) + 1);
util::inp_strlower(p.name); auto p = name_iov.base;
p = std::copy(std::begin(optarg), colon, p);
util::inp_strlower(name_iov.base, p);
*p = '\0';
if (!nghttp2_check_header_name( auto nv =
reinterpret_cast<const uint8_t *>(p.name.c_str()), p.name.size()) || HeaderRef(StringRef{name_iov.base, p},
!nghttp2_check_header_value( make_string_ref(balloc, StringRef{value, std::end(optarg)}));
reinterpret_cast<const uint8_t *>(p.value.c_str()), p.value.size())) {
return Header{}; if (!nghttp2_check_header_name(nv.name.byte(), nv.name.size()) ||
!nghttp2_check_header_value(nv.value.byte(), nv.value.size())) {
return {};
} }
return p; return nv;
} }
template <typename T> template <typename T>
@ -2389,7 +2395,7 @@ int parse_config(Config *config, int optid, const StringRef &opt,
} }
case SHRPX_OPTID_ADD_REQUEST_HEADER: case SHRPX_OPTID_ADD_REQUEST_HEADER:
case SHRPX_OPTID_ADD_RESPONSE_HEADER: { case SHRPX_OPTID_ADD_RESPONSE_HEADER: {
auto p = parse_header(optarg); auto p = parse_header(config->balloc, optarg);
if (p.name.empty()) { if (p.name.empty()) {
LOG(ERROR) << opt << ": invalid header field: " << optarg; LOG(ERROR) << opt << ": invalid header field: " << optarg;
return -1; return -1;

View File

@ -575,8 +575,8 @@ struct HttpConfig {
} xff; } xff;
std::vector<AltSvc> altsvcs; std::vector<AltSvc> altsvcs;
std::vector<ErrorPage> error_pages; std::vector<ErrorPage> error_pages;
Headers add_request_headers; HeaderRefs add_request_headers;
Headers add_response_headers; HeaderRefs add_response_headers;
StringRef server_name; StringRef server_name;
size_t request_header_field_buffer; size_t request_header_field_buffer;
size_t max_request_header_fields; size_t max_request_header_fields;
@ -987,7 +987,8 @@ int load_config(Config *config, const char *filename,
// like "NAME: VALUE". We require that NAME is non empty string. ":" // like "NAME: VALUE". We require that NAME is non empty string. ":"
// is allowed at the start of the NAME, but NAME == ":" is not // is allowed at the start of the NAME, but NAME == ":" is not
// allowed. This function returns pair of NAME and VALUE. // allowed. This function returns pair of NAME and VALUE.
Headers::value_type parse_header(const StringRef &optarg); HeaderRefs::value_type parse_header(BlockAllocator &balloc,
const StringRef &optarg);
std::vector<LogFragment> parse_log_format(BlockAllocator &balloc, std::vector<LogFragment> parse_log_format(BlockAllocator &balloc,
const StringRef &optarg); const StringRef &optarg);

View File

@ -37,32 +37,34 @@
namespace shrpx { namespace shrpx {
void test_shrpx_config_parse_header(void) { void test_shrpx_config_parse_header(void) {
auto p = parse_header(StringRef::from_lit("a: b")); BlockAllocator balloc(4096, 4096);
auto p = parse_header(balloc, StringRef::from_lit("a: b"));
CU_ASSERT("a" == p.name); CU_ASSERT("a" == p.name);
CU_ASSERT("b" == p.value); CU_ASSERT("b" == p.value);
p = parse_header(StringRef::from_lit("a: b")); p = parse_header(balloc, StringRef::from_lit("a: b"));
CU_ASSERT("a" == p.name); CU_ASSERT("a" == p.name);
CU_ASSERT("b" == p.value); CU_ASSERT("b" == p.value);
p = parse_header(StringRef::from_lit(":a: b")); p = parse_header(balloc, StringRef::from_lit(":a: b"));
CU_ASSERT(p.name.empty()); CU_ASSERT(p.name.empty());
p = parse_header(StringRef::from_lit("a: :b")); p = parse_header(balloc, StringRef::from_lit("a: :b"));
CU_ASSERT("a" == p.name); CU_ASSERT("a" == p.name);
CU_ASSERT(":b" == p.value); CU_ASSERT(":b" == p.value);
p = parse_header(StringRef::from_lit(": b")); p = parse_header(balloc, StringRef::from_lit(": b"));
CU_ASSERT(p.name.empty()); CU_ASSERT(p.name.empty());
p = parse_header(StringRef::from_lit("alpha: bravo charlie")); p = parse_header(balloc, StringRef::from_lit("alpha: bravo charlie"));
CU_ASSERT("alpha" == p.name); CU_ASSERT("alpha" == p.name);
CU_ASSERT("bravo charlie" == p.value); CU_ASSERT("bravo charlie" == p.value);
p = parse_header(StringRef::from_lit("a,: b")); p = parse_header(balloc, StringRef::from_lit("a,: b"));
CU_ASSERT(p.name.empty()); CU_ASSERT(p.name.empty());
p = parse_header(StringRef::from_lit("a: b\x0a")); p = parse_header(balloc, StringRef::from_lit("a: b\x0a"));
CU_ASSERT(p.name.empty()); CU_ASSERT(p.name.empty());
} }