src: Use std::vector to store name/value pairs

This commit is contained in:
Tatsuhiro Tsujikawa 2013-10-23 23:18:24 +09:00
parent 7b87d71121
commit 8c855c5567
6 changed files with 66 additions and 68 deletions

View File

@ -450,19 +450,20 @@ int Http2Handler::submit_response
{ {
std::string date_str = util::http_date(time(0)); std::string date_str = util::http_date(time(0));
const size_t static_size = 6; const size_t static_size = 6;
auto nv = util::make_unique<const char*[]>(static_size+headers.size()*2+1); auto nv = std::vector<const char*>();
nv[0] = ":status"; nv.reserve(static_size + headers.size() * 2 + 1);
nv[1] = status.c_str(); nv.push_back(":status");
nv[2] = "server"; nv.push_back(status.c_str());
nv[3] = NGHTTPD_SERVER.c_str(); nv.push_back("server");
nv[4] = "date"; nv.push_back(NGHTTPD_SERVER.c_str());
nv[5] = date_str.c_str(); nv.push_back("date");
for(int i = 0; i < (int)headers.size(); ++i) { nv.push_back(date_str.c_str());
nv[static_size+i*2] = headers[i].first.c_str(); for(size_t i = 0; i < headers.size(); ++i) {
nv[static_size+i*2+1] = headers[i].second.c_str(); nv.push_back(headers[i].first.c_str());
nv.push_back(headers[i].second.c_str());
} }
nv[static_size+headers.size()*2] = nullptr; nv.push_back(nullptr);
int r = nghttp2_submit_response(session_, stream_id, nv.get(), data_prd); int r = nghttp2_submit_response(session_, stream_id, nv.data(), data_prd);
return r; return r;
} }

View File

@ -269,16 +269,16 @@ bool value_lws(const nghttp2_nv *nv)
return true; return true;
} }
size_t copy_norm_headers_to_nv void copy_norm_headers_to_nv
(const char **nv, (std::vector<const char*>& nv,
const std::vector<std::pair<std::string, std::string>>& headers) const std::vector<std::pair<std::string, std::string>>& headers)
{ {
size_t i, j, nvlen = 0; size_t i, j;
for(i = 0, j = 0; i < headers.size() && j < IGN_HDLEN;) { for(i = 0, j = 0; i < headers.size() && j < IGN_HDLEN;) {
int rv = strcmp(headers[i].first.c_str(), IGN_HD[j]); int rv = strcmp(headers[i].first.c_str(), IGN_HD[j]);
if(rv < 0) { if(rv < 0) {
nv[nvlen++] = headers[i].first.c_str(); nv.push_back(headers[i].first.c_str());
nv[nvlen++] = headers[i].second.c_str(); nv.push_back(headers[i].second.c_str());
++i; ++i;
} else if(rv > 0) { } else if(rv > 0) {
++j; ++j;
@ -287,10 +287,9 @@ size_t copy_norm_headers_to_nv
} }
} }
for(; i < headers.size(); ++i) { for(; i < headers.size(); ++i) {
nv[nvlen++] = headers[i].first.c_str(); nv.push_back(headers[i].first.c_str());
nv[nvlen++] = headers[i].second.c_str(); nv.push_back(headers[i].second.c_str());
} }
return nvlen;
} }
void build_http1_headers_from_norm_headers void build_http1_headers_from_norm_headers

View File

@ -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'. // Returns true if the value of |nv| includes only ' ' (0x20) or '\t'.
bool value_lws(const nghttp2_nv *nv); 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 // disallowed headers in HTTP/2.0 spec and headers which require
// special handling (i.e. via), are not copied. // special handling (i.e. via), are not copied.
size_t copy_norm_headers_to_nv void copy_norm_headers_to_nv
(const char **nv, (std::vector<const char*>& nv,
const std::vector<std::pair<std::string, std::string>>& headers); const std::vector<std::pair<std::string, std::string>>& headers);
// Appends HTTP/1.1 style header lines to |hdrs| from headers in // Appends HTTP/1.1 style header lines to |hdrs| from headers in

View File

