diff --git a/src/HttpServer.cc b/src/HttpServer.cc index a704460d..11751360 100644 --- a/src/HttpServer.cc +++ b/src/HttpServer.cc @@ -450,19 +450,20 @@ int Http2Handler::submit_response { std::string date_str = util::http_date(time(0)); const size_t static_size = 6; - auto nv = util::make_unique(static_size+headers.size()*2+1); - nv[0] = ":status"; - nv[1] = status.c_str(); - nv[2] = "server"; - nv[3] = NGHTTPD_SERVER.c_str(); - nv[4] = "date"; - nv[5] = date_str.c_str(); - for(int i = 0; i < (int)headers.size(); ++i) { - nv[static_size+i*2] = headers[i].first.c_str(); - nv[static_size+i*2+1] = headers[i].second.c_str(); + auto nv = std::vector(); + nv.reserve(static_size + headers.size() * 2 + 1); + nv.push_back(":status"); + nv.push_back(status.c_str()); + nv.push_back("server"); + nv.push_back(NGHTTPD_SERVER.c_str()); + nv.push_back("date"); + nv.push_back(date_str.c_str()); + for(size_t i = 0; i < headers.size(); ++i) { + nv.push_back(headers[i].first.c_str()); + nv.push_back(headers[i].second.c_str()); } - nv[static_size+headers.size()*2] = nullptr; - int r = nghttp2_submit_response(session_, stream_id, nv.get(), data_prd); + nv.push_back(nullptr); + int r = nghttp2_submit_response(session_, stream_id, nv.data(), data_prd); return r; } diff --git a/src/http2.cc b/src/http2.cc index 343a208c..68e39de8 100644 --- a/src/http2.cc +++ b/src/http2.cc @@ -269,16 +269,16 @@ bool value_lws(const nghttp2_nv *nv) return true; } -size_t copy_norm_headers_to_nv -(const char **nv, +void copy_norm_headers_to_nv +(std::vector& nv, const std::vector>& headers) { - size_t i, j, nvlen = 0; + size_t i, j; for(i = 0, j = 0; i < headers.size() && j < IGN_HDLEN;) { int rv = strcmp(headers[i].first.c_str(), IGN_HD[j]); if(rv < 0) { - nv[nvlen++] = headers[i].first.c_str(); - nv[nvlen++] = headers[i].second.c_str(); + nv.push_back(headers[i].first.c_str()); + nv.push_back(headers[i].second.c_str()); ++i; } else if(rv > 0) { ++j; @@ -287,10 +287,9 @@ size_t copy_norm_headers_to_nv } } for(; i < headers.size(); ++i) { - nv[nvlen++] = headers[i].first.c_str(); - nv[nvlen++] = headers[i].second.c_str(); + nv.push_back(headers[i].first.c_str()); + nv.push_back(headers[i].second.c_str()); } - return nvlen; } void build_http1_headers_from_norm_headers diff --git a/src/http2.h b/src/http2.h index 2583ec0b..0270e7c7 100644 --- a/src/http2.h +++ b/src/http2.h @@ -89,11 +89,11 @@ std::string value_to_str(const nghttp2_nv *nv); // Returns true if the value of |nv| includes only ' ' (0x20) or '\t'. bool value_lws(const nghttp2_nv *nv); -// Copies headers in |headers| to |nv|. Certain headers, including +// Appends headers in |headers| to |nv|. Certain headers, including // disallowed headers in HTTP/2.0 spec and headers which require // special handling (i.e. via), are not copied. -size_t copy_norm_headers_to_nv -(const char **nv, +void copy_norm_headers_to_nv +(std::vector& nv, const std::vector>& headers); // Appends HTTP/1.1 style header lines to |hdrs| from headers in diff --git a/src/http2_test.cc b/src/http2_test.cc index 3f24d950..bd1f7c20 100644 --- a/src/http2_test.cc +++ b/src/http2_test.cc @@ -132,9 +132,9 @@ auto headers = std::vector> void test_http2_copy_norm_headers_to_nv(void) { - const char* nv[30]; - size_t nvlen = http2::copy_norm_headers_to_nv(nv, headers); - CU_ASSERT(12 == nvlen); + std::vector nv; + http2::copy_norm_headers_to_nv(nv, headers); + CU_ASSERT(12 == nv.size()); CU_ASSERT(strcmp(nv[0], "alpha") == 0); CU_ASSERT(strcmp(nv[1], "0") == 0); CU_ASSERT(strcmp(nv[2], "bravo") == 0); diff --git a/src/shrpx_http2_upstream.cc b/src/shrpx_http2_upstream.cc index f03afc14..7be268a3 100644 --- a/src/shrpx_http2_upstream.cc +++ b/src/shrpx_http2_upstream.cc @@ -863,20 +863,19 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) auto end_headers = std::end(downstream->get_response_headers()); size_t nheader = downstream->get_response_headers().size(); // 4 means :status and possible via header field. - auto nv = util::make_unique(nheader * 2 + 4 + 1); - size_t hdidx = 0; + auto nv = std::vector(); + nv.reserve(nheader * 2 + 4 + 1); std::string via_value; auto response_status = util::utos(downstream->get_response_http_status()); - nv[hdidx++] = ":status"; - nv[hdidx++] = response_status.c_str(); + nv.push_back(":status"); + nv.push_back(response_status.c_str()); - hdidx += http2::copy_norm_headers_to_nv(&nv[hdidx], - downstream->get_response_headers()); + http2::copy_norm_headers_to_nv(nv, downstream->get_response_headers()); auto via = downstream->get_norm_response_header("via"); if(get_config()->no_via) { if(via != end_headers) { - nv[hdidx++] = "via"; - nv[hdidx++] = (*via).second.c_str(); + nv.push_back("via"); + nv.push_back((*via).second.c_str()); } } else { if(via != end_headers) { @@ -885,10 +884,10 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) } via_value += http::create_via_header_value (downstream->get_response_major(), downstream->get_response_minor()); - nv[hdidx++] = "via"; - nv[hdidx++] = via_value.c_str(); + nv.push_back("via"); + nv.push_back(via_value.c_str()); } - nv[hdidx++] = nullptr; + nv.push_back(nullptr); if(LOG_ENABLED(INFO)) { std::stringstream ss; for(size_t i = 0; nv[i]; i += 2) { @@ -903,8 +902,8 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) data_prd.read_callback = spdy_data_read_callback; int rv; - rv = nghttp2_submit_response(session_, downstream->get_stream_id(), nv.get(), - &data_prd); + rv = nghttp2_submit_response(session_, downstream->get_stream_id(), + nv.data(), &data_prd); if(rv != 0) { ULOG(FATAL, this) << "nghttp2_submit_response() failed"; return -1; diff --git a/src/shrpx_spdy_downstream_connection.cc b/src/shrpx_spdy_downstream_connection.cc index 527a4d96..bdc01c64 100644 --- a/src/shrpx_spdy_downstream_connection.cc +++ b/src/shrpx_spdy_downstream_connection.cc @@ -236,15 +236,15 @@ int SpdyDownstreamConnection::push_request_headers() // 10 means :method, :scheme, :path and possible via and // x-forwarded-for header fields. We rename host header field as // :host. - auto nv = util::make_unique(nheader * 2 + 10 + 1); - size_t hdidx = 0; + auto nv = std::vector(); + nv.reserve(nheader * 2 + 10 + 1); std::string via_value; std::string xff_value; std::string scheme, path, query; if(downstream_->get_request_method() == "CONNECT") { // No :scheme header field for CONNECT method. - nv[hdidx++] = ":path"; - nv[hdidx++] = downstream_->get_request_path().c_str(); + nv.push_back(":path"); + nv.push_back(downstream_->get_request_path().c_str()); } else { http_parser_url u; const char *url = downstream_->get_request_path().c_str(); @@ -264,27 +264,26 @@ int SpdyDownstreamConnection::push_request_headers() path += query; } } - nv[hdidx++] = ":scheme"; + nv.push_back(":scheme"); if(scheme.empty()) { // The default scheme is http. For SPDY upstream, the path must // be absolute URI, so scheme should be provided. - nv[hdidx++] = "http"; + nv.push_back("http"); } else { - nv[hdidx++] = scheme.c_str(); + nv.push_back(scheme.c_str()); } - nv[hdidx++] = ":path"; + nv.push_back(":path"); if(path.empty()) { - nv[hdidx++] = downstream_->get_request_path().c_str(); + nv.push_back(downstream_->get_request_path().c_str()); } else { - nv[hdidx++] = path.c_str(); + nv.push_back(path.c_str()); } } - nv[hdidx++] = ":method"; - nv[hdidx++] = downstream_->get_request_method().c_str(); + nv.push_back(":method"); + nv.push_back(downstream_->get_request_method().c_str()); - hdidx += http2::copy_norm_headers_to_nv(&nv[hdidx], - downstream_->get_request_headers()); + http2::copy_norm_headers_to_nv(nv, downstream_->get_request_headers()); auto host = downstream_->get_norm_request_header("host"); if(host == end_headers) { @@ -293,8 +292,8 @@ int SpdyDownstreamConnection::push_request_headers() } return -1; } - nv[hdidx++] = ":host"; - nv[hdidx++] = (*host).second.c_str(); + nv.push_back(":host"); + nv.push_back((*host).second.c_str()); bool content_length = false; if(downstream_->get_norm_request_header("content-length") != end_headers) { @@ -304,8 +303,8 @@ int SpdyDownstreamConnection::push_request_headers() auto expect = downstream_->get_norm_request_header("expect"); if(expect != end_headers && !util::strifind((*expect).second.c_str(), "100-continue")) { - nv[hdidx++] = "expect"; - nv[hdidx++] = (*expect).second.c_str(); + nv.push_back("expect"); + nv.push_back((*expect).second.c_str()); } bool chunked_encoding = false; @@ -318,24 +317,24 @@ int SpdyDownstreamConnection::push_request_headers() auto xff = downstream_->get_norm_request_header("x-forwarded-for"); if(get_config()->add_x_forwarded_for) { - nv[hdidx++] = "x-forwarded-for"; + nv.push_back("x-forwarded-for"); if(xff != end_headers) { xff_value = (*xff).second; xff_value += ", "; } xff_value += downstream_->get_upstream()->get_client_handler()-> get_ipaddr(); - nv[hdidx++] = xff_value.c_str(); + nv.push_back(xff_value.c_str()); } else if(xff != end_headers) { - nv[hdidx++] = "x-forwarded-for"; - nv[hdidx++] = (*xff).second.c_str(); + nv.push_back("x-forwarded-for"); + nv.push_back((*xff).second.c_str()); } auto via = downstream_->get_norm_request_header("via"); if(get_config()->no_via) { if(via != end_headers) { - nv[hdidx++] = "via"; - nv[hdidx++] = (*via).second.c_str(); + nv.push_back("via"); + nv.push_back((*via).second.c_str()); } } else { if(via != end_headers) { @@ -344,10 +343,10 @@ int SpdyDownstreamConnection::push_request_headers() } via_value += http::create_via_header_value (downstream_->get_request_major(), downstream_->get_request_minor()); - nv[hdidx++] = "via"; - nv[hdidx++] = via_value.c_str(); + nv.push_back("via"); + nv.push_back(via_value.c_str()); } - nv[hdidx++] = nullptr; + nv.push_back(nullptr); if(LOG_ENABLED(INFO)) { std::stringstream ss; @@ -363,9 +362,9 @@ int SpdyDownstreamConnection::push_request_headers() nghttp2_data_provider data_prd; data_prd.source.ptr = this; data_prd.read_callback = spdy_data_read_callback; - rv = spdy_->submit_request(this, 0, nv.get(), &data_prd); + rv = spdy_->submit_request(this, 0, nv.data(), &data_prd); } else { - rv = spdy_->submit_request(this, 0, nv.get(), 0); + rv = spdy_->submit_request(this, 0, nv.data(), nullptr); } if(rv != 0) { DCLOG(FATAL, this) << "nghttp2_submit_request() failed";