nghttpx: Remember which resource is pushed
Remember which resource is pushed in order to conform to the semantics described in RFC 8297.
This commit is contained in:
parent
a776b0dbcc
commit
a31a2e3b2c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue