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