@ -132,9 +132,9 @@ auto headers = std::vector<std::pair<std::string, std::string>>
void test_http2_copy_norm_headers_to_nv(void) void test_http2_copy_norm_headers_to_nv(void)
{ {
const char* nv[30]; std::vector<const char*> nv;
size_t nvlen = http2::copy_norm_headers_to_nv(nv, headers); http2::copy_norm_headers_to_nv(nv, headers);
CU_ASSERT(12 == nvlen); CU_ASSERT(12 == nv.size());
CU_ASSERT(strcmp(nv[0], "alpha") == 0); CU_ASSERT(strcmp(nv[0], "alpha") == 0);
CU_ASSERT(strcmp(nv[1], "0") == 0); CU_ASSERT(strcmp(nv[1], "0") == 0);
CU_ASSERT(strcmp(nv[2], "bravo") == 0); CU_ASSERT(strcmp(nv[2], "bravo") == 0);

View File

@ -863,20 +863,19 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream)
auto end_headers = std::end(downstream->get_response_headers()); auto end_headers = std::end(downstream->get_response_headers());
size_t nheader = downstream->get_response_headers().size(); size_t nheader = downstream->get_response_headers().size();
// 4 means :status and possible via header field. // 4 means :status and possible via header field.
auto nv = util::make_unique<const char*[]>(nheader * 2 + 4 + 1); auto nv = std::vector<const char*>();
size_t hdidx = 0; nv.reserve(nheader * 2 + 4 + 1);
std::string via_value; std::string via_value;
auto response_status = util::utos(downstream->get_response_http_status()); auto response_status = util::utos(downstream->get_response_http_status());
nv[hdidx++] = ":status"; nv.push_back(":status");
nv[hdidx++] = response_status.c_str(); nv.push_back(response_status.c_str());
hdidx += http2::copy_norm_headers_to_nv(&nv[hdidx], http2::copy_norm_headers_to_nv(nv, downstream->get_response_headers());
downstream->get_response_headers());
auto via = downstream->get_norm_response_header("via"); auto via = downstream->get_norm_response_header("via");
if(get_config()->no_via) { if(get_config()->no_via) {
if(via != end_headers) { if(via != end_headers) {
nv[hdidx++] = "via"; nv.push_back("via");
nv[hdidx++] = (*via).second.c_str(); nv.push_back((*via).second.c_str());
} }
} else { } else {
if(via != end_headers) { if(via != end_headers) {
@ -885,10 +884,10 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream)
} }
via_value += http::create_via_header_value via_value += http::create_via_header_value
(downstream->get_response_major(), downstream->get_response_minor()); (downstream->get_response_major(), downstream->get_response_minor());
nv[hdidx++] = "via"; nv.push_back("via");
nv[hdidx++] = via_value.c_str(); nv.push_back(via_value.c_str());
} }
nv[hdidx++] = nullptr; nv.push_back(nullptr);
if(LOG_ENABLED(INFO)) { if(LOG_ENABLED(INFO)) {
std::stringstream ss; std::stringstream ss;
for(size_t i = 0; nv[i]; i += 2) { 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; data_prd.read_callback = spdy_data_read_callback;
int rv; int rv;
rv = nghttp2_submit_response(session_, downstream->get_stream_id(), nv.get(), rv = nghttp2_submit_response(session_, downstream->get_stream_id(),
&data_prd); nv.data(), &data_prd);
if(rv != 0) { if(rv != 0) {
ULOG(FATAL, this) << "nghttp2_submit_response() failed"; ULOG(FATAL, this) << "nghttp2_submit_response() failed";
return -1; return -1;

View File

@ -236,15 +236,15 @@ int SpdyDownstreamConnection::push_request_headers()
// 10 means :method, :scheme, :path and possible via and // 10 means :method, :scheme, :path and possible via and
// x-forwarded-for header fields. We rename host header field as // x-forwarded-for header fields. We rename host header field as
// :host. // :host.
auto nv = util::make_unique<const char*[]>(nheader * 2 + 10 + 1); auto nv = std::vector<const char*>();
size_t hdidx = 0; nv.reserve(nheader * 2 + 10 + 1);
std::string via_value; std::string via_value;
std::string xff_value; std::string xff_value;
std::string scheme, path, query; std::string scheme, path, query;
if(downstream_->get_request_method() == "CONNECT") { if(downstream_->get_request_method() == "CONNECT") {
// No :scheme header field for CONNECT method. // No :scheme header field for CONNECT method.
nv[hdidx++] = ":path"; nv.push_back(":path");
nv[hdidx++] = downstream_->get_request_path().c_str(); nv.push_back(downstream_->get_request_path().c_str());
} else { } else {
http_parser_url u; http_parser_url u;
const char *url = downstream_->get_request_path().c_str(); const char *url = downstream_->get_request_path().c_str();
@ -264,27 +264,26 @@ int SpdyDownstreamConnection::push_request_headers()
path += query; path += query;
} }
} }
nv[hdidx++] = ":scheme"; nv.push_back(":scheme");
if(scheme.empty()) { if(scheme.empty()) {
// The default scheme is http. For SPDY upstream, the path must // The default scheme is http. For SPDY upstream, the path must
// be absolute URI, so scheme should be provided. // be absolute URI, so scheme should be provided.
nv[hdidx++] = "http"; nv.push_back("http");
} else { } else {
nv[hdidx++] = scheme.c_str(); nv.push_back(scheme.c_str());
} }
nv[hdidx++] = ":path"; nv.push_back(":path");
if(path.empty()) { if(path.empty()) {
nv[hdidx++] = downstream_->get_request_path().c_str(); nv.push_back(downstream_->get_request_path().c_str());
} else { } else {
nv[hdidx++] = path.c_str(); nv.push_back(path.c_str());
} }
} }
nv[hdidx++] = ":method"; nv.push_back(":method");
nv[hdidx++] = downstream_->get_request_method().c_str(); nv.push_back(downstream_->get_request_method().c_str());
hdidx += http2::copy_norm_headers_to_nv(&nv[hdidx], http2::copy_norm_headers_to_nv(nv, downstream_->get_request_headers());
downstream_->get_request_headers());
auto host = downstream_->get_norm_request_header("host"); auto host = downstream_->get_norm_request_header("host");
if(host == end_headers) { if(host == end_headers) {
@ -293,8 +292,8 @@ int SpdyDownstreamConnection::push_request_headers()
} }
return -1; return -1;
} }
nv[hdidx++] = ":host"; nv.push_back(":host");
nv[hdidx++] = (*host).second.c_str(); nv.push_back((*host).second.c_str());
bool content_length = false; bool content_length = false;
if(downstream_->get_norm_request_header("content-length") != end_headers) { 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"); auto expect = downstream_->get_norm_request_header("expect");
if(expect != end_headers && if(expect != end_headers &&
!util::strifind((*expect).second.c_str(), "100-continue")) { !util::strifind((*expect).second.c_str(), "100-continue")) {
nv[hdidx++] = "expect"; nv.push_back("expect");
nv[hdidx++] = (*expect).second.c_str(); nv.push_back((*expect).second.c_str());
} }
bool chunked_encoding = false; bool chunked_encoding = false;
@ -318,24 +317,24 @@ int SpdyDownstreamConnection::push_request_headers()
auto xff = downstream_->get_norm_request_header("x-forwarded-for"); auto xff = downstream_->get_norm_request_header("x-forwarded-for");
if(get_config()->add_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) { if(xff != end_headers) {
xff_value = (*xff).second; xff_value = (*xff).second;
xff_value += ", "; xff_value += ", ";
} }
xff_value += downstream_->get_upstream()->get_client_handler()-> xff_value += downstream_->get_upstream()->get_client_handler()->
get_ipaddr(); get_ipaddr();
nv[hdidx++] = xff_value.c_str(); nv.push_back(xff_value.c_str());
} else if(xff != end_headers) { } else if(xff != end_headers) {
nv[hdidx++] = "x-forwarded-for"; nv.push_back("x-forwarded-for");
nv[hdidx++] = (*xff).second.c_str(); nv.push_back((*xff).second.c_str());
} }
auto via = downstream_->get_norm_request_header("via"); auto via = downstream_->get_norm_request_header("via");
if(get_config()->no_via) { if(get_config()->no_via) {
if(via != end_headers) { if(via != end_headers) {
nv[hdidx++] = "via"; nv.push_back("via");
nv[hdidx++] = (*via).second.c_str(); nv.push_back((*via).second.c_str());
} }
} else { } else {
if(via != end_headers) { if(via != end_headers) {
@ -344,10 +343,10 @@ int SpdyDownstreamConnection::push_request_headers()
} }
via_value += http::create_via_header_value via_value += http::create_via_header_value
(downstream_->get_request_major(), downstream_->get_request_minor()); (downstream_->get_request_major(), downstream_->get_request_minor());
nv[hdidx++] = "via"; nv.push_back("via");
nv[hdidx++] = via_value.c_str(); nv.push_back(via_value.c_str());
} }
nv[hdidx++] = nullptr; nv.push_back(nullptr);
if(LOG_ENABLED(INFO)) { if(LOG_ENABLED(INFO)) {
std::stringstream ss; std::stringstream ss;
@ -363,9 +362,9 @@ int SpdyDownstreamConnection::push_request_headers()
nghttp2_data_provider data_prd; nghttp2_data_provider data_prd;
data_prd.source.ptr = this; data_prd.source.ptr = this;
data_prd.read_callback = spdy_data_read_callback; 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 { } else {
rv = spdy_->submit_request(this, 0, nv.get(), 0); rv = spdy_->submit_request(this, 0, nv.data(), nullptr);
} }
if(rv != 0) { if(rv != 0) {
DCLOG(FATAL, this) << "nghttp2_submit_request() failed"; DCLOG(FATAL, this) << "nghttp2_submit_request() failed";