Repository: mesos Updated Branches: refs/heads/master aac4aa96b -> 244ae7371
Added http::Request::acceptsMediaType. Review: https://reviews.apache.org/r/36402 Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/244ae737 Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/244ae737 Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/244ae737 Branch: refs/heads/master Commit: 244ae73717202e037c613d01eed8498e094a8fa7 Parents: aac4aa9 Author: Isabel Jimenez <[email protected]> Authored: Tue Aug 11 12:53:48 2015 -0700 Committer: Benjamin Mahler <[email protected]> Committed: Tue Aug 11 12:55:05 2015 -0700 ---------------------------------------------------------------------- 3rdparty/libprocess/include/process/http.hpp | 8 +++- 3rdparty/libprocess/src/http.cpp | 58 +++++++++++++++++++++++ 3rdparty/libprocess/src/tests/http_tests.cpp | 58 +++++++++++++++++++++++ 3 files changed, 123 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/244ae737/3rdparty/libprocess/include/process/http.hpp ---------------------------------------------------------------------- diff --git a/3rdparty/libprocess/include/process/http.hpp b/3rdparty/libprocess/include/process/http.hpp index 3bcca9e..3cd3f15 100644 --- a/3rdparty/libprocess/include/process/http.hpp +++ b/3rdparty/libprocess/include/process/http.hpp @@ -118,9 +118,15 @@ struct Request /** * Returns whether the encoding is considered acceptable in the - * response. See RFC 2616 section 14 for details. + * response. See RFC 2616 section 14.3 for details. */ bool acceptsEncoding(const std::string& encoding) const; + + /** + * Returns whether the media type is considered acceptable in the + * response. See RFC 2616, section 14.1 for the details. + */ + bool acceptsMediaType(const std::string& mediaType) const; }; http://git-wip-us.apache.org/repos/asf/mesos/blob/244ae737/3rdparty/libprocess/src/http.cpp ---------------------------------------------------------------------- diff --git a/3rdparty/libprocess/src/http.cpp b/3rdparty/libprocess/src/http.cpp index 859a5dc..b70e2fa 100644 --- a/3rdparty/libprocess/src/http.cpp +++ b/3rdparty/libprocess/src/http.cpp @@ -189,6 +189,64 @@ bool Request::acceptsEncoding(const string& encoding) const } +bool Request::acceptsMediaType(const string& mediaType) const +{ + vector<string> mediaTypes = strings::tokenize(mediaType, "/"); + + if (mediaTypes.size() != 2) { + return false; + } + + Option<string> accept = headers.get("Accept"); + + // If no Accept header field is present, then it is assumed + // that the client accepts all media types. + if (accept.isNone()) { + return true; + } + + // Remove spaces and tabs for easier parsing. + accept = strings::remove(accept.get(), " "); + accept = strings::remove(accept.get(), "\t"); + accept = strings::remove(accept.get(), "\n"); + + // First match 'type/subtype', then 'type/*', then '*/*'. + vector<string> candidates; + candidates.push_back(mediaType); + candidates.push_back(mediaTypes[0] + "/*"); + candidates.push_back("*/*"); + + foreach (const string& candidate, candidates) { + foreach (const string& type, strings::tokenize(accept.get(), ",")) { + vector<string> tokens = strings::tokenize(type, ";"); + + if (tokens.empty()) { + continue; + } + + // Is the candidate one of the accepted type? + if (strings::lower(tokens[0]) == strings::lower(candidate)) { + // Is there a 0 q value? Ex: 'gzip;q=0.0'. + const map<string, vector<string>> values = + strings::pairs(type, ";", "="); + + // Look for { "q": ["0"] }. + if (values.count("q") == 0 || values.find("q")->second.size() != 1) { + // No q value, or malformed q value. + return true; + } + + // Is the q value > 0? + Try<double> value = numify<double>(values.find("q")->second[0]); + return value.isSome() && value.get() > 0; + } + } + } + + return false; +} + + Pipe::Reader Pipe::reader() const { return Pipe::Reader(data); http://git-wip-us.apache.org/repos/asf/mesos/blob/244ae737/3rdparty/libprocess/src/tests/http_tests.cpp ---------------------------------------------------------------------- diff --git a/3rdparty/libprocess/src/tests/http_tests.cpp b/3rdparty/libprocess/src/tests/http_tests.cpp index ecbcbd5..f89d7ee 100644 --- a/3rdparty/libprocess/src/tests/http_tests.cpp +++ b/3rdparty/libprocess/src/tests/http_tests.cpp @@ -20,6 +20,7 @@ #include <netinet/tcp.h> #include <string> +#include <vector> #include <process/address.hpp> #include <process/future.hpp> @@ -45,6 +46,7 @@ using process::http::URL; using process::network::Socket; using std::string; +using std::vector; using testing::_; using testing::Assign; @@ -652,6 +654,62 @@ TEST(HTTPTest, CaseInsensitiveHeaders) } +TEST(HTTPTest, Accepts) +{ + // Create requests that do not accept the 'text/*' media type. + vector<string> headers = { + "text/*;q=0.0", + "text/html;q=0.0", + "text/", + "text", + "foo/*", + "foo/*, text/*;q=0.0", + "foo/*,\ttext/*;q=0.0", + "*/*, text/*;q=0.0", + "*/*;q=0.0, foo", + "textttt/*" + }; + + foreach (const string& accept, headers) { + http::Request request; + request.headers["Accept"] = accept; + + EXPECT_FALSE(request.acceptsMediaType("text/*")) + << "Not expecting " << accept << " to match 'text/*'"; + + EXPECT_FALSE(request.acceptsMediaType("text/html")) + << "Not expecting " << accept << " to match 'text/html'"; + } + + // Create requests that accept 'text/html' media type. + headers = { + "text/*", + "text/*;q=0.1", + "text/html", + "text/html;q=0.1", + "text/bar, text/html,q=0.1", + "*/*, text/bar;q=0.5", + "*/*;q=0.9, text/foo", + "text/foo,\ttext/*;q=0.1", + "*/*", + "*/*, text/bar", + "*/*, foo/*" + }; + + foreach (const string& accept, headers) { + http::Request request; + request.headers["Accept"] = accept; + + EXPECT_TRUE(request.acceptsMediaType("text/html")) + << "Expecting '" << accept << "' to match 'text/html'"; + } + + // Missing header should accept all media types. + http::Request empty; + EXPECT_TRUE(empty.acceptsMediaType("text/html")); +} + + // TODO(evelinad): Add URLTest for IPv6. TEST(URLTest, Stringification) {
