Unverified Commit 0fbb46ed authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa Committed by GitHub

Merge pull request #1101 from nghttp2/remember-pushed-links

nghttpx: Remember which resource is pushed
parents 6ad629de a31a2e3b
......@@ -32,6 +32,7 @@
#include <string>
#include <memory>
#include <chrono>
#include <algorithm>
#include <ev.h>
......@@ -207,7 +208,40 @@ struct Response {
unconsumed_body_length -= len;
}
// returns true if a resource denoted by scheme, authority, and path
// has already been pushed.
bool is_resource_pushed(const StringRef &scheme, const StringRef &authority,
const StringRef &path) const {
if (!pushed_resources) {
return false;
}
return std::find(std::begin(*pushed_resources), std::end(*pushed_resources),
std::make_tuple(scheme, authority, path)) !=
std::end(*pushed_resources);
}
// remember that a resource denoted by scheme, authority, and path
// is pushed.
void resource_pushed(const StringRef &scheme, const StringRef &authority,
const StringRef &path) {
if (!pushed_resources) {
pushed_resources = make_unique<
std::vector<std::tuple<StringRef, StringRef, StringRef>>>();
}
pushed_resources->emplace_back(scheme, authority, path);
}
FieldStore fs;
// array of the tuple of scheme, authority, and path of pushed
// resource. This is required because RFC 8297 says that server
// typically includes header fields appeared in non-final response
// header fields in final response header fields. Without checking
// that a particular resource has already been pushed, or not, we
// end up pushing the same resource at least twice. It is unknown
// that we should use more complex data structure (e.g., std::set)
// to find the resources faster.
std::unique_ptr<std::vector<std::tuple<StringRef, StringRef, StringRef>>>
pushed_resources;
// the length of response body received so far
int64_t recv_body_length;
// The number of bytes not consumed by the application yet. This is
......
......@@ -2039,7 +2039,7 @@ int Http2Upstream::prepare_push_promise(Downstream *downstream) {
int rv;
const auto &req = downstream->request();
const auto &resp = downstream->response();
auto &resp = downstream->response();
auto base = http2::get_pure_path_component(req.path);
if (base.empty()) {
......@@ -2069,10 +2069,16 @@ int Http2Upstream::prepare_push_promise(Downstream *downstream) {
authority = req.authority;
}
if (resp.is_resource_pushed(scheme, authority, path)) {
continue;
}
rv = submit_push_promise(scheme, authority, path, downstream);
if (rv != 0) {
return -1;
}
resp.resource_pushed(scheme, authority, path);
}
}
return 0;
......@@ -2182,12 +2188,20 @@ int Http2Upstream::initiate_push(Downstream *downstream, const StringRef &uri) {
authority = req.authority;
}
auto &resp = downstream->response();
if (resp.is_resource_pushed(scheme, authority, path)) {
return 0;
}
rv = submit_push_promise(scheme, authority, path, downstream);
if (rv != 0) {
return -1;
}
resp.resource_pushed(scheme, authority, path);
return 0;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment