[core] more robust max-age parsing
This commit is contained in:
@@ -1,18 +1,18 @@
|
||||
#include <mbgl/storage/http_request_base.hpp>
|
||||
|
||||
#include <mbgl/util/http_header.hpp>
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
int64_t HTTPRequestBase::parseCacheControl(const char *value) {
|
||||
if (value) {
|
||||
unsigned long long seconds = 0;
|
||||
// TODO: cache-control may contain other information as well:
|
||||
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
|
||||
if (std::sscanf(value, "max-age=%llu", &seconds) == 1) {
|
||||
const auto cacheControl = http::CacheControl::parse(value);
|
||||
|
||||
if (cacheControl.maxAge) {
|
||||
return std::chrono::duration_cast<std::chrono::seconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch()).count() +
|
||||
seconds;
|
||||
*cacheControl.maxAge;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
29
src/mbgl/util/http_header.cpp
Normal file
29
src/mbgl/util/http_header.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <mbgl/util/http_header.hpp>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#pragma GCC diagnostic ignored "-Wshadow"
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/phoenix_core.hpp>
|
||||
#include <boost/spirit/include/phoenix_operator.hpp>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
namespace mbgl {
|
||||
namespace http {
|
||||
|
||||
CacheControl CacheControl::parse(const std::string& value) {
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace phoenix = boost::phoenix;
|
||||
|
||||
CacheControl result;
|
||||
qi::phrase_parse(value.begin(), value.end(), (
|
||||
(qi::lit("must-revalidate") [ phoenix::ref(result.mustRevalidate) = true ]) |
|
||||
(qi::lit("max-age") >> '=' >> qi::ulong_long [ phoenix::ref(result.maxAge) = qi::_1 ]) |
|
||||
(*(('"' >> *(('\\' >> qi::char_) | (qi::char_ - '"')) >> '"') | (qi::char_ - '"' - ',')))
|
||||
) % ',', qi::ascii::space);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace http
|
||||
} // namespace mbgl
|
||||
22
src/mbgl/util/http_header.hpp
Normal file
22
src/mbgl/util/http_header.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef MBGL_UTIL_HTTP_HEADER
|
||||
#define MBGL_UTIL_HTTP_HEADER
|
||||
|
||||
#include <mapbox/optional.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace mbgl {
|
||||
namespace http {
|
||||
|
||||
class CacheControl {
|
||||
public:
|
||||
static CacheControl parse(const std::string&);
|
||||
|
||||
mapbox::util::optional<uint64_t> maxAge;
|
||||
bool mustRevalidate = false;
|
||||
};
|
||||
|
||||
} // namespace http
|
||||
} // namespace mbgl
|
||||
|
||||
#endif
|
||||
71
test/storage/headers.cpp
Normal file
71
test/storage/headers.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#include "storage.hpp"
|
||||
#include "../fixtures/fixture_log_observer.hpp"
|
||||
|
||||
#include <mbgl/util/http_header.hpp>
|
||||
|
||||
TEST_F(Storage, HTTPHeaderParsing) {
|
||||
using namespace mbgl;
|
||||
|
||||
http::CacheControl cc;
|
||||
|
||||
cc = http::CacheControl::parse(R"#()#");
|
||||
ASSERT_FALSE(bool(cc.maxAge));
|
||||
EXPECT_EQ(false, cc.mustRevalidate);
|
||||
|
||||
cc = http::CacheControl::parse(R"#(max-age =34)#");
|
||||
ASSERT_TRUE(bool(cc.maxAge));
|
||||
EXPECT_EQ(34, *cc.maxAge);
|
||||
EXPECT_EQ(false, cc.mustRevalidate);
|
||||
|
||||
cc = http::CacheControl::parse(R"#(,max-age=1)#");
|
||||
ASSERT_TRUE(bool(cc.maxAge));
|
||||
EXPECT_EQ(1, *cc.maxAge);
|
||||
EXPECT_EQ(false, cc.mustRevalidate);
|
||||
|
||||
cc = http::CacheControl::parse(R"#(max-age=-1)#");
|
||||
ASSERT_FALSE(bool(cc.maxAge));
|
||||
EXPECT_EQ(false, cc.mustRevalidate);
|
||||
|
||||
cc = http::CacheControl::parse(R"#(max-age=foo)#");
|
||||
ASSERT_FALSE(bool(cc.maxAge));
|
||||
EXPECT_EQ(false, cc.mustRevalidate);
|
||||
|
||||
cc = http::CacheControl::parse(R"#(max-age="34,max-age="22,max-age=28)#");
|
||||
ASSERT_TRUE(bool(cc.maxAge));
|
||||
EXPECT_EQ(28, *cc.maxAge);
|
||||
EXPECT_EQ(false, cc.mustRevalidate);
|
||||
|
||||
cc = http::CacheControl::parse(R"#(max-age=3,max-age="34)#");
|
||||
ASSERT_TRUE(bool(cc.maxAge));
|
||||
EXPECT_EQ(3, *cc.maxAge);
|
||||
EXPECT_EQ(false, cc.mustRevalidate);
|
||||
|
||||
cc = http::CacheControl::parse(R"#(max-age="\",max-age=4,")#");
|
||||
ASSERT_FALSE(bool(cc.maxAge));
|
||||
EXPECT_EQ(false, cc.mustRevalidate);
|
||||
|
||||
cc = http::CacheControl::parse(R"#(private, max-age=0, no-cache)#");
|
||||
ASSERT_TRUE(bool(cc.maxAge));
|
||||
EXPECT_EQ(0, *cc.maxAge);
|
||||
EXPECT_EQ(false, cc.mustRevalidate);
|
||||
|
||||
cc = http::CacheControl::parse(R"#(max-age=0, no-cache, no-store)#");
|
||||
ASSERT_TRUE(bool(cc.maxAge));
|
||||
EXPECT_EQ(0, *cc.maxAge);
|
||||
EXPECT_EQ(false, cc.mustRevalidate);
|
||||
|
||||
cc = http::CacheControl::parse(R"#(, private , max-bar=3 , no-cache, "\,",,foo=",",,max-age=32)#");
|
||||
ASSERT_TRUE(bool(cc.maxAge));
|
||||
EXPECT_EQ(32, *cc.maxAge);
|
||||
EXPECT_EQ(false, cc.mustRevalidate);
|
||||
|
||||
cc = http::CacheControl::parse(R"#(max-age=3600, must-revalidate)#");
|
||||
ASSERT_TRUE(bool(cc.maxAge));
|
||||
EXPECT_EQ(3600, *cc.maxAge);
|
||||
EXPECT_EQ(true, cc.mustRevalidate);
|
||||
|
||||
cc = http::CacheControl::parse(R"#(no-cache="Expires,Via",max-age=3600, must-revalidate)#");
|
||||
ASSERT_TRUE(bool(cc.maxAge));
|
||||
EXPECT_EQ(3600, *cc.maxAge);
|
||||
EXPECT_EQ(true, cc.mustRevalidate);
|
||||
}
|
||||
@@ -72,6 +72,7 @@
|
||||
'storage/database.cpp',
|
||||
'storage/directory_reading.cpp',
|
||||
'storage/file_reading.cpp',
|
||||
'storage/headers.cpp',
|
||||
'storage/http_cancel.cpp',
|
||||
'storage/http_coalescing.cpp',
|
||||
'storage/http_error.cpp',
|
||||
|
||||
Reference in New Issue
Block a user