You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by be...@apache.org on 2015/02/08 16:51:42 UTC

[15/20] mesos git commit: Added http::get/put/post that take URL.

Added http::get/put/post that take URL.

Review: https://reviews.apache.org/r/29534


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/853bd8f8
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/853bd8f8
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/853bd8f8

Branch: refs/heads/master
Commit: 853bd8f8bc50c8d5c80acd1326714732000b4d66
Parents: 1993ff2
Author: Benjamin Hindman <be...@gmail.com>
Authored: Tue Dec 16 13:15:02 2014 -0800
Committer: Benjamin Hindman <be...@gmail.com>
Committed: Sat Feb 7 14:42:46 2015 -0800

----------------------------------------------------------------------
 3rdparty/libprocess/include/process/http.hpp    |  31 ++++-
 3rdparty/libprocess/src/http.cpp                | 125 ++++++++++++++-----
 3rdparty/libprocess/src/tests/http_tests.cpp    |   4 +-
 3rdparty/libprocess/src/tests/metrics_tests.cpp |   6 +-
 4 files changed, 129 insertions(+), 37 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/853bd8f8/3rdparty/libprocess/include/process/http.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/http.hpp b/3rdparty/libprocess/include/process/http.hpp
index 819cee1..f90f2c5 100644
--- a/3rdparty/libprocess/include/process/http.hpp
+++ b/3rdparty/libprocess/include/process/http.hpp
@@ -43,11 +43,15 @@ struct Request
   // Tracked by: https://issues.apache.org/jira/browse/MESOS-328.
   hashmap<std::string, std::string> headers;
   std::string method;
+
+  // TODO(benh): Replace 'url', 'path', 'query', and 'fragment' with URL.
   std::string url; // (path?query#fragment)
   std::string path;
-  std::string fragment;
   hashmap<std::string, std::string> query;
+  std::string fragment;
+
   std::string body;
+
   bool keepAlive;
 
   // Returns whether the encoding is considered acceptable in the request.
@@ -568,6 +572,31 @@ inline std::ostream& operator << (
 }
 
 
