src: Support rel with quoted value in Link header parser
This commit is contained in:
parent
6b28e033de
commit
1b00bc1929
48
src/http2.cc
48
src/http2.cc
|
@ -741,6 +741,54 @@ parse_next_link_header_once(const char *first, const char *last) {
|
|||
}
|
||||
// we expect link-param
|
||||
|
||||
// rel can take several relations using quoted form.
|
||||
static const char PLP[] = "rel=\"";
|
||||
static const size_t PLPLEN = sizeof(PLP) - 1;
|
||||
|
||||
static const char PLT[] = "preload";
|
||||
static const size_t PLTLEN = sizeof(PLT) - 1;
|
||||
if (first + PLPLEN < last && *(first + PLPLEN - 1) == '"' &&
|
||||
std::equal(PLP, PLP + PLPLEN, first)) {
|
||||
// we have to search preload in whitespace separated list:
|
||||
// rel="preload something http://example.org/foo"
|
||||
first += PLPLEN;
|
||||
auto start = first;
|
||||
for (; first != last;) {
|
||||
if (*first != ' ' && *first != '"') {
|
||||
++first;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (start == first) {
|
||||
return {{{0, 0}}, last};
|
||||
}
|
||||
|
||||
if (!ok && start + PLTLEN == first && *(start + PLTLEN - 1) == 'd' &&
|
||||
std::equal(PLT, PLT + PLTLEN, start)) {
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if (*first == '"') {
|
||||
break;
|
||||
}
|
||||
first = skip_lws(first, last);
|
||||
start = first;
|
||||
}
|
||||
if (first == last) {
|
||||
return {{{0, 0}}, first};
|
||||
}
|
||||
assert(*first == '"');
|
||||
++first;
|
||||
if (first == last || *first == ',') {
|
||||
goto almost_done;
|
||||
}
|
||||
if (*first == ';') {
|
||||
++first;
|
||||
// parse next link-param
|
||||
continue;
|
||||
}
|
||||
return {{{0, 0}}, last};
|
||||
}
|
||||
// we are only interested in rel=preload parameter. Others are
|
||||
// simply skipped.
|
||||
static const char PL[] = "rel=preload";
|
||||
|
|
|
@ -489,6 +489,110 @@ void test_http2_parse_link_header(void) {
|
|||
auto res = http2::parse_link_header(s, sizeof(s) - 1);
|
||||
CU_ASSERT(0 == res.size());
|
||||
}
|
||||
{
|
||||
// preload in relation-types list
|
||||
const char s[] = R"(<url>; rel="preload")";
|
||||
auto res = http2::parse_link_header(s, sizeof(s) - 1);
|
||||
CU_ASSERT(1 == res.size());
|
||||
CU_ASSERT(std::make_pair(&s[1], &s[4]) == res[0].uri);
|
||||
}
|
||||
{
|
||||
// preload in relation-types list followed by another parameter
|
||||
const char s[] = R"(<url>; rel="preload foo")";
|
||||
auto res = http2::parse_link_header(s, sizeof(s) - 1);
|
||||
CU_ASSERT(1 == res.size());
|
||||
CU_ASSERT(std::make_pair(&s[1], &s[4]) == res[0].uri);
|
||||
}
|
||||
{
|
||||
// preload in relation-types list following another parameter
|
||||
const char s[] = R"(<url>; rel="foo preload")";
|
||||
auto res = http2::parse_link_header(s, sizeof(s) - 1);
|
||||
CU_ASSERT(1 == res.size());
|
||||
CU_ASSERT(std::make_pair(&s[1], &s[4]) == res[0].uri);
|
||||
}
|
||||
{
|
||||
// preload in relation-types list between other parameters
|
||||
const char s[] = R"(<url>; rel="foo preload bar")";
|
||||
auto res = http2::parse_link_header(s, sizeof(s) - 1);
|
||||
CU_ASSERT(1 == res.size());
|
||||
CU_ASSERT(std::make_pair(&s[1], &s[4]) == res[0].uri);
|
||||
}
|
||||
{
|
||||
// preload in relation-types list between other parameters
|
||||
const char s[] = R"(<url>; rel="foo preload bar")";
|
||||
auto res = http2::parse_link_header(s, sizeof(s) - 1);
|
||||
CU_ASSERT(1 == res.size());
|
||||
CU_ASSERT(std::make_pair(&s[1], &s[4]) == res[0].uri);
|
||||
}
|
||||
{
|
||||
// no preload in relation-types list
|
||||
const char s[] = R"(<url>; rel="foo")";
|
||||
auto res = http2::parse_link_header(s, sizeof(s) - 1);
|
||||
CU_ASSERT(0 == res.size());
|
||||
}
|
||||
{
|
||||
// no preload in relation-types list, multiple unrelated elements.
|
||||
const char s[] = R"(<url>; rel="foo bar")";
|
||||
auto res = http2::parse_link_header(s, sizeof(s) - 1);
|
||||
CU_ASSERT(0 == res.size());
|
||||
}
|
||||
{
|
||||
// preload in relation-types list, followed by another link-value.
|
||||
const char s[] = R"(<url>; rel="preload", <url>)";
|
||||
auto res = http2::parse_link_header(s, sizeof(s) - 1);
|
||||
CU_ASSERT(1 == res.size());
|
||||
CU_ASSERT(std::make_pair(&s[1], &s[4]) == res[0].uri);
|
||||
}
|
||||
{
|
||||
// preload in relation-types list, following another link-value.
|
||||
const char s[] = R"(<url>, <url>; rel="preload")";
|
||||
auto res = http2::parse_link_header(s, sizeof(s) - 1);
|
||||
CU_ASSERT(1 == res.size());
|
||||
CU_ASSERT(std::make_pair(&s[8], &s[11]) == res[0].uri);
|
||||
}
|
||||
{
|
||||
// preload in relation-types list, followed by another link-param.
|
||||
const char s[] = R"(<url>; rel="preload"; as="font")";
|
||||
auto res = http2::parse_link_header(s, sizeof(s) - 1);
|
||||
CU_ASSERT(1 == res.size());
|
||||
CU_ASSERT(std::make_pair(&s[1], &s[4]) == res[0].uri);
|
||||
}
|
||||
{
|
||||
// preload in relation-types list, followed by character other
|
||||
// than ';' or ','
|
||||
const char s[] = R"(<url>; rel="preload".)";
|
||||
auto res = http2::parse_link_header(s, sizeof(s) - 1);
|
||||
CU_ASSERT(0 == res.size());
|
||||
}
|
||||
{
|
||||
// preload in relation-types list, followed by ';' but it
|
||||
// terminates input
|
||||
const char s[] = R"(<url>; rel="preload";)";
|
||||
auto res = http2::parse_link_header(s, sizeof(s) - 1);
|
||||
CU_ASSERT(0 == res.size());
|
||||
}
|
||||
{
|
||||
// preload in relation-types list, followed by ',' but it
|
||||
// terminates input
|
||||
const char s[] = R"(<url>; rel="preload",)";
|
||||
auto res = http2::parse_link_header(s, sizeof(s) - 1);
|
||||
CU_ASSERT(1 == res.size());
|
||||
CU_ASSERT(std::make_pair(&s[1], &s[4]) == res[0].uri);
|
||||
}
|
||||
{
|
||||
// preload in relation-types list but there is preceding white
|
||||
// space.
|
||||
const char s[] = R"(<url>; rel=" preload")";
|
||||
auto res = http2::parse_link_header(s, sizeof(s) - 1);
|
||||
CU_ASSERT(0 == res.size());
|
||||
}
|
||||
{
|
||||
// preload in relation-types list but there is trailing white
|
||||
// space.
|
||||
const char s[] = R"(<url>; rel="preload ")";
|
||||
auto res = http2::parse_link_header(s, sizeof(s) - 1);
|
||||
CU_ASSERT(0 == res.size());
|
||||
}
|
||||
}
|
||||
|
||||
void test_http2_path_join(void) {
|
||||
|
|
Loading…
Reference in New Issue