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
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), ':');
if (colon == std::end(optarg) || colon == std::begin(optarg)) {
return {"", ""};
return {};
}
auto value = colon + 1;
for (; *value == '\t' || *value == ' '; ++value)
;
auto p = Header(std::string{std::begin(optarg), colon},
std::string{value, std::end(optarg)});
util::inp_strlower(p.name);
auto name_iov =
make_byte_ref(balloc, std::distance(std::begin(optarg), colon) + 1);
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(
reinterpret_cast<const uint8_t *>(p.name.c_str()), p.name.size()) ||
!nghttp2_check_header_value(
reinterpret_cast<const uint8_t *>(p.value.c_str()), p.value.size())) {
return Header{};
auto nv =
HeaderRef(StringRef{name_iov.base, p},
make_string_ref(balloc, StringRef{value, std::end(optarg)}));
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>
@ -2389,7 +2395,7 @@ int parse_config(Config *config, int optid, const StringRef &opt,
}
case SHRPX_OPTID_ADD_REQUEST_HEADER:
case SHRPX_OPTID_ADD_RESPONSE_HEADER: {
auto p = parse_header(optarg);
auto p = parse_header(config->balloc, optarg);
if (p.name.empty()) {
LOG(ERROR) << opt << ": invalid header field: " << optarg;
return -1;

View File

@ -575,8 +575,8 @@ struct HttpConfig {
} xff;
std::vector<AltSvc> altsvcs;
std::vector<ErrorPage> error_pages;
Headers add_request_headers;
Headers add_response_headers;
HeaderRefs add_request_headers;
HeaderRefs add_response_headers;
StringRef server_name;
size_t request_header_field_buffer;
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. ":"
// is allowed at the start of the NAME, but NAME == ":" is not
// 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,
const StringRef &optarg);

View File

@ -37,32 +37,34 @@
namespace shrpx {
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("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("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());
p = parse_header(StringRef::from_lit("a: :b"));
p = parse_header(balloc, StringRef::from_lit("a: :b"));
CU_ASSERT("a" == p.name);
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());
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("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());
p = parse_header(StringRef::from_lit("a: b\x0a"));
p = parse_header(balloc, StringRef::from_lit("a: b\x0a"));
CU_ASSERT(p.name.empty());
}