nghttpx: Allow absolute URI in Link header field for push

This commit is contained in:
Tatsuhiro Tsujikawa 2015-09-05 18:59:19 +09:00
parent 6b38f7e0d2
commit e19d5efced
3 changed files with 33 additions and 19 deletions

View File

@ -59,17 +59,12 @@ header field to initiate server push:
Link: </fonts/font.woff>; rel=preload Link: </fonts/font.woff>; rel=preload
Link: </css/theme.css>; rel=preload Link: </css/theme.css>; rel=preload
Currently, the following restrictions are applied for server push: Currently, the following restriction is applied for server push:
1. URI-reference must not contain authority. If it exists, it is not 1. The associated stream must have method "GET" or "POST". The
pushed. ``/fonts/font.woff`` and ``css/theme.css`` are eligible to
be pushed. ``https://example.org/fonts/font.woff`` and
``//example.org/css/theme.css`` are not.
2. The associated stream must have method "GET" or "POST". The
associated stream's status code must be 200. associated stream's status code must be 200.
These limitations may be loosened in the future release. This limitation may be loosened in the future release.
UNIX DOMAIN SOCKET UNIX DOMAIN SOCKET
------------------ ------------------

View File

@ -1501,6 +1501,7 @@ int Http2Upstream::prepare_push_promise(Downstream *downstream) {
const char *relq = nullptr; const char *relq = nullptr;
size_t relqlen = 0; size_t relqlen = 0;
std::string authority, scheme;
http_parser_url v{}; http_parser_url v{};
rv = http_parser_parse_url(link_url, link_urllen, 0, &v); rv = http_parser_parse_url(link_url, link_urllen, 0, &v);
if (rv != 0) { if (rv != 0) {
@ -1518,9 +1519,18 @@ int Http2Upstream::prepare_push_promise(Downstream *downstream) {
relqlen = end - relq; relqlen = end - relq;
} }
} else { } else {
if (v.field_set & (1 << UF_HOST)) { if (v.field_set & (1 << UF_SCHEMA)) {
continue; http2::copy_url_component(scheme, &v, UF_SCHEMA, link_url);
} }
if (v.field_set & (1 << UF_HOST)) {
http2::copy_url_component(authority, &v, UF_HOST, link_url);
if (v.field_set & (1 << UF_PORT)) {
authority += ":";
authority += util::utos(v.port);
}
}
if (v.field_set & (1 << UF_PATH)) { if (v.field_set & (1 << UF_PATH)) {
auto &f = v.field_data[UF_PATH]; auto &f = v.field_data[UF_PATH];
rel = link_url + f.off; rel = link_url + f.off;
@ -1536,9 +1546,18 @@ int Http2Upstream::prepare_push_promise(Downstream *downstream) {
relqlen = f.len; relqlen = f.len;
} }
} }
if (scheme.empty()) {
scheme = downstream->get_request_http2_scheme();
}
if (authority.empty()) {
authority = downstream->get_request_http2_authority();
}
auto path = http2::path_join(base, baselen, nullptr, 0, rel, rellen, relq, auto path = http2::path_join(base, baselen, nullptr, 0, rel, rellen, relq,
relqlen); relqlen);
rv = submit_push_promise(path, downstream); rv = submit_push_promise(scheme, authority, path, downstream);
if (rv != 0) { if (rv != 0) {
return -1; return -1;
} }
@ -1547,7 +1566,9 @@ int Http2Upstream::prepare_push_promise(Downstream *downstream) {
return 0; return 0;
} }
int Http2Upstream::submit_push_promise(const std::string &path, int Http2Upstream::submit_push_promise(const std::string &scheme,
const std::string &authority,
const std::string &path,
Downstream *downstream) { Downstream *downstream) {
int rv; int rv;
std::vector<nghttp2_nv> nva; std::vector<nghttp2_nv> nva;
@ -1555,13 +1576,9 @@ int Http2Upstream::submit_push_promise(const std::string &path,
// juse use "GET" for now // juse use "GET" for now
nva.push_back(http2::make_nv_ll(":method", "GET")); nva.push_back(http2::make_nv_ll(":method", "GET"));
nva.push_back( nva.push_back(http2::make_nv_ls(":scheme", scheme));
http2::make_nv_ls(":scheme", downstream->get_request_http2_scheme()));
nva.push_back(http2::make_nv_ls(":path", path)); nva.push_back(http2::make_nv_ls(":path", path));
auto &authority = downstream->get_request_http2_authority();
if (!authority.empty()) {
nva.push_back(http2::make_nv_ls(":authority", authority)); nva.push_back(http2::make_nv_ls(":authority", authority));
}
for (auto &kv : downstream->get_request_headers()) { for (auto &kv : downstream->get_request_headers()) {
switch (kv.token) { switch (kv.token) {

View File

@ -96,7 +96,9 @@ public:
void check_shutdown(); void check_shutdown();
int prepare_push_promise(Downstream *downstream); int prepare_push_promise(Downstream *downstream);
int submit_push_promise(const std::string &path, Downstream *downstream); int submit_push_promise(const std::string &scheme,
const std::string &authority, const std::string &path,
Downstream *downstream);
int on_request_headers(Downstream *downstream, const nghttp2_frame *frame); int on_request_headers(Downstream *downstream, const nghttp2_frame *frame);