From 3ce1c1d39ff66383d797d61042d6ac67d42169ad Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Mon, 7 Sep 2015 23:11:23 +0900 Subject: [PATCH] nghttpx: Add date header field to error_reply and send_reply --- genheaderfunc.py | 1 + src/http2.cc | 5 +++++ src/http2.h | 1 + src/shrpx_http2_upstream.cc | 6 +++++- src/shrpx_https_upstream.cc | 5 +++++ src/shrpx_log_config.cc | 1 + src/shrpx_log_config.h | 1 + src/shrpx_mruby_module_response.cc | 8 ++++++++ src/shrpx_spdy_upstream.cc | 4 ++++ src/util.h | 7 +++++++ 10 files changed, 38 insertions(+), 1 deletion(-) diff --git a/genheaderfunc.py b/genheaderfunc.py index ce2f7ff0..a277fb4f 100755 --- a/genheaderfunc.py +++ b/genheaderfunc.py @@ -28,6 +28,7 @@ HEADERS = [ "accept-language", "cache-control", "user-agent", + "date", # disallowed h1 headers 'connection', 'keep-alive', diff --git a/src/http2.cc b/src/http2.cc index 8059ac04..8fc54cb9 100644 --- a/src/http2.cc +++ b/src/http2.cc @@ -414,6 +414,11 @@ int lookup_token(const uint8_t *name, size_t namelen) { break; case 4: switch (name[3]) { + case 'e': + if (util::streq_l("dat", name, 3)) { + return HD_DATE; + } + break; case 'k': if (util::streq_l("lin", name, 3)) { return HD_LINK; diff --git a/src/http2.h b/src/http2.h index 8fd32f85..eeaa506c 100644 --- a/src/http2.h +++ b/src/http2.h @@ -207,6 +207,7 @@ enum { HD_CONNECTION, HD_CONTENT_LENGTH, HD_COOKIE, + HD_DATE, HD_EXPECT, HD_HOST, HD_HTTP2_SETTINGS, diff --git a/src/shrpx_http2_upstream.cc b/src/shrpx_http2_upstream.cc index 8a3160f5..e739d8a4 100644 --- a/src/shrpx_http2_upstream.cc +++ b/src/shrpx_http2_upstream.cc @@ -1238,13 +1238,17 @@ int Http2Upstream::error_reply(Downstream *downstream, data_prd.source.ptr = downstream; data_prd.read_callback = downstream_data_read_callback; + auto lgconf = log_config(); + lgconf->update_tstamp(std::chrono::system_clock::now()); + auto content_length = util::utos(html.size()); auto status_code_str = util::utos(status_code); auto nva = make_array(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)); + http2::make_nv_ls("content-length", content_length), + http2::make_nv_ls("date", lgconf->time_http_str)); rv = nghttp2_submit_response(session_, downstream->get_stream_id(), nva.data(), nva.size(), &data_prd); diff --git a/src/shrpx_https_upstream.cc b/src/shrpx_https_upstream.cc index ca8a5778..6f48efe6 100644 --- a/src/shrpx_https_upstream.cc +++ b/src/shrpx_https_upstream.cc @@ -857,6 +857,11 @@ void HttpsUpstream::error_reply(unsigned int status_code) { output->append("\r\nContent-Length: "); auto cl = util::utos(html.size()); output->append(cl.c_str(), cl.size()); + output->append("\r\nDate: "); + auto lgconf = log_config(); + lgconf->update_tstamp(std::chrono::system_clock::now()); + auto &date = lgconf->time_http_str; + output->append(date.c_str(), date.size()); output->append("\r\nContent-Type: text/html; " "charset=UTF-8\r\nConnection: close\r\n\r\n"); output->append(html.c_str(), html.size()); diff --git a/src/shrpx_log_config.cc b/src/shrpx_log_config.cc index 6c21bc0c..3d77673d 100644 --- a/src/shrpx_log_config.cc +++ b/src/shrpx_log_config.cc @@ -64,6 +64,7 @@ LogConfig::update_tstamp(const std::chrono::system_clock::time_point &now) { time_local_str = util::format_common_log(now); time_iso8601_str = util::format_iso8601(now); + time_http_str = util::format_http_date(now); } } // namespace shrpx diff --git a/src/shrpx_log_config.h b/src/shrpx_log_config.h index 46b6357e..b87adb4b 100644 --- a/src/shrpx_log_config.h +++ b/src/shrpx_log_config.h @@ -35,6 +35,7 @@ struct LogConfig { std::chrono::system_clock::time_point time_str_updated_; std::string time_local_str; std::string time_iso8601_str; + std::string time_http_str; int accesslog_fd; int errorlog_fd; // true if errorlog_fd is referring to a terminal. diff --git a/src/shrpx_mruby_module_response.cc b/src/shrpx_mruby_module_response.cc index 00648231..63cc422e 100644 --- a/src/shrpx_mruby_module_response.cc +++ b/src/shrpx_mruby_module_response.cc @@ -210,6 +210,14 @@ mrb_value response_return(mrb_state *mrb, mrb_value self) { } downstream->set_response_content_length(bodylen); + auto date = downstream->get_response_header(http2::HD_DATE); + if (!date) { + auto lgconf = log_config(); + lgconf->update_tstamp(std::chrono::system_clock::now()); + downstream->add_response_header("date", lgconf->time_http_str, + http2::HD_DATE); + } + auto upstream = downstream->get_upstream(); rv = upstream->send_reply(downstream, body, bodylen); diff --git a/src/shrpx_spdy_upstream.cc b/src/shrpx_spdy_upstream.cc index d3dea3f9..bc60915e 100644 --- a/src/shrpx_spdy_upstream.cc +++ b/src/shrpx_spdy_upstream.cc @@ -881,6 +881,9 @@ int SpdyUpstream::error_reply(Downstream *downstream, data_prd.source.ptr = downstream; data_prd.read_callback = spdy_data_read_callback; + auto lgconf = log_config(); + lgconf->update_tstamp(std::chrono::system_clock::now()); + std::string content_length = util::utos(html.size()); std::string status_string = http2::get_status_string(status_code); const char *nv[] = {":status", status_string.c_str(), @@ -888,6 +891,7 @@ int SpdyUpstream::error_reply(Downstream *downstream, "content-type", "text/html; charset=UTF-8", "server", get_config()->server_name, "content-length", content_length.c_str(), + "date", lgconf->time_http_str.c_str(), nullptr}; rv = spdylay_submit_response(session_, downstream->get_stream_id(), nv, diff --git a/src/util.h b/src/util.h index 6463d19a..6ca9f735 100644 --- a/src/util.h +++ b/src/util.h @@ -588,6 +588,13 @@ template std::string format_iso8601(const T &tp) { return iso8601_date(t.count()); } +// Returns given time |tp| in HTTP date format. +template std::string format_http_date(const T &tp) { + auto t = + std::chrono::duration_cast(tp.time_since_epoch()); + return http_date(t.count()); +} + // Return the system precision of the template parameter |Clock| as // a nanosecond value of type |Rep| template Rep clock_precision() {