nghttp: Assign different priority according to the resource type
This commit is contained in:
parent
31ae1fe660
commit
8e9f08f81d
|
@ -60,6 +60,20 @@ const char* get_attr(const xmlChar **attrs, const char *name)
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void add_link(ParserData *parser_data, const char *uri, RequestPriority pri)
|
||||||
|
{
|
||||||
|
auto u = xmlBuildURI(reinterpret_cast<const xmlChar*>(uri),
|
||||||
|
reinterpret_cast<const xmlChar*>
|
||||||
|
(parser_data->base_uri.c_str()));
|
||||||
|
if(u) {
|
||||||
|
parser_data->links.push_back(std::make_pair(reinterpret_cast<char*>(u),
|
||||||
|
pri));
|
||||||
|
free(u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void start_element_func
|
void start_element_func
|
||||||
(void* user_data,
|
(void* user_data,
|
||||||
|
@ -70,29 +84,26 @@ void start_element_func
|
||||||
if(util::strieq(reinterpret_cast<const char*>(name), "link")) {
|
if(util::strieq(reinterpret_cast<const char*>(name), "link")) {
|
||||||
const char *rel_attr = get_attr(attrs, "rel");
|
const char *rel_attr = get_attr(attrs, "rel");
|
||||||
const char *href_attr = get_attr(attrs, "href");
|
const char *href_attr = get_attr(attrs, "href");
|
||||||
if((util::strieq(rel_attr, "shortcut icon") ||
|
if(!href_attr) {
|
||||||
util::strieq(rel_attr, "stylesheet")) &&
|
return;
|
||||||
href_attr) {
|
|
||||||
xmlChar *u = xmlBuildURI(reinterpret_cast<const xmlChar*>(href_attr),
|
|
||||||
reinterpret_cast<const xmlChar*>
|
|
||||||
(parser_data->base_uri.c_str()));
|
|
||||||
if(u) {
|
|
||||||
parser_data->links.push_back(reinterpret_cast<char*>(u));
|
|
||||||
free(u);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if(util::strieq(reinterpret_cast<const char*>(name), "img") ||
|
if(util::strieq(rel_attr, "shortcut icon")) {
|
||||||
util::strieq(reinterpret_cast<const char*>(name), "script")) {
|
add_link(parser_data, href_attr, REQ_PRI_LOWEST);
|
||||||
|
} else if(util::strieq(rel_attr, "stylesheet")) {
|
||||||
|
add_link(parser_data, href_attr, REQ_PRI_MEDIUM);
|
||||||
|
}
|
||||||
|
} else if(util::strieq(reinterpret_cast<const char*>(name), "img")) {
|
||||||
const char *src_attr = get_attr(attrs, "src");
|
const char *src_attr = get_attr(attrs, "src");
|
||||||
if(src_attr) {
|
if(!src_attr) {
|
||||||
xmlChar *u = xmlBuildURI(reinterpret_cast<const xmlChar*>(src_attr),
|
return;
|
||||||
reinterpret_cast<const xmlChar*>
|
|
||||||
(parser_data->base_uri.c_str()));
|
|
||||||
if(u) {
|
|
||||||
parser_data->links.push_back(reinterpret_cast<char*>(u));
|
|
||||||
free(u);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
add_link(parser_data, src_attr, REQ_PRI_LOWEST);
|
||||||
|
} else if(util::strieq(reinterpret_cast<const char*>(name), "script")) {
|
||||||
|
const char *src_attr = get_attr(attrs, "src");
|
||||||
|
if(!src_attr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
add_link(parser_data, src_attr, REQ_PRI_MEDIUM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -168,7 +179,8 @@ int HtmlParser::parse_chunk_internal(const char *chunk, size_t size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::string>& HtmlParser::get_links() const
|
const std::vector<std::pair<std::string, RequestPriority>>&
|
||||||
|
HtmlParser::get_links() const
|
||||||
{
|
{
|
||||||
return parser_data_.links;
|
return parser_data_.links;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,9 +36,16 @@
|
||||||
|
|
||||||
namespace nghttp2 {
|
namespace nghttp2 {
|
||||||
|
|
||||||
|
enum RequestPriority {
|
||||||
|
REQ_PRI_HIGH = 0,
|
||||||
|
REQ_PRI_MEDIUM = 1,
|
||||||
|
REQ_PRI_LOW = 2,
|
||||||
|
REQ_PRI_LOWEST = 3
|
||||||
|
};
|
||||||
|
|
||||||
struct ParserData {
|
struct ParserData {
|
||||||
std::string base_uri;
|
std::string base_uri;
|
||||||
std::vector<std::string> links;
|
std::vector<std::pair<std::string, RequestPriority>> links;
|
||||||
ParserData(const std::string& base_uri);
|
ParserData(const std::string& base_uri);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -47,7 +54,8 @@ public:
|
||||||
HtmlParser(const std::string& base_uri);
|
HtmlParser(const std::string& base_uri);
|
||||||
~HtmlParser();
|
~HtmlParser();
|
||||||
int parse_chunk(const char *chunk, size_t size, int fin);
|
int parse_chunk(const char *chunk, size_t size, int fin);
|
||||||
const std::vector<std::string>& get_links() const;
|
const std::vector<std::pair<std::string, RequestPriority>>&
|
||||||
|
get_links() const;
|
||||||
void clear_links();
|
void clear_links();
|
||||||
private:
|
private:
|
||||||
int parse_chunk_internal(const char *chunk, size_t size, int fin);
|
int parse_chunk_internal(const char *chunk, size_t size, int fin);
|
||||||
|
|
|
@ -248,16 +248,17 @@ struct Request {
|
||||||
const nghttp2_data_provider *data_prd;
|
const nghttp2_data_provider *data_prd;
|
||||||
int64_t data_length;
|
int64_t data_length;
|
||||||
int64_t data_offset;
|
int64_t data_offset;
|
||||||
|
int32_t pri;
|
||||||
// Recursion level: 0: first entity, 1: entity linked from first entity
|
// Recursion level: 0: first entity, 1: entity linked from first entity
|
||||||
int level;
|
int level;
|
||||||
RequestStat stat;
|
RequestStat stat;
|
||||||
std::string status;
|
std::string status;
|
||||||
Request(const std::string& uri, const http_parser_url &u,
|
Request(const std::string& uri, const http_parser_url &u,
|
||||||
const nghttp2_data_provider *data_prd, int64_t data_length,
|
const nghttp2_data_provider *data_prd, int64_t data_length,
|
||||||
int level = 0)
|
int32_t pri, int level = 0)
|
||||||
: uri(uri), u(u),
|
: uri(uri), u(u),
|
||||||
inflater(nullptr), html_parser(nullptr), data_prd(data_prd),
|
inflater(nullptr), html_parser(nullptr), data_prd(data_prd),
|
||||||
data_length(data_length), data_offset(0),
|
data_length(data_length), data_offset(0), pri(pri),
|
||||||
level(level)
|
level(level)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -794,6 +795,7 @@ struct HttpClient {
|
||||||
bool add_request(const std::string& uri,
|
bool add_request(const std::string& uri,
|
||||||
const nghttp2_data_provider *data_prd,
|
const nghttp2_data_provider *data_prd,
|
||||||
int64_t data_length,
|
int64_t data_length,
|
||||||
|
int32_t pri,
|
||||||
int level = 0)
|
int level = 0)
|
||||||
{
|
{
|
||||||
http_parser_url u;
|
http_parser_url u;
|
||||||
|
@ -807,7 +809,7 @@ struct HttpClient {
|
||||||
path_cache.insert(uri);
|
path_cache.insert(uri);
|
||||||
}
|
}
|
||||||
reqvec.push_back(util::make_unique<Request>(uri, u, data_prd,
|
reqvec.push_back(util::make_unique<Request>(uri, u, data_prd,
|
||||||
data_length, level));
|
data_length, pri, level));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -930,12 +932,23 @@ void submit_request(HttpClient *client,
|
||||||
}
|
}
|
||||||
nv[pos] = nullptr;
|
nv[pos] = nullptr;
|
||||||
|
|
||||||
int r = nghttp2_submit_request(client->session, config.pri,
|
int r = nghttp2_submit_request(client->session, req->pri,
|
||||||
nv.get(), req->data_prd, req);
|
nv.get(), req->data_prd, req);
|
||||||
assert(r == 0);
|
assert(r == 0);
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int32_t adjust_pri(int32_t base_pri, int32_t rel_pri)
|
||||||
|
{
|
||||||
|
if((int32_t)NGHTTP2_PRI_LOWEST - rel_pri < base_pri) {
|
||||||
|
return NGHTTP2_PRI_LOWEST;
|
||||||
|
} else {
|
||||||
|
return base_pri + rel_pri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void update_html_parser(HttpClient *client, Request *req,
|
void update_html_parser(HttpClient *client, Request *req,
|
||||||
const uint8_t *data, size_t len, int fin)
|
const uint8_t *data, size_t len, int fin)
|
||||||
|
@ -945,16 +958,16 @@ void update_html_parser(HttpClient *client, Request *req,
|
||||||
}
|
}
|
||||||
req->update_html_parser(data, len, fin);
|
req->update_html_parser(data, len, fin);
|
||||||
|
|
||||||
for(size_t i = 0; i < req->html_parser->get_links().size(); ++i) {
|
for(auto& p : req->html_parser->get_links()) {
|
||||||
const auto& raw_uri = req->html_parser->get_links()[i];
|
auto uri = strip_fragment(p.first.c_str());
|
||||||
auto uri = strip_fragment(raw_uri.c_str());
|
|
||||||
http_parser_url u;
|
http_parser_url u;
|
||||||
if(http_parser_parse_url(uri.c_str(), uri.size(), 0, &u) == 0 &&
|
if(http_parser_parse_url(uri.c_str(), uri.size(), 0, &u) == 0 &&
|
||||||
fieldeq(uri.c_str(), u, req->uri.c_str(), req->u, UF_SCHEMA) &&
|
fieldeq(uri.c_str(), u, req->uri.c_str(), req->u, UF_SCHEMA) &&
|
||||||
fieldeq(uri.c_str(), u, req->uri.c_str(), req->u, UF_HOST) &&
|
fieldeq(uri.c_str(), u, req->uri.c_str(), req->u, UF_HOST) &&
|
||||||
porteq(uri.c_str(), u, req->uri.c_str(), req->u)) {
|
porteq(uri.c_str(), u, req->uri.c_str(), req->u)) {
|
||||||
|
int32_t pri = adjust_pri(req->pri, p.second);
|
||||||
// No POST data for assets
|
// No POST data for assets
|
||||||
if ( client->add_request(uri, nullptr, 0, req->level+1) ) {
|
if ( client->add_request(uri, nullptr, 0, pri, req->level+1) ) {
|
||||||
submit_request(client, config.headers,
|
submit_request(client, config.headers,
|
||||||
client->reqvec.back().get());
|
client->reqvec.back().get());
|
||||||
}
|
}
|
||||||
|
@ -1344,7 +1357,7 @@ int communicate(const std::string& scheme, const std::string& host,
|
||||||
for(auto req : requests) {
|
for(auto req : requests) {
|
||||||
for(int i = 0; i < config.multiply; ++i) {
|
for(int i = 0; i < config.multiply; ++i) {
|
||||||
client.add_request(std::get<0>(req), std::get<1>(req),
|
client.add_request(std::get<0>(req), std::get<1>(req),
|
||||||
std::get<2>(req));
|
std::get<2>(req), config.pri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
client.update_hostport();
|
client.update_hostport();
|
||||||
|
|
Loading…
Reference in New Issue