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)
 {

Reply via email to