nghttpx: Specify altsvc info in one option and allow multiple occurrences
This commit is contained in:
parent
5b3deec186
commit
f9f6cdc93d
49
src/shrpx.cc
49
src/shrpx.cc
|
@ -444,14 +444,6 @@ void fill_default_config()
|
||||||
mod_config()->upstream_frame_debug = false;
|
mod_config()->upstream_frame_debug = false;
|
||||||
mod_config()->padding = 0;
|
mod_config()->padding = 0;
|
||||||
|
|
||||||
mod_config()->altsvc_port = 0;
|
|
||||||
mod_config()->altsvc_protocol_id = nullptr;
|
|
||||||
mod_config()->altsvc_protocol_id_len = 0;
|
|
||||||
mod_config()->altsvc_host = nullptr;
|
|
||||||
mod_config()->altsvc_host_len = 0;
|
|
||||||
mod_config()->altsvc_origin = nullptr;
|
|
||||||
mod_config()->altsvc_origin_len = 0;
|
|
||||||
|
|
||||||
nghttp2_option_new(&mod_config()->http2_option);
|
nghttp2_option_new(&mod_config()->http2_option);
|
||||||
|
|
||||||
nghttp2_option_set_no_auto_stream_window_update
|
nghttp2_option_set_no_auto_stream_window_update
|
||||||
|
@ -764,19 +756,13 @@ Misc:
|
||||||
downstream request.
|
downstream request.
|
||||||
--no-via Don't append to Via header field. If Via header
|
--no-via Don't append to Via header field. If Via header
|
||||||
field is received, it is left unaltered.
|
field is received, it is left unaltered.
|
||||||
--altsvc-port=<PORT>
|
--altsvc=<PROTOID,PORT[,HOST,[ORIGIN]]>
|
||||||
Port number of alternative service advertised in
|
Specify protocol ID, port, host and origin of
|
||||||
alt-svc header field or HTTP/2 ALTSVC frame.
|
alternative service. <HOST> and <ORIGIN> are
|
||||||
--altsvc-protocol-id=<PROTOID>
|
optional. They are advertised in alt-svc header
|
||||||
ALPN protocol identifier of alternative service
|
field or HTTP/2 ALTSVC frame. This option can be
|
||||||
advertised in alt-svc header field or HTTP/2
|
used multiple times to specify multiple
|
||||||
ALTSVC frame.
|
alternative services. Example: --altsvc=h2,443
|
||||||
--altsvc-host=<HOST>
|
|
||||||
Host name that alternative service is available
|
|
||||||
upon, which is advertised in HTTP/2 ALTSVC frame.
|
|
||||||
--altsvc-origin=<ORIGIN>
|
|
||||||
Origin that alternative service is applicable to,
|
|
||||||
which is advertised in HTTP/2 ALTSVC frame.
|
|
||||||
--frontend-http2-dump-request-header=<PATH>
|
--frontend-http2-dump-request-header=<PATH>
|
||||||
Dumps request headers received by HTTP/2 frontend
|
Dumps request headers received by HTTP/2 frontend
|
||||||
to the file denoted in <PATH>. The output is
|
to the file denoted in <PATH>. The output is
|
||||||
|
@ -883,10 +869,7 @@ int main(int argc, char **argv)
|
||||||
{"worker-read-burst", required_argument, &flag, 51},
|
{"worker-read-burst", required_argument, &flag, 51},
|
||||||
{"worker-write-rate", required_argument, &flag, 52},
|
{"worker-write-rate", required_argument, &flag, 52},
|
||||||
{"worker-write-burst", required_argument, &flag, 53},
|
{"worker-write-burst", required_argument, &flag, 53},
|
||||||
{"altsvc-port", required_argument, &flag, 54},
|
{"altsvc", required_argument, &flag, 54},
|
||||||
{"altsvc-protocol-id", required_argument, &flag, 55},
|
|
||||||
{"altsvc-host", required_argument, &flag, 56},
|
|
||||||
{"altsvc-origin", required_argument, &flag, 57},
|
|
||||||
{nullptr, 0, nullptr, 0 }
|
{nullptr, 0, nullptr, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1144,20 +1127,8 @@ int main(int argc, char **argv)
|
||||||
cmdcfgs.emplace_back(SHRPX_OPT_WORKER_WRITE_BURST, optarg);
|
cmdcfgs.emplace_back(SHRPX_OPT_WORKER_WRITE_BURST, optarg);
|
||||||
break;
|
break;
|
||||||
case 54:
|
case 54:
|
||||||
// --altsvc-port
|
// --altsvc
|
||||||
cmdcfgs.emplace_back(SHRPX_OPT_ALTSVC_PORT, optarg);
|
cmdcfgs.emplace_back(SHRPX_OPT_ALTSVC, optarg);
|
||||||
break;
|
|
||||||
case 55:
|
|
||||||
// --altsvc-protocol-id
|
|
||||||
cmdcfgs.emplace_back(SHRPX_OPT_ALTSVC_PROTOCOL_ID, optarg);
|
|
||||||
break;
|
|
||||||
case 56:
|
|
||||||
// --altsvc-host
|
|
||||||
cmdcfgs.emplace_back(SHRPX_OPT_ALTSVC_HOST, optarg);
|
|
||||||
break;
|
|
||||||
case 57:
|
|
||||||
// --altsvc-origin
|
|
||||||
cmdcfgs.emplace_back(SHRPX_OPT_ALTSVC_ORIGIN, optarg);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -121,10 +121,7 @@ const char SHRPX_OPT_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER[] =
|
||||||
const char SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING[] = "http2-no-cookie-crumbling";
|
const char SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING[] = "http2-no-cookie-crumbling";
|
||||||
const char SHRPX_OPT_FRONTEND_FRAME_DEBUG[] = "frontend-frame-debug";
|
const char SHRPX_OPT_FRONTEND_FRAME_DEBUG[] = "frontend-frame-debug";
|
||||||
const char SHRPX_OPT_PADDING[] = "padding";
|
const char SHRPX_OPT_PADDING[] = "padding";
|
||||||
const char SHRPX_OPT_ALTSVC_PORT[] = "altsvc-port";
|
const char SHRPX_OPT_ALTSVC[] = "altsvc";
|
||||||
const char SHRPX_OPT_ALTSVC_PROTOCOL_ID[] = "altsvc-protocol-id";
|
|
||||||
const char SHRPX_OPT_ALTSVC_HOST[] = "altsvc-host";
|
|
||||||
const char SHRPX_OPT_ALTSVC_ORIGIN[] = "altsvc-origin";
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
Config *config = nullptr;
|
Config *config = nullptr;
|
||||||
|
@ -502,32 +499,50 @@ int parse_config(const char *opt, const char *optarg)
|
||||||
mod_config()->upstream_frame_debug = util::strieq(optarg, "yes");
|
mod_config()->upstream_frame_debug = util::strieq(optarg, "yes");
|
||||||
} else if(util::strieq(opt, SHRPX_OPT_PADDING)) {
|
} else if(util::strieq(opt, SHRPX_OPT_PADDING)) {
|
||||||
mod_config()->padding = strtoul(optarg, nullptr, 10);
|
mod_config()->padding = strtoul(optarg, nullptr, 10);
|
||||||
} else if(util::strieq(opt, SHRPX_OPT_ALTSVC_PORT)) {
|
} else if(util::strieq(opt, SHRPX_OPT_ALTSVC)) {
|
||||||
errno = 0;
|
size_t len;
|
||||||
|
|
||||||
auto port = strtoul(optarg, nullptr, 10);
|
auto tokens = parse_config_str_list(&len, optarg);
|
||||||
|
|
||||||
if(errno == 0 &&
|
if(len < 2) {
|
||||||
1 <= port && port <= std::numeric_limits<uint16_t>::max()) {
|
// Requires at least protocol_id and port
|
||||||
|
LOG(ERROR) << "altsvc: too few parameters: " << optarg;
|
||||||
mod_config()->altsvc_port = port;
|
|
||||||
} else {
|
|
||||||
LOG(ERROR) << "altsvc-port is invalid: " << optarg;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else if(util::strieq(opt, SHRPX_OPT_ALTSVC_PROTOCOL_ID)) {
|
|
||||||
set_config_str(&mod_config()->altsvc_protocol_id, optarg);
|
|
||||||
|
|
||||||
mod_config()->altsvc_protocol_id_len =
|
if(len > 4) {
|
||||||
strlen(get_config()->altsvc_protocol_id);
|
// We only need protocol_id, port, host and origin
|
||||||
} else if(util::strieq(opt, SHRPX_OPT_ALTSVC_HOST)) {
|
LOG(ERROR) << "altsvc: too many parameters: " << optarg;
|
||||||
set_config_str(&mod_config()->altsvc_host, optarg);
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
mod_config()->altsvc_host_len = strlen(get_config()->altsvc_host);
|
errno = 0;
|
||||||
} else if(util::strieq(opt, SHRPX_OPT_ALTSVC_ORIGIN)) {
|
auto port = strtoul(tokens[1], nullptr, 10);
|
||||||
set_config_str(&mod_config()->altsvc_origin, optarg);
|
|
||||||
|
if(errno != 0 || port < 1 || port > std::numeric_limits<uint16_t>::max()) {
|
||||||
|
LOG(ERROR) << "altsvc: port is invalid: " << tokens[1];
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
AltSvc altsvc;
|
||||||
|
|
||||||
|
altsvc.port = port;
|
||||||
|
|
||||||
|
altsvc.protocol_id = tokens[0];
|
||||||
|
altsvc.protocol_id_len = strlen(altsvc.protocol_id);
|
||||||
|
|
||||||
|
if(len > 2) {
|
||||||
|
altsvc.host = tokens[2];
|
||||||
|
altsvc.host_len = strlen(altsvc.host);
|
||||||
|
|
||||||
|
if(len > 3) {
|
||||||
|
altsvc.origin = tokens[3];
|
||||||
|
altsvc.origin_len = strlen(altsvc.origin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod_config()->altsvcs.push_back(std::move(altsvc));
|
||||||
|
|
||||||
mod_config()->altsvc_origin_len = strlen(get_config()->altsvc_origin);
|
|
||||||
} else if(util::strieq(opt, "conf")) {
|
} else if(util::strieq(opt, "conf")) {
|
||||||
LOG(WARNING) << "conf is ignored";
|
LOG(WARNING) << "conf is ignored";
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -110,10 +110,7 @@ extern const char SHRPX_OPT_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER[];
|
||||||
extern const char SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING[];
|
extern const char SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING[];
|
||||||
extern const char SHRPX_OPT_FRONTEND_FRAME_DEBUG[];
|
extern const char SHRPX_OPT_FRONTEND_FRAME_DEBUG[];
|
||||||
extern const char SHRPX_OPT_PADDING[];
|
extern const char SHRPX_OPT_PADDING[];
|
||||||
extern const char SHRPX_OPT_ALTSVC_PORT[];
|
extern const char SHRPX_OPT_ALTSVC[];
|
||||||
extern const char SHRPX_OPT_ALTSVC_PROTOCOL_ID[];
|
|
||||||
extern const char SHRPX_OPT_ALTSVC_HOST[];
|
|
||||||
extern const char SHRPX_OPT_ALTSVC_ORIGIN[];
|
|
||||||
|
|
||||||
union sockaddr_union {
|
union sockaddr_union {
|
||||||
sockaddr sa;
|
sockaddr sa;
|
||||||
|
@ -127,9 +124,32 @@ enum shrpx_proto {
|
||||||
PROTO_HTTP
|
PROTO_HTTP
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AltSvc {
|
||||||
|
AltSvc()
|
||||||
|
: protocol_id(nullptr),
|
||||||
|
host(nullptr),
|
||||||
|
origin(nullptr),
|
||||||
|
protocol_id_len(0),
|
||||||
|
host_len(0),
|
||||||
|
origin_len(0),
|
||||||
|
port(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
char *protocol_id;
|
||||||
|
char *host;
|
||||||
|
char *origin;
|
||||||
|
|
||||||
|
size_t protocol_id_len;
|
||||||
|
size_t host_len;
|
||||||
|
size_t origin_len;
|
||||||
|
|
||||||
|
uint16_t port;
|
||||||
|
};
|
||||||
|
|
||||||
struct Config {
|
struct Config {
|
||||||
// The list of (private key file, certificate file) pair
|
// The list of (private key file, certificate file) pair
|
||||||
std::vector<std::pair<std::string, std::string>> subcerts;
|
std::vector<std::pair<std::string, std::string>> subcerts;
|
||||||
|
std::vector<AltSvc> altsvcs;
|
||||||
sockaddr_union downstream_addr;
|
sockaddr_union downstream_addr;
|
||||||
// binary form of http proxy host and port
|
// binary form of http proxy host and port
|
||||||
sockaddr_union downstream_http_proxy_addr;
|
sockaddr_union downstream_http_proxy_addr;
|
||||||
|
@ -176,9 +196,6 @@ struct Config {
|
||||||
char *client_cert_file;
|
char *client_cert_file;
|
||||||
FILE *http2_upstream_dump_request_header;
|
FILE *http2_upstream_dump_request_header;
|
||||||
FILE *http2_upstream_dump_response_header;
|
FILE *http2_upstream_dump_response_header;
|
||||||
char *altsvc_protocol_id;
|
|
||||||
char *altsvc_host;
|
|
||||||
char *altsvc_origin;
|
|
||||||
nghttp2_option *http2_option;
|
nghttp2_option *http2_option;
|
||||||
size_t downstream_addrlen;
|
size_t downstream_addrlen;
|
||||||
size_t num_worker;
|
size_t num_worker;
|
||||||
|
@ -202,9 +219,6 @@ struct Config {
|
||||||
// The number of elements in tls_proto_list
|
// The number of elements in tls_proto_list
|
||||||
size_t tls_proto_list_len;
|
size_t tls_proto_list_len;
|
||||||
size_t padding;
|
size_t padding;
|
||||||
size_t altsvc_protocol_id_len;
|
|
||||||
size_t altsvc_host_len;
|
|
||||||
size_t altsvc_origin_len;
|
|
||||||
// downstream protocol; this will be determined by given options.
|
// downstream protocol; this will be determined by given options.
|
||||||
shrpx_proto downstream_proto;
|
shrpx_proto downstream_proto;
|
||||||
int syslog_facility;
|
int syslog_facility;
|
||||||
|
@ -215,7 +229,6 @@ struct Config {
|
||||||
uint16_t downstream_port;
|
uint16_t downstream_port;
|
||||||
// port in http proxy URI
|
// port in http proxy URI
|
||||||
uint16_t downstream_http_proxy_port;
|
uint16_t downstream_http_proxy_port;
|
||||||
uint16_t altsvc_port;
|
|
||||||
bool verbose;
|
bool verbose;
|
||||||
bool daemon;
|
bool daemon;
|
||||||
bool verify_client;
|
bool verify_client;
|
||||||
|
|
|
@ -547,25 +547,27 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(get_config()->altsvc_port != 0 && get_config()->altsvc_protocol_id) {
|
if(!get_config()->altsvcs.empty()) {
|
||||||
// Set max_age to 24hrs, which is default for alt-svc header
|
// Set max_age to 24hrs, which is default for alt-svc header
|
||||||
// field.
|
// field.
|
||||||
|
for(auto& altsvc : get_config()->altsvcs) {
|
||||||
rv = nghttp2_submit_altsvc
|
rv = nghttp2_submit_altsvc
|
||||||
(session_, NGHTTP2_FLAG_NONE, 0,
|
(session_, NGHTTP2_FLAG_NONE, 0,
|
||||||
86400,
|
86400,
|
||||||
get_config()->altsvc_port,
|
altsvc.port,
|
||||||
reinterpret_cast<const uint8_t*>(get_config()->altsvc_protocol_id),
|
reinterpret_cast<const uint8_t*>(altsvc.protocol_id),
|
||||||
get_config()->altsvc_protocol_id_len,
|
altsvc.protocol_id_len,
|
||||||
reinterpret_cast<const uint8_t*>(get_config()->altsvc_host),
|
reinterpret_cast<const uint8_t*>(altsvc.host),
|
||||||
get_config()->altsvc_host_len,
|
altsvc.host_len,
|
||||||
reinterpret_cast<const uint8_t*>(get_config()->altsvc_origin),
|
reinterpret_cast<const uint8_t*>(altsvc.origin),
|
||||||
get_config()->altsvc_origin_len);
|
altsvc.origin_len);
|
||||||
|
|
||||||
if(rv != 0) {
|
if(rv != 0) {
|
||||||
ULOG(ERROR, this) << "nghttp2_submit_altsvc() returned error: "
|
ULOG(ERROR, this) << "nghttp2_submit_altsvc() returned error: "
|
||||||
<< nghttp2_strerror(rv);
|
<< nghttp2_strerror(rv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Http2Upstream::~Http2Upstream()
|
Http2Upstream::~Http2Upstream()
|
||||||
|
|
|
@ -681,12 +681,18 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream)
|
||||||
|
|
||||||
if(downstream->get_norm_response_header("alt-svc") == end_headers) {
|
if(downstream->get_norm_response_header("alt-svc") == end_headers) {
|
||||||
// We won't change or alter alt-svc from backend at the moment.
|
// We won't change or alter alt-svc from backend at the moment.
|
||||||
if(get_config()->altsvc_port != 0 && get_config()->altsvc_protocol_id) {
|
if(!get_config()->altsvcs.empty()) {
|
||||||
hdrs += "Alt-Svc: ";
|
hdrs += "Alt-Svc: ";
|
||||||
hdrs += util::percent_encode_token(get_config()->altsvc_protocol_id);
|
|
||||||
|
for(auto& altsvc : get_config()->altsvcs) {
|
||||||
|
hdrs += util::percent_encode_token(altsvc.protocol_id);
|
||||||
hdrs += "=";
|
hdrs += "=";
|
||||||
hdrs += util::utos(get_config()->altsvc_port);
|
hdrs += util::utos(altsvc.port);
|
||||||
hdrs += "\r\n";
|
hdrs += ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
hdrs[hdrs.size() - 2] = '\r';
|
||||||
|
hdrs[hdrs.size() - 1] = '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue