diff --git a/AUTHORS b/AUTHORS index 7a0b243c..a55dba53 100644 --- a/AUTHORS +++ b/AUTHORS @@ -71,6 +71,7 @@ Tomasz Buchert Vernon Tang Viacheslav Biriukov Viktor Szépe +Wenfeng Liu Xiaoguang Sun Zhuoyun Wei acesso diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c11989e..b2f598e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ cmake_minimum_required(VERSION 3.0) # XXX using 1.8.90 instead of 1.9.0-DEV -project(nghttp2 VERSION 1.13.90) +project(nghttp2 VERSION 1.14.90) # See versioning rule: # http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html diff --git a/author.py b/author.py new file mode 100755 index 00000000..760da009 --- /dev/null +++ b/author.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python + +# script to extract commit author's name from standard input. The +# input should be :, one per line. +# This script expects the input is created by git-log command: +# +# git log --format=%aN:%aE +# +# This script removes duplicates based on email address, breaking a +# tie with longer author name. Among the all author names extract the +# previous step, we remove duplicate by case-insensitive match. +# +# So we can do this in one line: +# +# git log --format=%aN:%aE | sort | uniq | ./author.py > authors + +import sys + +edict = {} + +for line in sys.stdin: + author, email = line.strip().split(':', 1) + if email in edict: + an = edict[email] + if len(an) < len(author) or an > author: + sys.stderr.write( + 'eliminated {} in favor of {}\n'.format(an, author)) + edict[email] = author + else: + sys.stderr.write( + 'eliminated {} in favor of {}\n'.format(author, an)) + else: + edict[email] = author + +names = list(sorted(edict.values())) + +ndict = {} + +for name in names: + lowname = name.lower() + if lowname in ndict: + an = ndict[lowname] + if an > name: + sys.stderr.write('eliminated {} in favor of {}\n'.format(an, name)) + ndict[lowname] = name + else: + sys.stderr.write('eliminated {} in favor of {}\n'.format(name, an)) + else: + ndict[lowname] = name + +for name in sorted(ndict.values()): + print name diff --git a/configure.ac b/configure.ac index ab9bd2ed..d06f11b0 100644 --- a/configure.ac +++ b/configure.ac @@ -25,7 +25,7 @@ dnl Do not change user variables! dnl http://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html AC_PREREQ(2.61) -AC_INIT([nghttp2], [1.14.0-DEV], [t-tujikawa@users.sourceforge.net]) +AC_INIT([nghttp2], [1.15.0-DEV], [t-tujikawa@users.sourceforge.net]) AC_CONFIG_AUX_DIR([.]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([config.h]) @@ -44,9 +44,9 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) dnl See versioning rule: dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html -AC_SUBST(LT_CURRENT, 23) +AC_SUBST(LT_CURRENT, 24) AC_SUBST(LT_REVISION, 0) -AC_SUBST(LT_AGE, 9) +AC_SUBST(LT_AGE, 10) major=`echo $PACKAGE_VERSION |cut -d. -f1 | sed -e "s/[^0-9]//g"` minor=`echo $PACKAGE_VERSION |cut -d. -f2 | sed -e "s/[^0-9]//g"` diff --git a/doc/Makefile.am b/doc/Makefile.am index fc3087b0..534484be 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -37,6 +37,7 @@ APIDOCS= \ nghttp2_hd_deflate_get_num_table_entries.rst \ nghttp2_hd_deflate_get_table_entry.rst \ nghttp2_hd_deflate_hd.rst \ + nghttp2_hd_deflate_hd_vec.rst \ nghttp2_hd_deflate_new.rst \ nghttp2_hd_deflate_new2.rst \ nghttp2_hd_inflate_change_table_size.rst \ diff --git a/doc/h2load.1 b/doc/h2load.1 index dd63c682..634385c9 100644 --- a/doc/h2load.1 +++ b/doc/h2load.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "H2LOAD" "1" "Jul 31, 2016" "1.14.0-DEV" "nghttp2" +.TH "H2LOAD" "1" "Aug 25, 2016" "1.14.0" "nghttp2" .SH NAME h2load \- HTTP/2 benchmarking tool . diff --git a/doc/nghttp.1 b/doc/nghttp.1 index 5d3f3eaa..6a711cc6 100644 --- a/doc/nghttp.1 +++ b/doc/nghttp.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "NGHTTP" "1" "Jul 31, 2016" "1.14.0-DEV" "nghttp2" +.TH "NGHTTP" "1" "Aug 25, 2016" "1.14.0" "nghttp2" .SH NAME nghttp \- HTTP/2 client . diff --git a/doc/nghttpd.1 b/doc/nghttpd.1 index 43540382..9eb17d73 100644 --- a/doc/nghttpd.1 +++ b/doc/nghttpd.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "NGHTTPD" "1" "Jul 31, 2016" "1.14.0-DEV" "nghttp2" +.TH "NGHTTPD" "1" "Aug 25, 2016" "1.14.0" "nghttp2" .SH NAME nghttpd \- HTTP/2 server . diff --git a/doc/nghttpx.1 b/doc/nghttpx.1 index c4548174..a27453ee 100644 --- a/doc/nghttpx.1 +++ b/doc/nghttpx.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "NGHTTPX" "1" "Jul 31, 2016" "1.14.0-DEV" "nghttp2" +.TH "NGHTTPX" "1" "Aug 25, 2016" "1.14.0" "nghttp2" .SH NAME nghttpx \- HTTP/2 proxy . @@ -938,6 +938,12 @@ $ssl_session_id: session ID for SSL/TLS connection. .IP \(bu 2 $ssl_session_reused: "r" if SSL/TLS session was reused. Otherwise, "." +.IP \(bu 2 +$backend_host: backend host used to fulfill the +request. "\-" if backend host is not available. +.IP \(bu 2 +$backend_port: backend port used to fulfill the +request. "\-" if backend host is not available. .UNINDENT .sp The variable can be enclosed by "{" and "}" for diff --git a/doc/nghttpx.1.rst b/doc/nghttpx.1.rst index 20236781..a8b292e7 100644 --- a/doc/nghttpx.1.rst +++ b/doc/nghttpx.1.rst @@ -847,6 +847,10 @@ Logging * $ssl_session_id: session ID for SSL/TLS connection. * $ssl_session_reused: "r" if SSL/TLS session was reused. Otherwise, "." + * $backend_host: backend host used to fulfill the + request. "-" if backend host is not available. + * $backend_port: backend port used to fulfill the + request. "-" if backend host is not available. The variable can be enclosed by "{" and "}" for disambiguation (e.g., ${remote_addr}). diff --git a/gennghttpxfun.py b/gennghttpxfun.py index ca40cabb..f76abcde 100755 --- a/gennghttpxfun.py +++ b/gennghttpxfun.py @@ -134,6 +134,7 @@ OPTIONS = [ "backend-http2-settings-timeout", "api-max-request-body", "backend-max-backoff", + "server-name", ] LOGVARS = [ diff --git a/lib/nghttp2_hd.c b/lib/nghttp2_hd.c index f8dba5c0..275c966c 100644 --- a/lib/nghttp2_hd.c +++ b/lib/nghttp2_hd.c @@ -768,14 +768,12 @@ static size_t entry_room(size_t namelen, size_t valuelen) { return NGHTTP2_HD_ENTRY_OVERHEAD + namelen + valuelen; } -static int emit_header(nghttp2_hd_nv *nv_out, nghttp2_hd_nv *nv) { +static void emit_header(nghttp2_hd_nv *nv_out, nghttp2_hd_nv *nv) { DEBUGF(fprintf(stderr, "inflatehd: header emission: %s: %s\n", nv->name->base, nv->value->base)); /* ent->ref may be 0. This happens if the encoder emits literal block larger than header table capacity with indexing. */ *nv_out = *nv; - - return 0; } static size_t count_encoded_length(size_t n, size_t prefix) { diff --git a/src/asio_client_session_impl.cc b/src/asio_client_session_impl.cc index fafb26b1..f5a14be9 100644 --- a/src/asio_client_session_impl.cc +++ b/src/asio_client_session_impl.cc @@ -503,7 +503,7 @@ const request *session_impl::submit(boost::system::error_code &ec, } auto nva = std::vector(); - nva.reserve(3 + h.size()); + nva.reserve(4 + h.size()); nva.push_back(http2::make_nv_ls(":method", method)); nva.push_back(http2::make_nv_ls(":scheme", uref.scheme)); nva.push_back(http2::make_nv_ls(":path", path)); diff --git a/src/memchunk.h b/src/memchunk.h index 4cfd3b12..d1753ceb 100644 --- a/src/memchunk.h +++ b/src/memchunk.h @@ -178,6 +178,9 @@ template struct Memchunks { } size_t append(const std::string &s) { return append(s.c_str(), s.size()); } size_t append(const StringRef &s) { return append(s.c_str(), s.size()); } + size_t append(const ImmutableString &s) { + return append(s.c_str(), s.size()); + } size_t remove(void *dest, size_t count) { if (!tail || count == 0) { return 0; diff --git a/src/shrpx.cc b/src/shrpx.cc index ece98e36..98c0f12b 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -574,7 +574,7 @@ int create_unix_domain_server_socket(UpstreamAddr &faddr, << (faddr.tls ? ", tls" : ""); (*found).used = true; faddr.fd = (*found).fd; - faddr.hostport = "localhost"; + faddr.hostport = ImmutableString::from_lit("localhost"); return 0; } @@ -639,7 +639,7 @@ int create_unix_domain_server_socket(UpstreamAddr &faddr, << (faddr.tls ? ", tls" : ""); faddr.fd = fd; - faddr.hostport = "localhost"; + faddr.hostport = ImmutableString::from_lit("localhost"); return 0; } @@ -791,7 +791,8 @@ int create_tcp_server_socket(UpstreamAddr &faddr, } faddr.fd = fd; - faddr.hostport = util::make_http_hostport(StringRef{host.data()}, faddr.port); + faddr.hostport = ImmutableString{ + util::make_http_hostport(StringRef{host.data()}, faddr.port)}; LOG(NOTICE) << "Listening on " << faddr.hostport << (faddr.tls ? ", tls" : ""); @@ -855,7 +856,7 @@ get_inherited_addr_from_config(const Config *config) { continue; } - iaddr.host = host.data(); + iaddr.host = ImmutableString{host.data()}; } return iaddrs; @@ -947,7 +948,7 @@ std::vector get_inherited_addr_from_env() { } InheritedAddr addr{}; - addr.host = path; + addr.host = ImmutableString{path}; addr.host_unix = true; addr.fd = static_cast(fd); iaddrs.push_back(std::move(addr)); @@ -1001,7 +1002,7 @@ std::vector get_inherited_addr_from_env() { } InheritedAddr addr{}; - addr.host = host.data(); + addr.host = ImmutableString{host.data()}; addr.port = static_cast(port); addr.fd = static_cast(fd); iaddrs.push_back(std::move(addr)); @@ -1272,10 +1273,8 @@ constexpr auto DEFAULT_ACCESSLOG_FORMAT = StringRef::from_lit( namespace { void fill_default_config(Config *config) { - *config = {}; - config->num_worker = 1; - config->conf_path = "/etc/nghttpx/nghttpx.conf"; + config->conf_path = ImmutableString::from_lit("/etc/nghttpx/nghttpx.conf"); config->pid = getpid(); if (ev_supported_backends() & ~ev_recommended_backends() & EVBACKEND_KQUEUE) { @@ -1306,7 +1305,8 @@ void fill_default_config(Config *config) { auto &ocspconf = tlsconf.ocsp; // ocsp update interval = 14400 secs = 4 hours, borrowed from h2o ocspconf.update_interval = 4_h; - ocspconf.fetch_ocsp_response_file = PKGDATADIR "/fetch-ocsp-response"; + ocspconf.fetch_ocsp_response_file = + ImmutableString::from_lit(PKGDATADIR "/fetch-ocsp-response"); } { @@ -1319,7 +1319,7 @@ void fill_default_config(Config *config) { auto &httpconf = config->http; httpconf.server_name = - StringRef::from_lit("nghttpx nghttp2/" NGHTTP2_VERSION); + ImmutableString::from_lit("nghttpx nghttp2/" NGHTTP2_VERSION); httpconf.no_host_rewrite = true; httpconf.request_header_field_buffer = 64_k; httpconf.max_request_header_fields = 100; @@ -1377,7 +1377,7 @@ void fill_default_config(Config *config) { accessconf.format = parse_log_format(DEFAULT_ACCESSLOG_FORMAT); auto &errorconf = loggingconf.error; - errorconf.file = "/dev/stderr"; + errorconf.file = ImmutableString::from_lit("/dev/stderr"); } loggingconf.syslog_facility = LOG_DAEMON; @@ -2205,6 +2205,9 @@ HTTP: 599. If "*" is used instead of , it matches all HTTP status code. If error status code comes from backend server, the custom error pages are not used. + --server-name= + Change server response header field value to . + Default: )" << get_config()->http.server_name << R"( API: --api-max-request-body= @@ -2396,7 +2399,7 @@ int process_options(Config *config, if (listenerconf.addrs.empty()) { UpstreamAddr addr{}; - addr.host = "*"; + addr.host = ImmutableString::from_lit("*"); addr.port = 3000; addr.tls = true; addr.family = AF_INET; @@ -2833,6 +2836,7 @@ int main(int argc, char **argv) { &flag, 125}, {SHRPX_OPT_API_MAX_REQUEST_BODY.c_str(), required_argument, &flag, 126}, {SHRPX_OPT_BACKEND_MAX_BACKOFF.c_str(), required_argument, &flag, 127}, + {SHRPX_OPT_SERVER_NAME.c_str(), required_argument, &flag, 128}, {nullptr, 0, nullptr, 0}}; int option_index = 0; @@ -2935,7 +2939,7 @@ int main(int argc, char **argv) { break; case 12: // --conf - mod_config()->conf_path = optarg; + mod_config()->conf_path = ImmutableString{optarg}; break; case 14: // --syslog-facility @@ -3430,6 +3434,10 @@ int main(int argc, char **argv) { // --backend-max-backoff cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_MAX_BACKOFF, StringRef{optarg}); break; + case 128: + // --server-name + cmdcfgs.emplace_back(SHRPX_OPT_SERVER_NAME, StringRef{optarg}); + break; default: break; } diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index 2eb208a3..d84e7f0f 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -1127,6 +1127,11 @@ int option_lookup_token(const char *name, size_t namelen) { break; case 11: switch (name[10]) { + case 'e': + if (util::strieq_l("server-nam", name, 10)) { + return SHRPX_OPTID_SERVER_NAME; + } + break; case 's': if (util::strieq_l("backend-tl", name, 10)) { return SHRPX_OPTID_BACKEND_TLS; @@ -2027,7 +2032,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, << strerror(errno); return -1; } - config->user = pwd->pw_name; + config->user = ImmutableString{pwd->pw_name}; config->uid = pwd->pw_uid; config->gid = pwd->pw_gid; @@ -2044,7 +2049,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, LOG(ERROR) << opt << ": Couldn't read key file's passwd from " << optarg; return -1; } - config->tls.private_key_passwd = passwd; + config->tls.private_key_passwd = ImmutableString{passwd}; return 0; } @@ -2479,14 +2484,14 @@ int parse_config(Config *config, int optid, const StringRef &opt, switch (optid) { case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED: { auto &memcachedconf = config->tls.session_cache.memcached; - memcachedconf.host = host; + memcachedconf.host = ImmutableString{host}; memcachedconf.port = port; memcachedconf.tls = params.tls; break; } case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED: { auto &memcachedconf = config->tls.ticket.memcached; - memcachedconf.host = host; + memcachedconf.host = ImmutableString{host}; memcachedconf.port = port; memcachedconf.tls = params.tls; break; @@ -2673,6 +2678,11 @@ int parse_config(Config *config, int optid, const StringRef &opt, case SHRPX_OPTID_BACKEND_MAX_BACKOFF: return parse_duration(&config->conn.downstream->timeout.max_backoff, opt, optarg); + case SHRPX_OPTID_SERVER_NAME: + config->http.server_name = + ImmutableString{std::begin(optarg), std::end(optarg)}; + + return 0; case SHRPX_OPTID_CONF: LOG(WARN) << "conf: ignored"; @@ -2948,7 +2958,7 @@ int configure_downstream_group(Config *config, bool http2_proxy, auto &sni = tlsconf.backend_sni_name; for (auto &addr_group : addr_groups) { for (auto &addr : addr_group.addrs) { - addr.sni = sni; + addr.sni = ImmutableString{sni}; } } } @@ -2995,7 +3005,7 @@ int configure_downstream_group(Config *config, bool http2_proxy, // for AF_UNIX socket, we use "localhost" as host for backend // hostport. This is used as Host header field to backend and // not going to be passed to any syscalls. - addr.hostport = "localhost"; + addr.hostport = ImmutableString::from_lit("localhost"); auto path = addr.host.c_str(); auto pathlen = addr.host.size(); diff --git a/src/shrpx_config.h b/src/shrpx_config.h index d0645ff3..0a1b86bb 100644 --- a/src/shrpx_config.h +++ b/src/shrpx_config.h @@ -284,6 +284,7 @@ constexpr auto SHRPX_OPT_API_MAX_REQUEST_BODY = StringRef::from_lit("api-max-request-body"); constexpr auto SHRPX_OPT_BACKEND_MAX_BACKOFF = StringRef::from_lit("backend-max-backoff"); +constexpr auto SHRPX_OPT_SERVER_NAME = StringRef::from_lit("server-name"); constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8; @@ -552,7 +553,7 @@ struct HttpConfig { std::vector error_pages; Headers add_request_headers; Headers add_response_headers; - StringRef server_name; + ImmutableString server_name; size_t request_header_field_buffer; size_t max_request_header_fields; size_t response_header_field_buffer; @@ -706,8 +707,14 @@ struct APIConfig { }; struct Config { + Config() = default; ~Config(); + Config(Config &&) = delete; + Config(const Config &&) = delete; + Config &operator=(Config &&) = delete; + Config &operator=(const Config &&) = delete; + HttpProxy downstream_http_proxy; HttpConfig http; Http2Config http2; @@ -837,6 +844,7 @@ enum { SHRPX_OPTID_REQUEST_HEADER_FIELD_BUFFER, SHRPX_OPTID_RESPONSE_HEADER_FIELD_BUFFER, SHRPX_OPTID_RLIMIT_NOFILE, + SHRPX_OPTID_SERVER_NAME, SHRPX_OPTID_STREAM_READ_TIMEOUT, SHRPX_OPTID_STREAM_WRITE_TIMEOUT, SHRPX_OPTID_STRIP_INCOMING_FORWARDED, diff --git a/src/shrpx_http.cc b/src/shrpx_http.cc index c2939c7e..e54040bf 100644 --- a/src/shrpx_http.cc +++ b/src/shrpx_http.cc @@ -51,7 +51,7 @@ StringRef create_error_html(BlockAllocator &balloc, unsigned int http_status) { return concat_string_ref( balloc, StringRef::from_lit(R"()"), status_string, StringRef::from_lit("

"), status_string, - StringRef::from_lit("