+// Asynchronously sends an HTTP GET request to the specified URL and
+// returns the HTTP response.
+Future<Response> get(
+    const URL& url,
+    const Option<hashmap<std::string, std::string>>& headers = None());
+
+
+// Asynchronously sends an HTTP PUT request to the specified URL and
+// returns the HTTP response.
+Future<Response> put(
+    const URL& url,
+    const Option<hashmap<std::string, std::string>>& headers = None(),
+    const Option<std::string>& body = None(),
+    const Option<std::string>& contentType = None());
+
+
+// Asynchronously sends an HTTP POST request to the specified URL and
+// returns the HTTP response.
+Future<Response> post(
+    const URL& url,
+    const Option<hashmap<std::string, std::string>>& headers = None(),
+    const Option<std::string>& body = None(),
+    const Option<std::string>& contentType = None());
+
+
 // Asynchronously sends an HTTP GET request to the process with the
 // given UPID and returns the HTTP response from the process.
 Future<Response> get(

http://git-wip-us.apache.org/repos/asf/mesos/blob/853bd8f8/3rdparty/libprocess/src/http.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/http.cpp b/3rdparty/libprocess/src/http.cpp
index 30e825d..c18de81 100644
--- a/3rdparty/libprocess/src/http.cpp
+++ b/3rdparty/libprocess/src/http.cpp
@@ -6,6 +6,7 @@
 #include <deque>
 #include <iostream>
 #include <string>
+#include <vector>
 
 #include <process/future.hpp>
 #include <process/http.hpp>
@@ -21,6 +22,7 @@
 
 using std::deque;
 using std::string;
+using std::vector;
 
 using process::http::Request;
 using process::http::Response;
@@ -28,7 +30,6 @@ using process::http::Response;
 using process::network::Socket;
 
 namespace process {
-
 namespace http {
 
 hashmap<uint16_t, string> statuses;
@@ -111,24 +112,25 @@ Future<Response> decode(const string& buffer)
 // Forward declaration.
 Future<Response> _request(
     Socket socket,
-    const UPID& upid,
+    const Node& node,
+    const URL& url,
     const string& method,
-    const Option<string>& path,
-    const Option<string>& query,
-    const Option<hashmap<string, string> >& _headers,
+    const Option<hashmap<string, string>>& _headers,
     const Option<string>& body,
     const Option<string>& contentType);
 
 
 Future<Response> request(
-    const UPID& upid,
+    const URL& url,
     const string& method,
-    const Option<string>& path,
-    const Option<string>& query,
-    const Option<hashmap<string, string> >& headers,
+    const Option<hashmap<string, string>>& headers,
     const Option<string>& body,
     const Option<string>& contentType)
 {
+  if (url.scheme != "http") {
+    return Failure("Unsupported URL scheme");
+  }
+
   Try<Socket> create = Socket::create();
 
   if (create.isError()) {
@@ -137,13 +139,31 @@ Future<Response> request(
 
   Socket socket = create.get();
 
-  return socket.connect(upid.node)
+  Node node;
+
+  if (url.ip.isSome()) {
+    node.ip = url.ip.get().address();
+  } else if (url.domain.isNone()) {
+    return Failure("Missing URL domain or IP");
+  } else {
+    Try<uint32_t> ip = net::getIP(url.domain.get(), AF_INET);
+
+    if (ip.isError()) {
+      return Failure("Failed to determine IP of domain '" +
+                     url.domain.get() + "': " + ip.error());
+    }
+
+    node.ip = ip.get();
+  }
+
+  node.port = url.port;
+
+  return socket.connect(node)
     .then(lambda::bind(&_request,
                        socket,
-                       upid,
+                       node,
+                       url,
                        method,
-                       path,
-                       query,
                        headers,
                        body,
                        contentType));
@@ -152,24 +172,30 @@ Future<Response> request(
 
 Future<Response> _request(
     Socket socket,
-    const UPID& upid,
+    const Node& node,
+    const URL& url,
     const string& method,
-    const Option<string>& path,
-    const Option<string>& query,
-    const Option<hashmap<string, string> >& _headers,
+    const Option<hashmap<string, string>>& _headers,
     const Option<string>& body,
     const Option<string>& contentType)
 {
   std::ostringstream out;
 
-  out << method << " /" << upid.id;
+  out << method << " /" << strings::remove(url.path, "/", strings::PREFIX);
 
-  if (path.isSome()) {
-    out << "/" << path.get();
+  if (!url.query.empty()) {
+    // Convert the query to a string that we join via '=' and '&'.
+    vector<string> query;
+
+    foreachpair (const string& key, const string& value, url.query) {
+      query.push_back(key + "=" + value);
+    }
+
+    out << "?" << strings::join("&", query);
   }
 
-  if (query.isSome()) {
-    out << "?" << query.get();
+  if (url.fragment.isSome()) {
+    out << "#" << url.fragment.get();
   }
 
   out << " HTTP/1.1\r\n";
@@ -182,7 +208,7 @@ Future<Response> _request(
   }
 
   // Need to specify the 'Host' header.
-  headers["Host"] = stringify(upid.node);
+  headers["Host"] = stringify(node);
 
   // Tell the server to close the connection when it's done.
   headers["Connection"] = "close";
@@ -220,17 +246,52 @@ Future<Response> _request(
     .then(lambda::bind(&internal::decode, lambda::_1));
 }
 
-
 } // namespace internal {
 
 
 Future<Response> get(
+    const URL& url,
+    const Option<hashmap<string, string>>& headers)
+{
+  return internal::request(url, "GET", headers, None(), None());
+}
+
+
+Future<Response> put(
+    const URL& url,
+    const Option<hashmap<string, string>>& headers,
+    const Option<string>& body,
+    const Option<string>& contentType)
+{
+  if (body.isNone() && contentType.isSome()) {
+    return Failure("Attempted to do a PUT with a Content-Type but no body");
+  }
+
+  return internal::request(url, "PUT", headers, body, contentType);
+}
+
+
+Future<Response> post(
+    const URL& url,
+    const Option<hashmap<string, string>>& headers,
+    const Option<string>& body,
+    const Option<string>& contentType)
+{
+  if (body.isNone() && contentType.isSome()) {
+    return Failure("Attempted to do a POST with a Content-Type but no body");
+  }
+
+  return internal::request(url, "POST", headers, body, contentType);
+}
+
+
+Future<Response> get(
     const UPID& upid,
     const Option<string>& path,
     const Option<string>& query,
-    const Option<hashmap<string, string> >& headers)
+    const Option<hashmap<string, string>>& headers)
 {
-  URL url("http", net::IP(upid.address.ip), upid.address.port, upid.id);
+  URL url("http", net::IP(upid.node.ip), upid.node.port, upid.id);
 
   if (path.isSome()) {
     // TODO(benh): Get 'query' and/or 'fragment' out of 'path'.
@@ -255,16 +316,18 @@ Future<Response> get(
 Future<Response> post(
     const UPID& upid,
     const Option<string>& path,
-    const Option<hashmap<string, string> >& headers,
+    const Option<hashmap<string, string>>& headers,
     const Option<string>& body,
     const Option<string>& contentType)
 {
-  if (body.isNone() && contentType.isSome()) {
-    return Failure("Attempted to do a POST with a Content-Type but no body");
+  URL url("http", net::IP(upid.node.ip), upid.node.port, upid.id);
+
+  if (path.isSome()) {
+    // TODO(benh): Get 'query' and/or 'fragment' out of 'path'.
+    url.path = strings::join("/", url.path, path.get());
   }
 
-  return internal::request(
-      upid, "POST", path, None(), headers, body, contentType);
+  return post(url, headers, body, contentType);
 }
 
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/853bd8f8/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 73949b8..aaa1646 100644
--- a/3rdparty/libprocess/src/tests/http_tests.cpp
+++ b/3rdparty/libprocess/src/tests/http_tests.cpp
@@ -259,7 +259,7 @@ http::Response validateGetWithQuery(const http::Request& request)
   EXPECT_EQ("GET", request.method);
   EXPECT_THAT(request.path, EndsWith("get"));
   EXPECT_EQ("", request.body);
-  EXPECT_EQ("frag", request.fragment);
+  EXPECT_EQ("", request.fragment);
   EXPECT_EQ("bar", request.query.at("foo"));
   EXPECT_EQ(1, request.query.size());
 
@@ -287,7 +287,7 @@ TEST(HTTP, Get)
     .WillOnce(Invoke(validateGetWithQuery));
 
   Future<http::Response> queryFuture =
-    http::get(process.self(), "get", "foo=bar#frag");
+    http::get(process.self(), "get", "foo=bar");
 
   AWAIT_READY(queryFuture);
   ASSERT_EQ(http::statuses[200], queryFuture.get().status);

http://git-wip-us.apache.org/repos/asf/mesos/blob/853bd8f8/3rdparty/libprocess/src/tests/metrics_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/tests/metrics_tests.cpp b/3rdparty/libprocess/src/tests/metrics_tests.cpp
index 0c80c69..f9b2dc0 100644
--- a/3rdparty/libprocess/src/tests/metrics_tests.cpp
+++ b/3rdparty/libprocess/src/tests/metrics_tests.cpp
@@ -229,7 +229,7 @@ TEST(Metrics, SnapshotTimeout)
   // Ensure the timeout parameter is validated.
   AWAIT_EXPECT_RESPONSE_STATUS_EQ(
       BadRequest().status,
-      http::get(upid, "snapshot?timeout=foobar"));
+      http::get(upid, "snapshot", "timeout=foobar"));
 
   // Advance the clock to avoid rate limit.
   Clock::advance(Seconds(1));
@@ -253,7 +253,7 @@ TEST(Metrics, SnapshotTimeout)
   Clock::advance(Seconds(1));
 
   // Get the snapshot.
-  Future<Response> response = http::get(upid, "snapshot?timeout=2secs");
+  Future<Response> response = http::get(upid, "snapshot", "timeout=2secs");
 
   // Make sure the request is pending before the timeout is exceeded.
   Clock::settle();
@@ -296,7 +296,7 @@ TEST(Metrics, SnapshotTimeout)
   // Ensure MetricsProcess has removed the metrics.
   Clock::settle();
 
-  response = http::get(upid, "snapshot?timeout=2secs");
+  response = http::get(upid, "snapshot", "timeout=2secs");
 
   AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response);