diff --git a/src/http2.cc b/src/http2.cc index 8385cafe..445ebe44 100644 --- a/src/http2.cc +++ b/src/http2.cc @@ -134,107 +134,107 @@ std::string get_status_string(unsigned int status_code) { } } -const char *stringify_status(unsigned int status_code) { +StringRef stringify_status(unsigned int status_code) { switch (status_code) { case 100: - return "100"; + return StringRef::from_lit("100"); case 101: - return "101"; + return StringRef::from_lit("101"); case 200: - return "200"; + return StringRef::from_lit("200"); case 201: - return "201"; + return StringRef::from_lit("201"); case 202: - return "202"; + return StringRef::from_lit("202"); case 203: - return "203"; + return StringRef::from_lit("203"); case 204: - return "204"; + return StringRef::from_lit("204"); case 205: - return "205"; + return StringRef::from_lit("205"); case 206: - return "206"; + return StringRef::from_lit("206"); case 300: - return "300"; + return StringRef::from_lit("300"); case 301: - return "301"; + return StringRef::from_lit("301"); case 302: - return "302"; + return StringRef::from_lit("302"); case 303: - return "303"; + return StringRef::from_lit("303"); case 304: - return "304"; + return StringRef::from_lit("304"); case 305: - return "305"; - // case 306: return "306"; + return StringRef::from_lit("305"); + // case 306: return StringRef::from_lit("306"); case 307: - return "307"; + return StringRef::from_lit("307"); case 308: - return "308"; + return StringRef::from_lit("308"); case 400: - return "400"; + return StringRef::from_lit("400"); case 401: - return "401"; + return StringRef::from_lit("401"); case 402: - return "402"; + return StringRef::from_lit("402"); case 403: - return "403"; + return StringRef::from_lit("403"); case 404: - return "404"; + return StringRef::from_lit("404"); case 405: - return "405"; + return StringRef::from_lit("405"); case 406: - return "406"; + return StringRef::from_lit("406"); case 407: - return "407"; + return StringRef::from_lit("407"); case 408: - return "408"; + return StringRef::from_lit("408"); case 409: - return "409"; + return StringRef::from_lit("409"); case 410: - return "410"; + return StringRef::from_lit("410"); case 411: - return "411"; + return StringRef::from_lit("411"); case 412: - return "412"; + return StringRef::from_lit("412"); case 413: - return "413"; + return StringRef::from_lit("413"); case 414: - return "414"; + return StringRef::from_lit("414"); case 415: - return "415"; + return StringRef::from_lit("415"); case 416: - return "416"; + return StringRef::from_lit("416"); case 417: - return "417"; + return StringRef::from_lit("417"); case 421: - return "421"; + return StringRef::from_lit("421"); case 426: - return "426"; + return StringRef::from_lit("426"); case 428: - return "428"; + return StringRef::from_lit("428"); case 429: - return "429"; + return StringRef::from_lit("429"); case 431: - return "431"; + return StringRef::from_lit("431"); case 451: - return "451"; + return StringRef::from_lit("451"); case 500: - return "500"; + return StringRef::from_lit("500"); case 501: - return "501"; + return StringRef::from_lit("501"); case 502: - return "502"; + return StringRef::from_lit("502"); case 503: - return "503"; + return StringRef::from_lit("503"); case 504: - return "504"; + return StringRef::from_lit("504"); case 505: - return "505"; + return StringRef::from_lit("505"); case 511: - return "511"; + return StringRef::from_lit("511"); default: - return nullptr; + return StringRef{}; } } diff --git a/src/http2.h b/src/http2.h index 48d4916d..0ae9d3b3 100644 --- a/src/http2.h +++ b/src/http2.h @@ -98,7 +98,7 @@ std::string get_status_string(unsigned int status_code); // Returns string version of |status_code|. This function can handle // only predefined status code. Otherwise, returns nullptr. -const char *stringify_status(unsigned int status_code); +StringRef stringify_status(unsigned int status_code); void capitalize(DefaultMemchunks *buf, const StringRef &s); diff --git a/src/shrpx-unittest.cc b/src/shrpx-unittest.cc index 0f2e2fd2..725838f8 100644 --- a/src/shrpx-unittest.cc +++ b/src/shrpx-unittest.cc @@ -143,6 +143,8 @@ int main(int argc, char *argv[]) { !CU_add_test(pSuite, "util_ipv6_numeric_addr", shrpx::test_util_ipv6_numeric_addr) || !CU_add_test(pSuite, "util_utos", shrpx::test_util_utos) || + !CU_add_test(pSuite, "util_make_string_ref_uint", + shrpx::test_util_make_string_ref_uint) || !CU_add_test(pSuite, "util_utos_unit", shrpx::test_util_utos_unit) || !CU_add_test(pSuite, "util_utos_funit", shrpx::test_util_utos_funit) || !CU_add_test(pSuite, "util_parse_uint_with_unit", diff --git a/src/shrpx_http2_upstream.cc b/src/shrpx_http2_upstream.cc index 79fac5de..e54b8e90 100644 --- a/src/shrpx_http2_upstream.cc +++ b/src/shrpx_http2_upstream.cc @@ -1229,20 +1229,20 @@ int Http2Upstream::send_reply(Downstream *downstream, const uint8_t *body, const auto &resp = downstream->response(); auto &httpconf = get_config()->http; + auto &balloc = downstream->get_block_allocator(); + const auto &headers = resp.fs.headers(); auto nva = std::vector(); // 2 for :status and server nva.reserve(2 + headers.size() + httpconf.add_response_headers.size()); - std::string status_code_str; - auto response_status_const = http2::stringify_status(resp.http_status); - if (response_status_const) { - nva.push_back(http2::make_nv_lc_nocopy(":status", response_status_const)); - } else { - status_code_str = util::utos(resp.http_status); - nva.push_back(http2::make_nv_ls(":status", status_code_str)); + auto response_status = http2::stringify_status(resp.http_status); + if (response_status.empty()) { + response_status = util::make_string_ref_uint(balloc, resp.http_status); } + nva.push_back(http2::make_nv_ls_nocopy(":status", response_status)); + for (auto &kv : headers) { if (kv.name.empty() || kv.name[0] == ':') { continue; @@ -1290,6 +1290,8 @@ int Http2Upstream::error_reply(Downstream *downstream, int rv; auto &resp = downstream->response(); + auto &balloc = downstream->get_block_allocator(); + auto html = http::create_error_html(status_code); resp.http_status = status_code; auto body = downstream->get_response_buf(); @@ -1303,20 +1305,20 @@ int Http2Upstream::error_reply(Downstream *downstream, auto lgconf = log_config(); lgconf->update_tstamp(std::chrono::system_clock::now()); - auto response_status_const = http2::stringify_status(status_code); - auto content_length = util::utos(html.size()); + auto response_status = http2::stringify_status(status_code); + if (response_status.empty()) { + response_status = util::make_string_ref_uint(balloc, status_code); + } - std::string status_code_str; + auto content_length = util::make_string_ref_uint(balloc, html.size()); + auto date = make_string_ref(balloc, StringRef{lgconf->time_http_str}); - auto nva = make_array( - response_status_const - ? http2::make_nv_lc_nocopy(":status", response_status_const) - : http2::make_nv_ls(":status", - (status_code_str = util::utos(status_code))), - http2::make_nv_ll("content-type", "text/html; charset=UTF-8"), - http2::make_nv_ls_nocopy("server", get_config()->http.server_name), - http2::make_nv_ls("content-length", content_length), - http2::make_nv_ls("date", lgconf->time_http_str)); + auto nva = std::array{ + {http2::make_nv_ls_nocopy(":status", response_status), + http2::make_nv_ll("content-type", "text/html; charset=UTF-8"), + http2::make_nv_ls_nocopy("server", get_config()->http.server_name), + http2::make_nv_ls_nocopy("content-length", content_length), + http2::make_nv_ls_nocopy("date", date)}}; rv = nghttp2_submit_response(session_, downstream->get_stream_id(), nva.data(), nva.size(), &data_prd); @@ -1357,6 +1359,8 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) { const auto &req = downstream->request(); auto &resp = downstream->response(); + auto &balloc = downstream->get_block_allocator(); + if (LOG_ENABLED(INFO)) { if (downstream->get_non_final_response()) { DLOG(INFO, downstream) << "HTTP non-final response header"; @@ -1396,16 +1400,14 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) { nva.reserve(resp.fs.headers().size() + 4 + httpconf.add_response_headers.size()); std::string via_value; - std::string response_status; - auto response_status_const = http2::stringify_status(resp.http_status); - if (response_status_const) { - nva.push_back(http2::make_nv_lc_nocopy(":status", response_status_const)); - } else { - response_status = util::utos(resp.http_status); - nva.push_back(http2::make_nv_ls(":status", response_status)); + auto response_status = http2::stringify_status(resp.http_status); + if (response_status.empty()) { + response_status = util::make_string_ref_uint(balloc, resp.http_status); } + nva.push_back(http2::make_nv_ls_nocopy(":status", response_status)); + if (downstream->get_non_final_response()) { http2::copy_headers_to_nva(nva, resp.fs.headers()); diff --git a/src/shrpx_mruby_module_response.cc b/src/shrpx_mruby_module_response.cc index 65fec390..8a89a058 100644 --- a/src/shrpx_mruby_module_response.cc +++ b/src/shrpx_mruby_module_response.cc @@ -215,14 +215,7 @@ mrb_value response_return(mrb_state *mrb, mrb_value self) { bodylen = vallen; } - StringRef content_length; - { - auto iov = make_byte_ref(balloc, str_size("18446744073709551615") + 1); - auto p = iov.base; - p = util::utos(p, bodylen); - *p = '\0'; - content_length = StringRef{iov.base, p}; - } + auto content_length = util::make_string_ref_uint(balloc, bodylen); auto cl = resp.fs.header(http2::HD_CONTENT_LENGTH); if (cl) { diff --git a/src/util.h b/src/util.h index 4f926e2a..2d3208fc 100644 --- a/src/util.h +++ b/src/util.h @@ -51,6 +51,7 @@ #include "template.h" #include "network.h" +#include "allocator.h" namespace nghttp2 { @@ -405,6 +406,15 @@ template OutputIt utos(OutputIt dst, T n) { return res; } +template +StringRef make_string_ref_uint(BlockAllocator &balloc, T n) { + auto iov = make_byte_ref(balloc, str_size("18446744073709551615") + 1); + auto p = iov.base; + p = util::utos(p, n); + *p = '\0'; + return StringRef{iov.base, p}; +} + template std::string utos_unit(T n) { char u = 0; if (n >= (1 << 30)) { diff --git a/src/util_test.cc b/src/util_test.cc index 0a17e255..8a8ee181 100644 --- a/src/util_test.cc +++ b/src/util_test.cc @@ -239,8 +239,17 @@ void test_util_utos(void) { CU_ASSERT(("0" == StringRef{buf, util::utos(buf, 0)})); CU_ASSERT(("123" == StringRef{buf, util::utos(buf, 123)})); - CU_ASSERT(("9223372036854775808" == - StringRef{buf, util::utos(buf, 9223372036854775808ULL)})); + CU_ASSERT(("18446744073709551615" == + StringRef{buf, util::utos(buf, 18446744073709551615ULL)})); +} + +void test_util_make_string_ref_uint(void) { + BlockAllocator balloc(1024, 1024); + + CU_ASSERT("0" == util::make_string_ref_uint(balloc, 0)); + CU_ASSERT("123" == util::make_string_ref_uint(balloc, 123)); + CU_ASSERT("18446744073709551615" == + util::make_string_ref_uint(balloc, 18446744073709551615ULL)); } void test_util_utos_unit(void) { diff --git a/src/util_test.h b/src/util_test.h index f51692aa..b44d5b17 100644 --- a/src/util_test.h +++ b/src/util_test.h @@ -45,6 +45,7 @@ void test_util_http_date(void); void test_util_select_h2(void); void test_util_ipv6_numeric_addr(void); void test_util_utos(void); +void test_util_make_string_ref_uint(void); void test_util_utos_unit(void); void test_util_utos_funit(void); void test_util_parse_uint_with_unit(void);