diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index 3e62a5b1..c4464129 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -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(p.name.c_str()), p.name.size()) || - !nghttp2_check_header_value( - reinterpret_cast(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 @@ -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; diff --git a/src/shrpx_config.h b/src/shrpx_config.h index a633b4fd..94065ca0 100644 --- a/src/shrpx_config.h +++ b/src/shrpx_config.h @@ -575,8 +575,8 @@ struct HttpConfig { } xff; std::vector altsvcs; std::vector 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 parse_log_format(BlockAllocator &balloc, const StringRef &optarg); diff --git a/src/shrpx_config_test.cc b/src/shrpx_config_test.cc index 224535d9..a3f259dd 100644 --- a/src/shrpx_config_test.cc +++ b/src/shrpx_config_test.cc @@ -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()); }