diff --git a/src/HttpServer.cc b/src/HttpServer.cc index 59be6c71..a24f222e 100644 --- a/src/HttpServer.cc +++ b/src/HttpServer.cc @@ -455,15 +455,15 @@ int Http2Handler::submit_file_response(const std::string& status, std::string content_length = util::to_str(file_length); std::string last_modified_str; auto nva = std::vector{ - MAKE_NV_LS(":status", status), - MAKE_NV_LS("server", NGHTTPD_SERVER), - MAKE_NV_LS("content-length", content_length), - MAKE_NV_LS_LS("cache-control", "max-age=3600"), - MAKE_NV_LS("date", date_str), + http2::make_nv_ls(":status", status), + http2::make_nv_ls("server", NGHTTPD_SERVER), + http2::make_nv_ls("content-length", content_length), + http2::make_nv_ll("cache-control", "max-age=3600"), + http2::make_nv_ls("date", date_str), }; if(last_modified != 0) { last_modified_str = util::http_date(last_modified); - nva.push_back(MAKE_NV_LS("last-modified", last_modified_str)); + nva.push_back(http2::make_nv_ls("last-modified", last_modified_str)); } return nghttp2_submit_response(session_, stream_id, nva.data(), nva.size(), data_prd); @@ -477,9 +477,9 @@ int Http2Handler::submit_response { std::string date_str = util::http_date(time(0)); auto nva = std::vector{ - MAKE_NV_LS(":status", status), - MAKE_NV_LS("server", NGHTTPD_SERVER), - MAKE_NV_LS("date", date_str) + http2::make_nv_ls(":status", status), + http2::make_nv_ls("server", NGHTTPD_SERVER), + http2::make_nv_ls("date", date_str) }; for(size_t i = 0; i < headers.size(); ++i) { nva.push_back(http2::make_nv(headers[i].first, headers[i].second)); @@ -494,8 +494,8 @@ int Http2Handler::submit_response(const std::string& status, nghttp2_data_provider *data_prd) { auto nva = std::vector{ - MAKE_NV_LS(":status", status), - MAKE_NV_LS("server", NGHTTPD_SERVER) + http2::make_nv_ls(":status", status), + http2::make_nv_ls("server", NGHTTPD_SERVER) }; return nghttp2_submit_response(session_, stream_id, nva.data(), nva.size(), data_prd); diff --git a/src/http2.h b/src/http2.h index e293427a..e5325f4a 100644 --- a/src/http2.h +++ b/src/http2.h @@ -28,6 +28,7 @@ #include "nghttp2_config.h" #include +#include #include #include @@ -39,22 +40,6 @@ namespace nghttp2 { namespace http2 { -// Create nghttp2_nv from string literal |NAME| and std::string -// |VALUE|. -#define MAKE_NV_LS(NAME, VALUE) \ - { (uint8_t*)NAME, (uint8_t*)VALUE.c_str(), \ - (uint16_t)(sizeof(NAME) - 1), (uint16_t)VALUE.size() } - -// Create nghttp2_nv from string literal |NAME| and |VALUE|. -#define MAKE_NV_LS_LS(NAME, VALUE) \ - { (uint8_t*)NAME, (uint8_t*)VALUE, \ - (uint16_t)(sizeof(NAME) - 1), (uint16_t)(sizeof(VALUE) - 1) } - -// Create nghttp2_nv from string literal |NAME| and c-string |VALUE|. -#define MAKE_NV_LS_CS(NAME, VALUE) \ - { (uint8_t*)NAME, (uint8_t*)VALUE, \ - (uint16_t)(sizeof(NAME) - 1), (uint16_t)(strlen(VALUE)) } - std::string get_status_string(unsigned int status_code); void capitalize(std::string& s, size_t offset); @@ -130,6 +115,31 @@ concat_norm_headers // value.c_str(). nghttp2_nv make_nv(const std::string& name, const std::string& value); +// Create nghttp2_nv from string literal |name| and |value|. +template +nghttp2_nv make_nv_ll(const char(&name)[N], const char(&value)[M]) +{ + return { (uint8_t*)name, (uint8_t*)value, + (uint16_t)(N - 1), (uint16_t)(M - 1) }; +} + +// Create nghttp2_nv from string literal |name| and c-string |value|. +template +nghttp2_nv make_nv_lc(const char(&name)[N], const char *value) +{ + return { (uint8_t*)name, (uint8_t*)value, + (uint16_t)(N - 1), (uint16_t)strlen(value) }; +} + +// Create nghttp2_nv from string literal |name| and std::string +// |value|. +template +nghttp2_nv make_nv_ls(const char(&name)[N], const std::string& value) +{ + return { (uint8_t*)name, (uint8_t*)value.c_str(), + (uint16_t)(N - 1), (uint16_t)value.size() }; +} + // 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. diff --git a/src/shrpx_http2_downstream_connection.cc b/src/shrpx_http2_downstream_connection.cc index 8dae7175..04becdf2 100644 --- a/src/shrpx_http2_downstream_connection.cc +++ b/src/shrpx_http2_downstream_connection.cc @@ -250,21 +250,23 @@ int Http2DownstreamConnection::push_request_headers() if(downstream_->get_request_method() == "CONNECT") { // The upstream may be HTTP/2 or HTTP/1 if(!downstream_->get_request_http2_authority().empty()) { - nva.push_back(MAKE_NV_LS(":authority", - downstream_->get_request_http2_authority())); + nva.push_back(http2::make_nv_ls + (":authority", + downstream_->get_request_http2_authority())); } else { - nva.push_back(MAKE_NV_LS(":authority", - downstream_->get_request_path())); + nva.push_back(http2::make_nv_ls(":authority", + downstream_->get_request_path())); } } else if(!downstream_->get_request_http2_scheme().empty()) { // Here the upstream is HTTP/2 - nva.push_back(MAKE_NV_LS(":scheme", - downstream_->get_request_http2_scheme())); - nva.push_back(MAKE_NV_LS(":path", - downstream_->get_request_path())); + nva.push_back(http2::make_nv_ls(":scheme", + downstream_->get_request_http2_scheme())); + nva.push_back(http2::make_nv_ls(":path", + downstream_->get_request_path())); if(!downstream_->get_request_http2_authority().empty()) { - nva.push_back(MAKE_NV_LS(":authority", - downstream_->get_request_http2_authority())); + nva.push_back(http2::make_nv_ls + (":authority", + downstream_->get_request_http2_authority())); } else if(downstream_->get_norm_request_header("host") == end_headers) { if(LOG_ENABLED(INFO)) { DCLOG(INFO, this) << "host header field missing"; @@ -295,14 +297,15 @@ int Http2DownstreamConnection::push_request_headers() if(scheme.empty()) { // The default scheme is http. For HTTP2 upstream, the path must // be absolute URI, so scheme should be provided. - nva.push_back(MAKE_NV_LS_LS(":scheme", "http")); + nva.push_back(http2::make_nv_ll(":scheme", "http")); } else { - nva.push_back(MAKE_NV_LS(":scheme", scheme)); + nva.push_back(http2::make_nv_ls(":scheme", scheme)); } if(path.empty()) { - nva.push_back(MAKE_NV_LS(":path", downstream_->get_request_path())); + nva.push_back(http2::make_nv_ls(":path", + downstream_->get_request_path())); } else { - nva.push_back(MAKE_NV_LS(":path", path)); + nva.push_back(http2::make_nv_ls(":path", path)); } if(!authority.empty()) { // TODO properly check IPv6 numeric address @@ -314,7 +317,7 @@ int Http2DownstreamConnection::push_request_headers() authority += ":"; authority += util::utos(u.port); } - nva.push_back(MAKE_NV_LS(":authority", authority)); + nva.push_back(http2::make_nv_ls(":authority", authority)); } else if(downstream_->get_norm_request_header("host") == end_headers) { if(LOG_ENABLED(INFO)) { DCLOG(INFO, this) << "host header field missing"; @@ -323,7 +326,8 @@ int Http2DownstreamConnection::push_request_headers() } } - nva.push_back(MAKE_NV_LS(":method", downstream_->get_request_method())); + nva.push_back(http2::make_nv_ls(":method", + downstream_->get_request_method())); http2::copy_norm_headers_to_nva(nva, downstream_->get_request_headers()); @@ -348,15 +352,15 @@ int Http2DownstreamConnection::push_request_headers() } xff_value += downstream_->get_upstream()->get_client_handler()-> get_ipaddr(); - nva.push_back(MAKE_NV_LS("x-forwarded-for", xff_value)); + nva.push_back(http2::make_nv_ls("x-forwarded-for", xff_value)); } else if(xff != end_headers) { - nva.push_back(MAKE_NV_LS("x-forwarded-for", (*xff).second)); + nva.push_back(http2::make_nv_ls("x-forwarded-for", (*xff).second)); } auto via = downstream_->get_norm_request_header("via"); if(get_config()->no_via) { if(via != end_headers) { - nva.push_back(MAKE_NV_LS("via", (*via).second)); + nva.push_back(http2::make_nv_ls("via", (*via).second)); } } else { if(via != end_headers) { @@ -365,7 +369,7 @@ int Http2DownstreamConnection::push_request_headers() } via_value += http::create_via_header_value (downstream_->get_request_major(), downstream_->get_request_minor()); - nva.push_back(MAKE_NV_LS("via", via_value)); + nva.push_back(http2::make_nv_ls("via", via_value)); } if(LOG_ENABLED(INFO)) { diff --git a/src/shrpx_http2_upstream.cc b/src/shrpx_http2_upstream.cc index 50e23a7d..6c9d8105 100644 --- a/src/shrpx_http2_upstream.cc +++ b/src/shrpx_http2_upstream.cc @@ -879,10 +879,10 @@ int Http2Upstream::error_reply(Downstream *downstream, auto content_length = util::utos(html.size()); auto status_code_str = util::utos(status_code); auto nva = std::vector{ - MAKE_NV_LS(":status", status_code_str), - MAKE_NV_LS_LS("content-type", "text/html; charset=UTF-8"), - MAKE_NV_LS_CS("server", get_config()->server_name), - MAKE_NV_LS("content-length", content_length) + http2::make_nv_ls(":status", status_code_str), + http2::make_nv_ll("content-type", "text/html; charset=UTF-8"), + http2::make_nv_lc("server", get_config()->server_name), + http2::make_nv_ls("content-length", content_length) }; rv = nghttp2_submit_response(session_, downstream->get_stream_id(), @@ -950,13 +950,13 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) nva.reserve(nheader + 2); std::string via_value; auto response_status = util::utos(downstream->get_response_http_status()); - nva.push_back(MAKE_NV_LS(":status", response_status)); + nva.push_back(http2::make_nv_ls(":status", response_status)); http2::copy_norm_headers_to_nva(nva, downstream->get_response_headers()); auto via = downstream->get_norm_response_header("via"); if(get_config()->no_via) { if(via != end_headers) { - nva.push_back(MAKE_NV_LS("via", (*via).second)); + nva.push_back(http2::make_nv_ls("via", (*via).second)); } } else { if(via != end_headers) { @@ -965,7 +965,7 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) } via_value += http::create_via_header_value (downstream->get_response_major(), downstream->get_response_minor()); - nva.push_back(MAKE_NV_LS("via", via_value)); + nva.push_back(http2::make_nv_ls("via", via_value)); } if(LOG_ENABLED(INFO)) { std::stringstream ss;