You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by bm...@apache.org on 2015/09/28 20:27:15 UTC

[01/10] mesos git commit: Updated http::URL to a URI-reference.

Repository: mesos
Updated Branches:
  refs/heads/master bfeb070a2 -> 82fb36ac0


Updated http::URL to a URI-reference.

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


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

Branch: refs/heads/master
Commit: 2fd5ed9ef150524d50a8e79c1a71c6292de68ac3
Parents: b06e932
Author: Benjamin Mahler <be...@gmail.com>
Authored: Thu Sep 17 15:07:59 2015 -0700
Committer: Benjamin Mahler <be...@gmail.com>
Committed: Mon Sep 28 10:38:01 2015 -0700

----------------------------------------------------------------------
 3rdparty/libprocess/include/process/http.hpp |  9 +++--
 3rdparty/libprocess/src/http.cpp             | 41 ++++++++++++++---------
 2 files changed, 32 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/2fd5ed9e/3rdparty/libprocess/include/process/http.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/http.hpp b/3rdparty/libprocess/include/process/http.hpp
index fbd6cf7..c71efcc 100644
--- a/3rdparty/libprocess/include/process/http.hpp
+++ b/3rdparty/libprocess/include/process/http.hpp
@@ -663,6 +663,10 @@ std::string encode(const hashmap<std::string, std::string>& query);
 
 // Represents a Uniform Resource Locator:
 //   scheme://domain|ip:port/path?query#fragment
+//
+// This is actually a URI-reference (see 4.1 of RFC 3986).
+//
+// TODO(bmahler): The default port should depend on the scheme!
 struct URL
 {
   URL(const std::string& _scheme,
@@ -693,11 +697,12 @@ struct URL
       query(_query),
       fragment(_fragment) {}
 
-  std::string scheme;
+  Option<std::string> scheme;
+
   // TODO(benh): Consider using unrestricted union for 'domain' and 'ip'.
   Option<std::string> domain;
   Option<net::IP> ip;
-  uint16_t port;
+  Option<uint16_t> port;
   std::string path;
   hashmap<std::string, std::string> query;
   Option<std::string> fragment;

http://git-wip-us.apache.org/repos/asf/mesos/blob/2fd5ed9e/3rdparty/libprocess/src/http.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/http.cpp b/3rdparty/libprocess/src/http.cpp
index 9ad613a..b4ab772 100644
--- a/3rdparty/libprocess/src/http.cpp
+++ b/3rdparty/libprocess/src/http.cpp
@@ -595,7 +595,9 @@ std::string encode(const hashmap<std::string, std::string>& query)
 
 ostream& operator<<(ostream& stream, const URL& url)
 {
-  stream << url.scheme << "://";
+  if (url.scheme.isSome()) {
+    stream << url.scheme.get() << "://";
+  }
 
   if (url.domain.isSome()) {
     stream << url.domain.get();
@@ -603,7 +605,9 @@ ostream& operator<<(ostream& stream, const URL& url)
     stream << url.ip.get();
   }
 
-  stream << ":" << url.port;
+  if (url.port.isSome()) {
+    stream << ":" << url.port.get();
+  }
 
   stream << "/" << strings::remove(url.path, "/", strings::PREFIX);
 
@@ -771,32 +775,33 @@ Future<Response> request(
     const Option<string>& body,
     const Option<string>& contentType)
 {
-  auto create = [&url]() -> Try<Socket> {
-    if (url.scheme == "http") {
+  Try<Socket> socket = [&url]() -> Try<Socket> {
+    // Default to 'http' if no scheme was specified.
+    if (url.scheme.isNone() || url.scheme == string("http")) {
       return Socket::create(Socket::POLL);
     }
 
+    if (url.scheme == string("https")) {
 #ifdef USE_SSL_SOCKET
-    if (url.scheme == "https") {
       return Socket::create(Socket::SSL);
-    }
+#else
+      return Error("'https' scheme requires SSL enabled");
 #endif
+    }
 
     return Error("Unsupported URL scheme");
   }();
 
-  if (create.isError()) {
-    return Failure("Failed to create socket: " + create.error());
+  if (socket.isError()) {
+    return Failure("Failed to create socket: " + socket.error());
   }
 
-  Socket socket = create.get();
-
   Address address;
 
   if (url.ip.isSome()) {
     address.ip = url.ip.get();
   } else if (url.domain.isNone()) {
-    return Failure("Missing URL domain or IP");
+    return Failure("Expecting url.ip or url.domain to be set");
   } else {
     Try<net::IP> ip = net::getIP(url.domain.get(), AF_INET);
 
@@ -808,11 +813,15 @@ Future<Response> request(
     address.ip = ip.get();
   }
 
-  address.port = url.port;
+  if (url.port.isNone()) {
+    return Failure("Expecting url.port to be set");
+  }
+
+  address.port = url.port.get();
 
-  return socket.connect(address)
+  return socket->connect(address)
     .then(lambda::bind(&_request,
-                       socket,
+                       socket.get(),
                        address,
                        url,
                        method,
@@ -864,11 +873,11 @@ Future<Response> _request(
   // Need to specify the 'Host' header.
   if (url.domain.isSome()) {
     // Use ONLY domain for standard ports.
-    if (url.port == 80 || url.port == 443) {
+    if (url.port.isNone() || url.port == 80 || url.port == 443) {
       headers["Host"] = url.domain.get();
     } else {
       // Add port for non-standard ports.
-      headers["Host"] = url.domain.get() + ":" + stringify(url.port);
+      headers["Host"] = url.domain.get() + ":" + stringify(url.port.get());
     }
   } else {
     headers["Host"] = stringify(address);


[05/10] mesos git commit: Introduced a typedef to make consistent use of case-insentitive http headers easier.

Posted by bm...@apache.org.
Introduced a typedef to make consistent use of case-insentitive http headers easier.

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


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

Branch: refs/heads/master
Commit: bf207e368dcfbf33315dae094e9a91bcd51cc135
Parents: c9d2017
Author: Benjamin Mahler <be...@gmail.com>
Authored: Mon Sep 21 19:55:28 2015 -0700
Committer: Benjamin Mahler <be...@gmail.com>
Committed: Mon Sep 28 10:50:51 2015 -0700

----------------------------------------------------------------------
 3rdparty/libprocess/include/process/http.hpp    | 36 ++++++++++----------
 3rdparty/libprocess/src/http.cpp                | 28 +++++++--------
 3rdparty/libprocess/src/tests/http_tests.cpp    |  4 +--
 3rdparty/libprocess/src/tests/process_tests.cpp |  6 ++--
 4 files changed, 37 insertions(+), 37 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/bf207e36/3rdparty/libprocess/include/process/http.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/http.hpp b/3rdparty/libprocess/include/process/http.hpp
index 5932af4..e32607b 100644
--- a/3rdparty/libprocess/include/process/http.hpp
+++ b/3rdparty/libprocess/include/process/http.hpp
@@ -145,6 +145,12 @@ struct CaseInsensitiveEqual
 };
 
 
+typedef hashmap<std::string,
+                std::string,
+                CaseInsensitiveHash,
+                CaseInsensitiveEqual> Headers;
+
+
 struct Request
 {
   std::string method;
@@ -155,10 +161,7 @@ struct Request
   // For server requests, the URL may be a URI or a relative reference.
   URL url;
 
-  hashmap<std::string,
-          std::string,
-          CaseInsensitiveHash,
-          CaseInsensitiveEqual> headers;
+  Headers headers;
 
   // TODO(bmahler): Add a 'query' field which contains both
   // the URL query and the parsed form data from the body.
@@ -356,10 +359,7 @@ struct Response
   // TODO(benh): Add major/minor version.
   std::string status;
 
-  hashmap<std::string,
-          std::string,
-          CaseInsensitiveHash,
-          CaseInsensitiveEqual> headers;
+  Headers headers;
 
   // Either provide a 'body', an absolute 'path' to a file, or a
   // 'pipe' for streaming a response. Distinguish between the cases
@@ -723,7 +723,7 @@ std::string encode(const hashmap<std::string, std::string>& query);
 // response is received.
 Future<Response> get(
     const URL& url,
-    const Option<hashmap<std::string, std::string>>& headers = None());
+    const Option<Headers>& headers = None());
 
 
 // Asynchronously sends an HTTP GET request to the process with the
@@ -733,7 +733,7 @@ Future<Response> get(
     const UPID& upid,
     const Option<std::string>& path = None(),
     const Option<std::string>& query = None(),
-    const Option<hashmap<std::string, std::string>>& headers = None());
+    const Option<Headers>& headers = None());
 
 
 // Asynchronously sends an HTTP POST request to the specified URL
@@ -741,7 +741,7 @@ Future<Response> get(
 // response is received.
 Future<Response> post(
     const URL& url,
-    const Option<hashmap<std::string, std::string>>& headers = None(),
+    const Option<Headers>& headers = None(),
     const Option<std::string>& body = None(),
     const Option<std::string>& contentType = None());
 
@@ -752,7 +752,7 @@ Future<Response> post(
 Future<Response> post(
     const UPID& upid,
     const Option<std::string>& path = None(),
-    const Option<hashmap<std::string, std::string>>& headers = None(),
+    const Option<Headers>& headers = None(),
     const Option<std::string>& body = None(),
     const Option<std::string>& contentType = None());
 
@@ -767,7 +767,7 @@ Future<Response> post(
  */
 Future<Response> requestDelete(
     const URL& url,
-    const Option<hashmap<std::string, std::string>>& headers = None());
+    const Option<Headers>& headers = None());
 
 
 /**
@@ -783,7 +783,7 @@ Future<Response> requestDelete(
 Future<Response> requestDelete(
     const UPID& upid,
     const Option<std::string>& path = None(),
-    const Option<hashmap<std::string, std::string>>& headers = None());
+    const Option<Headers>& headers = None());
 
 
 namespace streaming {
@@ -794,7 +794,7 @@ namespace streaming {
 // from the Pipe::Reader.
 Future<Response> get(
     const URL& url,
-    const Option<hashmap<std::string, std::string>>& headers = None());
+    const Option<Headers>& headers = None());
 
 // Asynchronously sends an HTTP GET request to the process with the
 // given UPID and returns the HTTP response of type 'PIPE' once the
@@ -804,7 +804,7 @@ Future<Response> get(
     const UPID& upid,
     const Option<std::string>& path = None(),
     const Option<std::string>& query = None(),
-    const Option<hashmap<std::string, std::string>>& headers = None());
+    const Option<Headers>& headers = None());
 
 // Asynchronously sends an HTTP POST request to the specified URL
 // and returns the HTTP response of type 'PIPE' once the response
@@ -812,7 +812,7 @@ Future<Response> get(
 // from the Pipe::Reader.
 Future<Response> post(
     const URL& url,
-    const Option<hashmap<std::string, std::string>>& headers = None(),
+    const Option<Headers>& headers = None(),
     const Option<std::string>& body = None(),
     const Option<std::string>& contentType = None());
 
@@ -823,7 +823,7 @@ Future<Response> post(
 Future<Response> post(
     const UPID& upid,
     const Option<std::string>& path = None(),
-    const Option<hashmap<std::string, std::string>>& headers = None(),
+    const Option<Headers>& headers = None(),
     const Option<std::string>& body = None(),
     const Option<std::string>& contentType = None());
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/bf207e36/3rdparty/libprocess/src/http.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/http.cpp b/3rdparty/libprocess/src/http.cpp
index b4ab772..c93e7e0 100644
--- a/3rdparty/libprocess/src/http.cpp
+++ b/3rdparty/libprocess/src/http.cpp
@@ -762,7 +762,7 @@ Future<Response> _request(
     const URL& url,
     const string& method,
     bool streamingResponse,
-    const Option<hashmap<string, string>>& _headers,
+    const Option<Headers>& _headers,
     const Option<string>& body,
     const Option<string>& contentType);
 
@@ -771,7 +771,7 @@ Future<Response> request(
     const URL& url,
     const string& method,
     bool streamedResponse,
-    const Option<hashmap<string, string>>& headers,
+    const Option<Headers>& headers,
     const Option<string>& body,
     const Option<string>& contentType)
 {
@@ -838,7 +838,7 @@ Future<Response> _request(
     const URL& url,
     const string& method,
     bool streamedResponse,
-    const Option<hashmap<string, string>>& _headers,
+    const Option<Headers>& _headers,
     const Option<string>& body,
     const Option<string>& contentType)
 {
@@ -864,7 +864,7 @@ Future<Response> _request(
   out << " HTTP/1.1\r\n";
 
   // Set up the headers as necessary.
-  hashmap<string, string> headers;
+  Headers headers;
 
   if (_headers.isSome()) {
     headers = _headers.get();
@@ -937,7 +937,7 @@ Future<Response> _request(
 
 Future<Response> get(
     const URL& url,
-    const Option<hashmap<string, string>>& headers)
+    const Option<Headers>& headers)
 {
   return internal::request(url, "GET", false, headers, None(), None());
 }
@@ -947,7 +947,7 @@ Future<Response> get(
     const UPID& upid,
     const Option<string>& path,
     const Option<string>& query,
-    const Option<hashmap<string, string>>& headers)
+    const Option<Headers>& headers)
 {
   URL url("http", net::IP(upid.address.ip), upid.address.port, upid.id);
 
@@ -973,7 +973,7 @@ Future<Response> get(
 
 Future<Response> post(
     const URL& url,
-    const Option<hashmap<string, string>>& headers,
+    const Option<Headers>& headers,
     const Option<string>& body,
     const Option<string>& contentType)
 {
@@ -988,7 +988,7 @@ Future<Response> post(
 Future<Response> post(
     const UPID& upid,
     const Option<string>& path,
-    const Option<hashmap<string, string>>& headers,
+    const Option<Headers>& headers,
     const Option<string>& body,
     const Option<string>& contentType)
 {
@@ -1005,7 +1005,7 @@ Future<Response> post(
 
 Future<Response> requestDelete(
     const URL& url,
-    const Option<hashmap<string, string>>& headers)
+    const Option<Headers>& headers)
 {
   return internal::request(url, "DELETE", false, headers, None(), None());
 }
@@ -1014,7 +1014,7 @@ Future<Response> requestDelete(
 Future<Response> requestDelete(
     const UPID& upid,
     const Option<string>& path,
-    const Option<hashmap<string, string>>& headers)
+    const Option<Headers>& headers)
 {
   URL url("http", net::IP(upid.address.ip), upid.address.port, upid.id);
 
@@ -1033,7 +1033,7 @@ namespace streaming {
 
 Future<Response> get(
     const URL& url,
-    const Option<hashmap<string, string>>& headers)
+    const Option<Headers>& headers)
 {
   return internal::request(url, "GET", true, headers, None(), None());
 }
@@ -1043,7 +1043,7 @@ Future<Response> get(
     const UPID& upid,
     const Option<string>& path,
     const Option<string>& query,
-    const Option<hashmap<string, string>>& headers)
+    const Option<Headers>& headers)
 {
   URL url("http", net::IP(upid.address.ip), upid.address.port, upid.id);
 
@@ -1069,7 +1069,7 @@ Future<Response> get(
 
 Future<Response> post(
     const URL& url,
-    const Option<hashmap<string, string>>& headers,
+    const Option<Headers>& headers,
     const Option<string>& body,
     const Option<string>& contentType)
 {
@@ -1084,7 +1084,7 @@ Future<Response> post(
 Future<Response> post(
     const UPID& upid,
     const Option<string>& path,
-    const Option<hashmap<string, string>>& headers,
+    const Option<Headers>& headers,
     const Option<string>& body,
     const Option<string>& contentType)
 {

http://git-wip-us.apache.org/repos/asf/mesos/blob/bf207e36/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 a52561e..c380f35 100644
--- a/3rdparty/libprocess/src/tests/http_tests.cpp
+++ b/3rdparty/libprocess/src/tests/http_tests.cpp
@@ -127,7 +127,7 @@ TEST(HTTPTest, Auth)
                  noAuthFuture.get().headers.get("WWW-authenticate"));
 
   // Now test passing wrong auth header.
-  hashmap<string, string> headers;
+  http::Headers headers;
   headers["Authorization"] = "Basic " + base64::encode("testuser:wrongpass");
 
   Future<http::Response> wrongAuthFuture =
@@ -606,7 +606,7 @@ TEST(HTTPTest, Post)
   ASSERT_EQ(http::statuses[200], future.get().status);
 
   // Now test passing headers instead.
-  hashmap<string, string> headers;
+  http::Headers headers;
   headers["Content-Type"] = "text/plain";
 
   EXPECT_CALL(*http.process, post(_))

http://git-wip-us.apache.org/repos/asf/mesos/blob/bf207e36/3rdparty/libprocess/src/tests/process_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/tests/process_tests.cpp b/3rdparty/libprocess/src/tests/process_tests.cpp
index 1023500..ffd260a 100644
--- a/3rdparty/libprocess/src/tests/process_tests.cpp
+++ b/3rdparty/libprocess/src/tests/process_tests.cpp
@@ -1371,7 +1371,7 @@ TEST(ProcessTest, Http1)
     .WillOnce(DoAll(FutureArg<0>(&pid),
                     FutureArg<1>(&body)));
 
-  hashmap<string, string> headers;
+  http::Headers headers;
   headers["User-Agent"] = "libprocess/";
 
   Future<http::Response> response =
@@ -1419,7 +1419,7 @@ TEST(ProcessTest, Http2)
     .WillOnce(DoAll(FutureArg<0>(&pid),
                     FutureArg<1>(&body)));
 
-  hashmap<string, string> headers;
+  http::Headers headers;
   headers["Libprocess-From"] = stringify(from);
 
   Future<http::Response> response =
@@ -1745,7 +1745,7 @@ TEST(ProcessTest, PercentEncodedURLs)
   EXPECT_CALL(process, handler1(_, _))
     .WillOnce(FutureSatisfy(&handler1));
 
-  hashmap<string, string> headers;
+  http::Headers headers;
   headers["User-Agent"] = "libprocess/";
 
   Future<http::Response> response = http::post(pid, "handler1", headers);


[08/10] mesos git commit: Improved streaming decoder tests by checking the failed state.

Posted by bm...@apache.org.
Improved streaming decoder tests by checking the failed state.

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


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

Branch: refs/heads/master
Commit: 82fb36ac0b68eea0488aae1bca21b9a880b1e25e
Parents: 2bc6a19
Author: Benjamin Mahler <be...@gmail.com>
Authored: Mon Sep 21 11:26:54 2015 -0700
Committer: Benjamin Mahler <be...@gmail.com>
Committed: Mon Sep 28 11:09:55 2015 -0700

----------------------------------------------------------------------
 3rdparty/libprocess/src/tests/decoder_tests.cpp | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/82fb36ac/3rdparty/libprocess/src/tests/decoder_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/tests/decoder_tests.cpp b/3rdparty/libprocess/src/tests/decoder_tests.cpp
index 76eb80f..ab33126 100644
--- a/3rdparty/libprocess/src/tests/decoder_tests.cpp
+++ b/3rdparty/libprocess/src/tests/decoder_tests.cpp
@@ -162,7 +162,7 @@ TEST(DecoderTest, StreamingResponse)
   const string body = "hi";
 
   deque<Response*> responses = decoder.decode(headers.data(), headers.length());
-  ASSERT_FALSE(decoder.failed());
+  EXPECT_FALSE(decoder.failed());
   ASSERT_EQ(1, responses.size());
 
   Response* response = responses[0];
@@ -178,9 +178,11 @@ TEST(DecoderTest, StreamingResponse)
   EXPECT_TRUE(read.isPending());
 
   decoder.decode(body.data(), body.length());
+  EXPECT_FALSE(decoder.failed());
 
   // Feeding EOF to the decoder should be ok.
   decoder.decode("", 0);
+  EXPECT_FALSE(decoder.failed());
 
   EXPECT_TRUE(read.isReady());
   EXPECT_EQ("hi", read.get());
@@ -207,9 +209,9 @@ TEST(DecoderTest, StreamingResponseFailure)
   const string body = "1";
 
   deque<Response*> responses = decoder.decode(headers.data(), headers.length());
-  ASSERT_FALSE(decoder.failed());
-  ASSERT_EQ(1, responses.size());
+  EXPECT_FALSE(decoder.failed());
 
+  ASSERT_EQ(1, responses.size());
   Response* response = responses[0];
 
   EXPECT_EQ("200 OK", response->status);
@@ -223,6 +225,7 @@ TEST(DecoderTest, StreamingResponseFailure)
   EXPECT_TRUE(read.isPending());
 
   decoder.decode(body.data(), body.length());
+  EXPECT_FALSE(decoder.failed());
 
   EXPECT_TRUE(read.isReady());
   EXPECT_EQ("1", read.get());
@@ -233,6 +236,7 @@ TEST(DecoderTest, StreamingResponseFailure)
 
   // Feeding EOF to the decoder should trigger a failure!
   decoder.decode("", 0);
+  EXPECT_TRUE(decoder.failed());
 
   EXPECT_TRUE(read.isFailed());
   EXPECT_EQ("failed to decode body", read.failure());


[06/10] mesos git commit: Consistent use of case insensitive keys for HTTP headers.

Posted by bm...@apache.org.
Consistent use of case insensitive keys for HTTP headers.

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


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

Branch: refs/heads/master
Commit: 605a8b62796d5f9a7ae52a798ba1f7a08a71742f
Parents: bf207e3
Author: Benjamin Mahler <be...@gmail.com>
Authored: Mon Sep 21 19:55:48 2015 -0700
Committer: Benjamin Mahler <be...@gmail.com>
Committed: Mon Sep 28 11:09:48 2015 -0700

----------------------------------------------------------------------
 src/scheduler/scheduler.cpp                     |  2 +-
 .../provisioner/docker/registry_client.cpp      | 19 +++++++++----------
 src/tests/executor_http_api_tests.cpp           | 14 +++++++-------
 src/tests/http_api_tests.cpp                    | 20 ++++++++++----------
 src/tests/master_maintenance_tests.cpp          |  2 +-
 src/tests/reservation_endpoints_tests.cpp       | 12 ++++++------
 src/tests/teardown_tests.cpp                    | 10 +++++-----
 7 files changed, 39 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/605a8b62/src/scheduler/scheduler.cpp
----------------------------------------------------------------------
diff --git a/src/scheduler/scheduler.cpp b/src/scheduler/scheduler.cpp
index ee146eb..56801ca 100644
--- a/src/scheduler/scheduler.cpp
+++ b/src/scheduler/scheduler.cpp
@@ -306,7 +306,7 @@ protected:
     // the scheduler driver does.
 
     const string body = serialize(contentType, call);
-    const hashmap<string, string> headers{{"Accept", stringify(contentType)}};
+    const http::Headers headers{{"Accept", stringify(contentType)}};
 
     Future<Response> response;
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/605a8b62/src/slave/containerizer/provisioner/docker/registry_client.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/provisioner/docker/registry_client.cpp b/src/slave/containerizer/provisioner/docker/registry_client.cpp
index 0a96631..c2040b4 100644
--- a/src/slave/containerizer/provisioner/docker/registry_client.cpp
+++ b/src/slave/containerizer/provisioner/docker/registry_client.cpp
@@ -20,6 +20,7 @@
 
 #include <process/defer.hpp>
 #include <process/dispatch.hpp>
+#include <process/http.hpp>
 #include <process/io.hpp>
 
 #include "slave/containerizer/provisioner/docker/registry_client.hpp"
@@ -81,12 +82,12 @@ private:
 
   Future<Response> doHttpGet(
       const URL& url,
-      const Option<hashmap<string, string>>& headers,
+      const Option<process::http::Headers>& headers,
       const Duration& timeout,
       bool resend,
       const Option<string>& lastResponse) const;
 
-  Try<hashmap<string, string>> getAuthenticationAttributes(
+  Try<process::http::Headers> getAuthenticationAttributes(
       const Response& httpResponse) const;
 
   Owned<TokenManager> tokenManager_;
@@ -197,8 +198,7 @@ RegistryClientProcess::RegistryClientProcess(
     credentials_(creds) {}
 
 
-Try<hashmap<string, string>>
-RegistryClientProcess::getAuthenticationAttributes(
+Try<process::http::Headers> RegistryClientProcess::getAuthenticationAttributes(
     const Response& httpResponse) const
 {
   if (httpResponse.headers.find("WWW-Authenticate") ==
@@ -217,7 +217,7 @@ RegistryClientProcess::getAuthenticationAttributes(
 
   const vector<string> authParams = strings::tokenize(authStringTokens[1], ",");
 
-  hashmap<string, string> authAttributes;
+  process::http::Headers authAttributes;
   auto addAttribute = [&authAttributes](
       const string& param) -> Try<Nothing> {
     const vector<string> paramTokens =
@@ -245,10 +245,9 @@ RegistryClientProcess::getAuthenticationAttributes(
 }
 
 
-Future<Response>
-RegistryClientProcess::doHttpGet(
+Future<Response> RegistryClientProcess::doHttpGet(
     const URL& url,
-    const Option<hashmap<string, string>>& headers,
+    const Option<process::http::Headers>& headers,
     const Duration& timeout,
     bool resend,
     const Option<string>& lastResponseStatus) const
@@ -319,7 +318,7 @@ RegistryClientProcess::doHttpGet(
 
       // Handle 401 Unauthorized.
       if (httpResponse.status == "401 Unauthorized") {
-        Try<hashmap<string, string>> authAttributes =
+        Try<process::http::Headers> authAttributes =
           getAuthenticationAttributes(httpResponse);
 
         if (authAttributes.isError()) {
@@ -343,7 +342,7 @@ RegistryClientProcess::doHttpGet(
           .then(defer(self(), [=](
               const Future<Token>& tokenResponse) {
             // Send request with acquired token.
-            hashmap<string, string> authHeaders = {
+            process::http::Headers authHeaders = {
               {"Authorization", "Bearer " + tokenResponse.get().raw}
             };
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/605a8b62/src/tests/executor_http_api_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/executor_http_api_tests.cpp b/src/tests/executor_http_api_tests.cpp
index c2c05f4..31938c2 100644
--- a/src/tests/executor_http_api_tests.cpp
+++ b/src/tests/executor_http_api_tests.cpp
@@ -139,7 +139,7 @@ TEST_F(ExecutorHttpApiTest, ValidJsonButInvalidProtobuf)
   JSON::Object object;
   object.values["string"] = "valid_json";
 
-  hashmap<string, string> headers;
+  process::http::Headers headers;
   headers["Accept"] = APPLICATION_JSON;
 
   Future<Response> response = process::http::post(
@@ -176,7 +176,7 @@ TEST_P(ExecutorHttpApiTest, MalformedContent)
   const string body = "MALFORMED_CONTENT";
 
   const ContentType contentType = GetParam();
-  hashmap<string, string> headers;
+  process::http::Headers headers;
   headers["Accept"] = stringify(contentType);
 
   Future<Response> response = process::http::post(
@@ -211,7 +211,7 @@ TEST_P(ExecutorHttpApiTest, UnsupportedContentMediaType)
   Clock::settle();
 
   ContentType contentType = GetParam();
-  hashmap<string, string> headers;
+  process::http::Headers headers;
   headers["Accept"] = stringify(contentType);
 
   Call call;
@@ -254,7 +254,7 @@ TEST_P(ExecutorHttpApiTest, MessageFromUnknownFramework)
   Clock::settle();
 
   ContentType contentType = GetParam();
-  hashmap<string, string> headers;
+  process::http::Headers headers;
   headers["Accept"] = stringify(contentType);
 
   Call call;
@@ -325,7 +325,7 @@ TEST_P(ExecutorHttpApiTest, DefaultAccept)
   Clock::pause();
   Clock::settle();
 
-  hashmap<string, string> headers;
+  process::http::Headers headers;
   headers["Accept"] = "*/*";
 
   // Only subscribe needs to 'Accept' JSON or protobuf.
@@ -376,7 +376,7 @@ TEST_P(ExecutorHttpApiTest, NoAcceptHeader)
 
   // No 'Accept' header leads to all media types considered
   // acceptable. JSON will be chosen by default.
-  hashmap<string, string> headers;
+  process::http::Headers headers;
 
   // Only subscribe needs to 'Accept' JSON or protobuf.
   Call call;
@@ -420,7 +420,7 @@ TEST_P(ExecutorHttpApiTest, NotAcceptable)
   // Retrieve the parameter passed as content type to this test.
   const ContentType contentType = GetParam();
 
-  hashmap<string, string> headers;
+  process::http::Headers headers;
   headers["Accept"] = "foo";
 
   // Only subscribe needs to 'Accept' JSON or protobuf.

http://git-wip-us.apache.org/repos/asf/mesos/blob/605a8b62/src/tests/http_api_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/http_api_tests.cpp b/src/tests/http_api_tests.cpp
index 7938bbb..df87afe 100644
--- a/src/tests/http_api_tests.cpp
+++ b/src/tests/http_api_tests.cpp
@@ -181,7 +181,7 @@ TEST_F(HttpApiTest, ValidJsonButInvalidProtobuf)
   JSON::Object object;
   object.values["string"] = "valid_json";
 
-  hashmap<string, string> headers;
+  process::http::Headers headers;
   headers["Accept"] = APPLICATION_JSON;
 
   Future<Response> response = process::http::post(
@@ -209,7 +209,7 @@ TEST_P(HttpApiTest, MalformedContent)
   const string body = "MALFORMED_CONTENT";
 
   const string contentType = GetParam();
-  hashmap<string, string> headers;
+  process::http::Headers headers;
   headers["Accept"] = contentType;
 
   Future<Response> response = process::http::post(
@@ -235,7 +235,7 @@ TEST_P(HttpApiTest, UnsupportedContentMediaType)
   ASSERT_SOME(master);
 
   const string contentType = GetParam();
-  hashmap<string, string> headers;
+  process::http::Headers headers;
   headers["Accept"] = contentType;
 
   Call call;
@@ -277,7 +277,7 @@ TEST_P(HttpApiTest, Subscribe)
 
   // Retrieve the parameter passed as content type to this test.
   const string contentType = GetParam();
-  hashmap<string, string> headers;
+  process::http::Headers headers;
   headers["Accept"] = contentType;
 
   Future<Response> response = process::http::streaming::post(
@@ -347,7 +347,7 @@ TEST_P(HttpApiTest, SubscribedOnRetryWithForce)
 
   // Retrieve the parameter passed as content type to this test.
   const string contentType = GetParam();
-  hashmap<string, string> headers;
+  process::http::Headers headers;
   headers["Accept"] = contentType;
 
   auto deserializer =
@@ -472,7 +472,7 @@ TEST_P(HttpApiTest, UpdatePidToHttpScheduler)
 
   // Retrieve the parameter passed as content type to this test.
   const string contentType = GetParam();
-  hashmap<string, string> headers;
+  process::http::Headers headers;
   headers["Accept"] = contentType;
 
   Future<Response> response = process::http::streaming::post(
@@ -559,7 +559,7 @@ TEST_P(HttpApiTest, UpdatePidToHttpSchedulerWithoutForce)
 
   // Retrieve the parameter passed as content type to this test.
   const string contentType = GetParam();
-  hashmap<string, string> headers;
+  process::http::Headers headers;
   headers["Accept"] = contentType;
 
   Future<Response> response = process::http::streaming::post(
@@ -618,7 +618,7 @@ TEST_P(HttpApiTest, NotAcceptable)
   // Retrieve the parameter passed as content type to this test.
   const string contentType = GetParam();
 
-  hashmap<string, string> headers;
+  process::http::Headers headers;
   headers["Accept"] = "foo";
 
   // Only subscribe needs to 'Accept' json or protobuf.
@@ -653,7 +653,7 @@ TEST_P(HttpApiTest, NoAcceptHeader)
 
   // No 'Accept' header leads to all media types considered
   // acceptable. JSON will be chosen by default.
-  hashmap<string, string> headers;
+  process::http::Headers headers;
 
   // Only subscribe needs to 'Accept' json or protobuf.
   Call call;
@@ -683,7 +683,7 @@ TEST_P(HttpApiTest, DefaultAccept)
   Try<PID<Master> > master = StartMaster(flags);
   ASSERT_SOME(master);
 
-  hashmap<string, string> headers;
+  process::http::Headers headers;
   headers["Accept"] = "*/*";
 
   // Only subscribe needs to 'Accept' json or protobuf.

http://git-wip-us.apache.org/repos/asf/mesos/blob/605a8b62/src/tests/master_maintenance_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_maintenance_tests.cpp b/src/tests/master_maintenance_tests.cpp
index 89ad138..e89ce3b 100644
--- a/src/tests/master_maintenance_tests.cpp
+++ b/src/tests/master_maintenance_tests.cpp
@@ -139,7 +139,7 @@ public:
   }
 
   // Default headers for all POST's to maintenance endpoints.
-  hashmap<string, string> headers;
+  process::http::Headers headers;
 
   const string maintenanceHostname = "maintenance-host";
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/605a8b62/src/tests/reservation_endpoints_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/reservation_endpoints_tests.cpp b/src/tests/reservation_endpoints_tests.cpp
index 398a2e1..d411852 100644
--- a/src/tests/reservation_endpoints_tests.cpp
+++ b/src/tests/reservation_endpoints_tests.cpp
@@ -103,10 +103,10 @@ public:
     return info;
   }
 
-  hashmap<string, string> createBasicAuthHeaders(
+  process::http::Headers createBasicAuthHeaders(
       const Credential& credential) const
   {
-    return hashmap<string, string>{{
+    return process::http::Headers{{
       "Authorization",
       "Basic " +
         base64::encode(credential.principal() + ":" + credential.secret())
@@ -698,7 +698,7 @@ TEST_F(ReservationEndpointsTest, InsufficientResources)
       frameworkInfo.role(),
       createReservationInfo(DEFAULT_CREDENTIAL.principal()));
 
-  hashmap<string, string> headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL);
+  process::http::Headers headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL);
   string body = createRequestBody(slaveId.get(), dynamicallyReserved);
 
   Future<Response> response =
@@ -791,7 +791,7 @@ TEST_F(ReservationEndpointsTest, BadCredentials)
   Resources dynamicallyReserved = unreserved.flatten(
       "role", createReservationInfo(DEFAULT_CREDENTIAL.principal()));
 
-  hashmap<string, string> headers = createBasicAuthHeaders(credential);
+  process::http::Headers headers = createBasicAuthHeaders(credential);
   string body = createRequestBody(slaveId.get(), dynamicallyReserved);
 
   Future<Response> response =
@@ -825,7 +825,7 @@ TEST_F(ReservationEndpointsTest, NoSlaveId)
   Resources dynamicallyReserved = unreserved.flatten(
       "role", createReservationInfo(DEFAULT_CREDENTIAL.principal()));
 
-  hashmap<string, string> headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL);
+  process::http::Headers headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL);
   string body = "resources=" + stringify(toJSONArray(dynamicallyReserved));
 
   Future<Response> response =
@@ -860,7 +860,7 @@ TEST_F(ReservationEndpointsTest, NoResources)
   Try<PID<Slave>> slave = StartSlave();
   ASSERT_SOME(slave);
 
-  hashmap<string, string> headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL);
+  process::http::Headers headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL);
   string body = "slaveId=" + slaveId.get().value();
 
   Future<Response> response =

http://git-wip-us.apache.org/repos/asf/mesos/blob/605a8b62/src/tests/teardown_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/teardown_tests.cpp b/src/tests/teardown_tests.cpp
index daf748c..2eeead7 100644
--- a/src/tests/teardown_tests.cpp
+++ b/src/tests/teardown_tests.cpp
@@ -85,7 +85,7 @@ TEST_F(TeardownTest, TeardownEndpoint)
 
   AWAIT_READY(frameworkId);
 
-  hashmap<string, string> headers;
+  process::http::Headers headers;
   headers["Authorization"] = "Basic " +
     base64::encode(DEFAULT_CREDENTIAL.principal() +
                    ":" + DEFAULT_CREDENTIAL.secret());
@@ -124,7 +124,7 @@ TEST_F(TeardownTest, TeardownEndpointBadCredentials)
 
   AWAIT_READY(frameworkId);
 
-  hashmap<string, string> headers;
+  process::http::Headers headers;
   headers["Authorization"] = "Basic " +
     base64::encode("badPrincipal:badSecret");
 
@@ -174,7 +174,7 @@ TEST_F(TeardownTest, TeardownEndpointGoodACLs)
 
   AWAIT_READY(frameworkId);
 
-  hashmap<string, string> headers;
+  process::http::Headers headers;
   headers["Authorization"] = "Basic " +
     base64::encode(DEFAULT_CREDENTIAL.principal() +
                    ":" + DEFAULT_CREDENTIAL.secret());
@@ -222,7 +222,7 @@ TEST_F(TeardownTest, TeardownEndpointBadACLs)
 
   AWAIT_READY(frameworkId);
 
-  hashmap<string, string> headers;
+  process::http::Headers headers;
   headers["Authorization"] = "Basic " +
     base64::encode(DEFAULT_CREDENTIAL.principal() +
                    ":" + DEFAULT_CREDENTIAL.secret());
@@ -262,7 +262,7 @@ TEST_F(TeardownTest, TeardownEndpointNoFrameworkId)
   ASSERT_EQ(DRIVER_RUNNING, driver.start());
 
   AWAIT_READY(frameworkId);
-  hashmap<string, string> headers;
+  process::http::Headers headers;
   headers["Authorization"] = "Basic " +
     base64::encode("badPrincipal:badSecret");
   Future<Response> response =


[02/10] mesos git commit: Removed implicit logging from Socket::shutdown in favor of returning a Try.

Posted by bm...@apache.org.
Removed implicit logging from Socket::shutdown in favor of returning a Try.

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


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

Branch: refs/heads/master
Commit: b06e932a036044c54cd72ddde1d26c5f9271ea51
Parents: bfeb070
Author: Benjamin Mahler <be...@gmail.com>
Authored: Mon Sep 21 11:18:06 2015 -0700
Committer: Benjamin Mahler <be...@gmail.com>
Committed: Mon Sep 28 10:38:01 2015 -0700

----------------------------------------------------------------------
 3rdparty/libprocess/include/process/socket.hpp  | 10 ++++++----
 3rdparty/libprocess/src/libevent_ssl_socket.cpp |  7 +++++--
 3rdparty/libprocess/src/libevent_ssl_socket.hpp |  2 +-
 3rdparty/libprocess/src/process.cpp             | 14 ++++++++++++--
 4 files changed, 24 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/b06e932a/3rdparty/libprocess/include/process/socket.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/socket.hpp b/3rdparty/libprocess/include/process/socket.hpp
index a677e29..817cb37 100644
--- a/3rdparty/libprocess/include/process/socket.hpp
+++ b/3rdparty/libprocess/include/process/socket.hpp
@@ -168,11 +168,13 @@ public:
     // enabling reuse of a pool of preallocated strings/buffers.
     virtual Future<Nothing> send(const std::string& data);
 
-    virtual void shutdown()
+    virtual Try<Nothing> shutdown()
     {
       if (::shutdown(s, SHUT_RD) < 0) {
-        PLOG(ERROR) << "Shutdown failed on fd=" << s;
+        return ErrnoError();
       }
+
+      return Nothing();
     }
 
     virtual Socket::Kind kind() const = 0;
@@ -291,9 +293,9 @@ public:
     return impl->send(data);
   }
 
-  void shutdown()
+  Try<Nothing> shutdown()
   {
-    impl->shutdown();
+    return impl->shutdown();
   }
 
 private:

http://git-wip-us.apache.org/repos/asf/mesos/blob/b06e932a/3rdparty/libprocess/src/libevent_ssl_socket.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/libevent_ssl_socket.cpp b/3rdparty/libprocess/src/libevent_ssl_socket.cpp
index 80db6e8..52ae802 100644
--- a/3rdparty/libprocess/src/libevent_ssl_socket.cpp
+++ b/3rdparty/libprocess/src/libevent_ssl_socket.cpp
@@ -155,7 +155,7 @@ void LibeventSSLSocketImpl::initialize()
 }
 
 
-void LibeventSSLSocketImpl::shutdown()
+Try<Nothing> LibeventSSLSocketImpl::shutdown()
 {
   // Nothing to do if this socket was never initialized.
   synchronized (lock) {
@@ -166,7 +166,8 @@ void LibeventSSLSocketImpl::shutdown()
       CHECK(recv_request.get() == NULL);
       CHECK(send_request.get() == NULL);
 
-      return;
+      errno = ENOTCONN;
+      return ErrnoError();
     }
   }
 
@@ -200,6 +201,8 @@ void LibeventSSLSocketImpl::shutdown()
         }
       },
       DISALLOW_SHORT_CIRCUIT);
+
+  return Nothing();
 }
 
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/b06e932a/3rdparty/libprocess/src/libevent_ssl_socket.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/libevent_ssl_socket.hpp b/3rdparty/libprocess/src/libevent_ssl_socket.hpp
index 3b17fa2..dc54c74 100644
--- a/3rdparty/libprocess/src/libevent_ssl_socket.hpp
+++ b/3rdparty/libprocess/src/libevent_ssl_socket.hpp
@@ -53,7 +53,7 @@ public:
   // This call is used to do the equivalent of shutting down the read
   // end. This means finishing the future of any outstanding read
   // request.
-  virtual void shutdown();
+  virtual Try<Nothing> shutdown();
 
   // We need a post-initializer because 'shared_from_this()' is not
   // valid until the constructor has finished.

http://git-wip-us.apache.org/repos/asf/mesos/blob/b06e932a/3rdparty/libprocess/src/process.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/process.cpp b/3rdparty/libprocess/src/process.cpp
index c03fba4..7a2b911 100644
--- a/3rdparty/libprocess/src/process.cpp
+++ b/3rdparty/libprocess/src/process.cpp
@@ -1821,7 +1821,12 @@ Encoder* SocketManager::next(int s)
           // calling close the termination logic is not run twice.
           Socket* socket = iterator->second;
           sockets.erase(iterator);
-          socket->shutdown();
+
+          Try<Nothing> shutdown = socket->shutdown();
+          if (shutdown.isError()) {
+            LOG(ERROR) << "Failed to shutdown socket with fd " << socket->get()
+                       << ": " << shutdown.error();
+          }
 
           delete socket;
         }
@@ -1901,7 +1906,12 @@ void SocketManager::close(int s)
       // termination logic is not run twice.
       Socket* socket = iterator->second;
       sockets.erase(iterator);
-      socket->shutdown();
+
+      Try<Nothing> shutdown = socket->shutdown();
+      if (shutdown.isError()) {
+        LOG(ERROR) << "Failed to shutdown socket with fd " << socket->get()
+                   << ": " << shutdown.error();
+      }
 
       delete socket;
     }


[04/10] mesos git commit: Updates to reflect addition of URL in http::Request.

Posted by bm...@apache.org.
Updates to reflect addition of URL in http::Request.

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


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

Branch: refs/heads/master
Commit: c9d2017c08334346534e035f0ff88802f3716e3e
Parents: d347bf5
Author: Benjamin Mahler <be...@gmail.com>
Authored: Thu Sep 17 16:34:58 2015 -0700
Committer: Benjamin Mahler <be...@gmail.com>
Committed: Mon Sep 28 10:50:51 2015 -0700

----------------------------------------------------------------------
 src/files/files.cpp               | 27 ++++++++++++++++-----------
 src/master/http.cpp               | 22 +++++++++++-----------
 src/master/registrar.cpp          |  2 +-
 src/slave/http.cpp                |  4 ++--
 src/slave/monitor.cpp             |  2 +-
 src/tests/fetcher_cache_tests.cpp |  4 ++--
 6 files changed, 33 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/c9d2017c/src/files/files.cpp
----------------------------------------------------------------------
diff --git a/src/files/files.cpp b/src/files/files.cpp
index 5afe332..08e76b9 100644
--- a/src/files/files.cpp
+++ b/src/files/files.cpp
@@ -214,7 +214,7 @@ const string FilesProcess::BROWSE_HELP = HELP(
 
 Future<Response> FilesProcess::browse(const Request& request)
 {
-  Option<string> path = request.query.get("path");
+  Option<string> path = request.url.query.get("path");
 
   if (!path.isSome() || path.get().empty()) {
     return BadRequest("Expecting 'path=value' in query.\n");
@@ -251,7 +251,7 @@ Future<Response> FilesProcess::browse(const Request& request)
     listing.values.push_back(file);
   }
 
-  return OK(listing, request.query.get("jsonp"));
+  return OK(listing, request.url.query.get("jsonp"));
 }
 
 
@@ -287,7 +287,7 @@ const string FilesProcess::READ_HELP = HELP(
 
 Future<Response> FilesProcess::read(const Request& request)
 {
-  Option<string> path = request.query.get("path");
+  Option<string> path = request.url.query.get("path");
 
   if (!path.isSome() || path.get().empty()) {
     return BadRequest("Expecting 'path=value' in query.\n");
@@ -295,21 +295,26 @@ Future<Response> FilesProcess::read(const Request& request)
 
   off_t offset = -1;
 
-  if (request.query.get("offset").isSome()) {
-    Try<off_t> result = numify<off_t>(request.query.get("offset").get());
+  if (request.url.query.get("offset").isSome()) {
+    Try<off_t> result = numify<off_t>(request.url.query.get("offset").get());
+
     if (result.isError()) {
       return BadRequest("Failed to parse offset: " + result.error() + ".\n");
     }
+
     offset = result.get();
   }
 
   ssize_t length = -1;
 
-  if (request.query.get("length").isSome()) {
-    Try<ssize_t> result = numify<ssize_t>(request.query.get("length").get());
+  if (request.url.query.get("length").isSome()) {
+    Try<ssize_t> result = numify<ssize_t>(
+        request.url.query.get("length").get());
+
     if (result.isError()) {
       return BadRequest("Failed to parse length: " + result.error() + ".\n");
     }
+
     length = result.get();
   }
 
@@ -364,7 +369,7 @@ Future<Response> FilesProcess::read(const Request& request)
     JSON::Object object;
     object.values["offset"] = size;
     object.values["data"] = "";
-    return OK(object, request.query.get("jsonp"));
+    return OK(object, request.url.query.get("jsonp"));
   }
 
   // Seek to the offset we want to read from.
@@ -395,7 +400,7 @@ Future<Response> FilesProcess::read(const Request& request)
         lambda::_1,
         offset,
         data,
-        request.query.get("jsonp")))
+        request.url.query.get("jsonp")))
     .onAny(lambda::bind(&os::close, fd.get()));
 }
 
@@ -414,7 +419,7 @@ const string FilesProcess::DOWNLOAD_HELP = HELP(
 
 Future<Response> FilesProcess::download(const Request& request)
 {
-  Option<string> path = request.query.get("path");
+  Option<string> path = request.url.query.get("path");
 
   if (!path.isSome() || path.get().empty()) {
     return BadRequest("Expecting 'path=value' in query.\n");
@@ -469,7 +474,7 @@ Future<Response> FilesProcess::debug(const Request& request)
   foreachpair (const string& name, const string& path, paths) {
     object.values[name] = path;
   }
-  return OK(object, request.query.get("jsonp"));
+  return OK(object, request.url.query.get("jsonp"));
 }
 
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/c9d2017c/src/master/http.cpp
----------------------------------------------------------------------
diff --git a/src/master/http.cpp b/src/master/http.cpp
index cd37c91..4b9f9ed 100644
--- a/src/master/http.cpp
+++ b/src/master/http.cpp
@@ -333,7 +333,7 @@ void Master::Http::log(const Request& request)
   Option<string> userAgent = request.headers.get("User-Agent");
   Option<string> forwardedFor = request.headers.get("X-Forwarded-For");
 
-  LOG(INFO) << "HTTP " << request.method << " for " << request.path
+  LOG(INFO) << "HTTP " << request.method << " for " << request.url.path
             << " from " << request.client
             << (userAgent.isSome()
                 ? " with User-Agent='" + userAgent.get() + "'"
@@ -780,7 +780,7 @@ Future<Response> Master::Http::slaves(const Request& request) const
   }
 
 
-  return OK(object, request.query.get("jsonp"));
+  return OK(object, request.url.query.get("jsonp"));
 }
 
 
@@ -926,7 +926,7 @@ Future<Response> Master::Http::state(const Request& request) const
     object.values["unregistered_frameworks"] = std::move(array);
   }
 
-  return OK(object, request.query.get("jsonp"));
+  return OK(object, request.url.query.get("jsonp"));
 }
 
 
@@ -1188,7 +1188,7 @@ Future<Response> Master::Http::stateSummary(const Request& request) const
     object.values["frameworks"] = std::move(array);
   }
 
-  return OK(object, request.query.get("jsonp"));
+  return OK(object, request.url.query.get("jsonp"));
 }
 
 
@@ -1214,7 +1214,7 @@ Future<Response> Master::Http::roles(const Request& request) const
     object.values["roles"] = std::move(array);
   }
 
-  return OK(object, request.query.get("jsonp"));
+  return OK(object, request.url.query.get("jsonp"));
 }
 
 
@@ -1376,10 +1376,10 @@ struct TaskComparator
 Future<Response> Master::Http::tasks(const Request& request) const
 {
   // Get list options (limit and offset).
-  Result<int> result = numify<int>(request.query.get("limit"));
+  Result<int> result = numify<int>(request.url.query.get("limit"));
   size_t limit = result.isSome() ? result.get() : TASK_LIMIT;
 
-  result = numify<int>(request.query.get("offset"));
+  result = numify<int>(request.url.query.get("offset"));
   size_t offset = result.isSome() ? result.get() : 0;
 
   // TODO(nnielsen): Currently, formatting errors in offset and/or limit
@@ -1409,7 +1409,7 @@ Future<Response> Master::Http::tasks(const Request& request) const
 
   // Sort tasks by task status timestamp. Default order is descending.
   // The earliest timestamp is chosen for comparison when multiple are present.
-  Option<string> order = request.query.get("order");
+  Option<string> order = request.url.query.get("order");
   if (order.isSome() && (order.get() == "asc")) {
     sort(tasks.begin(), tasks.end(), TaskComparator::ascending);
   } else {
@@ -1429,7 +1429,7 @@ Future<Response> Master::Http::tasks(const Request& request) const
     object.values["tasks"] = std::move(array);
   }
 
-  return OK(object, request.query.get("jsonp"));
+  return OK(object, request.url.query.get("jsonp"));
 }
 
 
@@ -1458,7 +1458,7 @@ Future<Response> Master::Http::maintenanceSchedule(const Request& request) const
         mesos::maintenance::Schedule() :
         master->maintenance.schedules.front();
 
-    return OK(JSON::Protobuf(schedule), request.query.get("jsonp"));
+    return OK(JSON::Protobuf(schedule), request.url.query.get("jsonp"));
   }
 
   // Parse the POST body as JSON.
@@ -1813,7 +1813,7 @@ Future<Response> Master::Http::maintenanceStatus(const Request& request) const
       }
     }
 
-    return OK(JSON::Protobuf(status), request.query.get("jsonp"));
+    return OK(JSON::Protobuf(status), request.url.query.get("jsonp"));
   }));
 }
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/c9d2017c/src/master/registrar.cpp
----------------------------------------------------------------------
diff --git a/src/master/registrar.cpp b/src/master/registrar.cpp
index d81560a..1117232 100644
--- a/src/master/registrar.cpp
+++ b/src/master/registrar.cpp
@@ -245,7 +245,7 @@ Future<Response> RegistrarProcess::registry(const Request& request)
     result = JSON::Protobuf(variable.get().get());
   }
 
-  return OK(result, request.query.get("jsonp"));
+  return OK(result, request.url.query.get("jsonp"));
 }
 
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/c9d2017c/src/slave/http.cpp
----------------------------------------------------------------------
diff --git a/src/slave/http.cpp b/src/slave/http.cpp
index cddc8ad..f9cf7bb 100644
--- a/src/slave/http.cpp
+++ b/src/slave/http.cpp
@@ -186,7 +186,7 @@ void Slave::Http::log(const Request& request)
   Option<string> userAgent = request.headers.get("User-Agent");
   Option<string> forwardedFor = request.headers.get("X-Forwarded-For");
 
-  LOG(INFO) << "HTTP " << request.method << " for " << request.path
+  LOG(INFO) << "HTTP " << request.method << " for " << request.url.path
             << " from " << request.client
             << (userAgent.isSome()
                 ? " with User-Agent='" + userAgent.get() + "'"
@@ -404,7 +404,7 @@ Future<Response> Slave::Http::state(const Request& request) const
   }
   object.values["flags"] = flags;
 
-  return OK(object, request.query.get("jsonp"));
+  return OK(object, request.url.query.get("jsonp"));
 }
 
 } // namespace slave {

http://git-wip-us.apache.org/repos/asf/mesos/blob/c9d2017c/src/slave/monitor.cpp
----------------------------------------------------------------------
diff --git a/src/slave/monitor.cpp b/src/slave/monitor.cpp
index 8d8b422..aa6e958 100644
--- a/src/slave/monitor.cpp
+++ b/src/slave/monitor.cpp
@@ -147,7 +147,7 @@ private:
       }
     }
 
-    return http::OK(result, request.query.get("jsonp"));
+    return http::OK(result, request.url.query.get("jsonp"));
   }
 
   // Callback used to retrieve resource usage information from slave.

http://git-wip-us.apache.org/repos/asf/mesos/blob/c9d2017c/src/tests/fetcher_cache_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/fetcher_cache_tests.cpp b/src/tests/fetcher_cache_tests.cpp
index b709b1e..31ca146 100644
--- a/src/tests/fetcher_cache_tests.cpp
+++ b/src/tests/fetcher_cache_tests.cpp
@@ -788,11 +788,11 @@ public:
       synchronized (mutex) {
         countRequests++;
 
-        if (strings::contains(event.request->path, COMMAND_NAME)) {
+        if (strings::contains(event.request->url.path, COMMAND_NAME)) {
           countCommandRequests++;
         }
 
-        if (strings::contains(event.request->path, ARCHIVE_NAME)) {
+        if (strings::contains(event.request->url.path, ARCHIVE_NAME)) {
           countArchiveRequests++;
         }
 


[09/10] mesos git commit: Re-enabled decoder test for case insensitive headers.

Posted by bm...@apache.org.
Re-enabled decoder test for case insensitive headers.

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


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

Branch: refs/heads/master
Commit: 2bc6a19638ad8f6d3f8d7653c3f2b72d1cf0f864
Parents: 127a218
Author: Benjamin Mahler <be...@gmail.com>
Authored: Mon Sep 21 11:24:22 2015 -0700
Committer: Benjamin Mahler <be...@gmail.com>
Committed: Mon Sep 28 11:09:55 2015 -0700

----------------------------------------------------------------------
 3rdparty/libprocess/src/tests/decoder_tests.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/2bc6a196/3rdparty/libprocess/src/tests/decoder_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/tests/decoder_tests.cpp b/3rdparty/libprocess/src/tests/decoder_tests.cpp
index 858b40f..76eb80f 100644
--- a/3rdparty/libprocess/src/tests/decoder_tests.cpp
+++ b/3rdparty/libprocess/src/tests/decoder_tests.cpp
@@ -94,8 +94,7 @@ TEST(DecoderTest, RequestHeaderContinuation)
 }
 
 
-// This is expected to fail for now, see my TODO(bmahler) on http::Request.
-TEST(DecoderTest, DISABLED_RequestHeaderCaseInsensitive)
+TEST(DecoderTest, RequestHeaderCaseInsensitive)
 {
   Try<Socket> socket = Socket::create();
   ASSERT_SOME(socket);


[10/10] mesos git commit: Added a TODO to keep Request.keepAlive consistent with the 'Connection' header value.

Posted by bm...@apache.org.
Added a TODO to keep Request.keepAlive consistent with the 'Connection' header value.

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


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

Branch: refs/heads/master
Commit: 9b05418fbe9a352f04e251080dba4711d8fb0e0e
Parents: 605a8b6
Author: Benjamin Mahler <be...@gmail.com>
Authored: Mon Sep 21 11:33:22 2015 -0700
Committer: Benjamin Mahler <be...@gmail.com>
Committed: Mon Sep 28 11:09:55 2015 -0700

----------------------------------------------------------------------
 3rdparty/libprocess/include/process/http.hpp | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/9b05418f/3rdparty/libprocess/include/process/http.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/http.hpp b/3rdparty/libprocess/include/process/http.hpp
index e32607b..ba3f0bc 100644
--- a/3rdparty/libprocess/include/process/http.hpp
+++ b/3rdparty/libprocess/include/process/http.hpp
@@ -168,6 +168,8 @@ struct Request
 
   std::string body;
 
+  // TODO(bmahler): Ensure this is consistent with the 'Connection'
+  // header; perhaps make this a function that checks the header.
   bool keepAlive;
 
   // For server requests, this contains the address of the client.


[03/10] mesos git commit: Added URL within http::Request.

Posted by bm...@apache.org.
Added URL within http::Request.

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


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

Branch: refs/heads/master
Commit: d347bf56c807dad2c7966546819d03f9a7686eb4
Parents: 2fd5ed9
Author: Benjamin Mahler <be...@gmail.com>
Authored: Thu Sep 17 16:27:51 2015 -0700
Committer: Benjamin Mahler <be...@gmail.com>
Committed: Mon Sep 28 10:50:50 2015 -0700

----------------------------------------------------------------------
 .../libprocess/include/process/firewall.hpp     |   4 +-
 3rdparty/libprocess/include/process/http.hpp    | 129 ++++++++++---------
 3rdparty/libprocess/include/process/system.hpp  |   2 +-
 3rdparty/libprocess/src/decoder.hpp             |  19 ++-
 3rdparty/libprocess/src/help.cpp                |   2 +-
 3rdparty/libprocess/src/logging.cpp             |   4 +-
 3rdparty/libprocess/src/metrics/metrics.cpp     |   6 +-
 3rdparty/libprocess/src/process.cpp             |  45 +++----
 3rdparty/libprocess/src/tests/benchmarks.cpp    |   8 +-
 3rdparty/libprocess/src/tests/decoder_tests.cpp |  16 +--
 3rdparty/libprocess/src/tests/http_tests.cpp    |  24 ++--
 11 files changed, 129 insertions(+), 130 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/d347bf56/3rdparty/libprocess/include/process/firewall.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/firewall.hpp b/3rdparty/libprocess/include/process/firewall.hpp
index b1abfb2..b5c7d99 100644
--- a/3rdparty/libprocess/include/process/firewall.hpp
+++ b/3rdparty/libprocess/include/process/firewall.hpp
@@ -80,8 +80,8 @@ public:
       const network::Socket&,
       const http::Request& request)
   {
-    if (paths.contains(request.path)) {
-      return http::Forbidden("Endpoint '" + request.path + "' is disabled");
+    if (paths.contains(request.url.path)) {
+      return http::Forbidden("Endpoint '" + request.url.path + "' is disabled");
     }
 
     return None();

http://git-wip-us.apache.org/repos/asf/mesos/blob/d347bf56/3rdparty/libprocess/include/process/http.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/http.hpp b/3rdparty/libprocess/include/process/http.hpp
index c71efcc..5932af4 100644
--- a/3rdparty/libprocess/include/process/http.hpp
+++ b/3rdparty/libprocess/include/process/http.hpp
@@ -62,6 +62,59 @@ extern hashmap<uint16_t, std::string> statuses;
 void initialize();
 
 
+// Represents a Uniform Resource Locator:
+//   scheme://domain|ip:port/path?query#fragment
+//
+// This is actually a URI-reference (see 4.1 of RFC 3986).
+//
+// TODO(bmahler): The default port should depend on the scheme!
+struct URL
+{
+  URL() = default;
+
+  URL(const std::string& _scheme,
+      const std::string& _domain,
+      const uint16_t _port = 80,
+      const std::string& _path = "/",
+      const hashmap<std::string, std::string>& _query =
+        (hashmap<std::string, std::string>()),
+      const Option<std::string>& _fragment = None())
+    : scheme(_scheme),
+      domain(_domain),
+      port(_port),
+      path(_path),
+      query(_query),
+      fragment(_fragment) {}
+
+  URL(const std::string& _scheme,
+      const net::IP& _ip,
+      const uint16_t _port = 80,
+      const std::string& _path = "/",
+      const hashmap<std::string, std::string>& _query =
+        (hashmap<std::string, std::string>()),
+      const Option<std::string>& _fragment = None())
+    : scheme(_scheme),
+      ip(_ip),
+      port(_port),
+      path(_path),
+      query(_query),
+      fragment(_fragment) {}
+
+  Option<std::string> scheme;
+
+  // TODO(benh): Consider using unrestricted union for 'domain' and 'ip'.
+  Option<std::string> domain;
+  Option<net::IP> ip;
+  Option<uint16_t> port;
+  std::string path;
+  hashmap<std::string, std::string> query;
+  Option<std::string> fragment;
+};
+
+
+std::ostream& operator<<(std::ostream& stream, const URL& url);
+
+
 struct CaseInsensitiveHash
 {
   size_t operator()(const std::string& key) const
@@ -94,31 +147,30 @@ struct CaseInsensitiveEqual
 
 struct Request
 {
-  // Contains the client's address. Note that this may
-  // correspond to a proxy or load balancer address.
-  network::Address client;
+  std::string method;
 
   // TODO(benh): Add major/minor version.
+
+  // For client requests, the URL should be a URI.
+  // For server requests, the URL may be a URI or a relative reference.
+  URL url;
+
   hashmap<std::string,
           std::string,
           CaseInsensitiveHash,
           CaseInsensitiveEqual> headers;
 
-  std::string method;
-
-  // TODO(benh): Replace 'url', 'path', 'query', and 'fragment' with URL.
-  std::string url; // (path?query#fragment)
-
-  // TODO(vinod): Make this a 'Path' instead of 'string'.
-  std::string path;
-
-  hashmap<std::string, std::string> query;
-  std::string fragment;
+  // TODO(bmahler): Add a 'query' field which contains both
+  // the URL query and the parsed form data from the body.
 
   std::string body;
 
   bool keepAlive;
 
+  // For server requests, this contains the address of the client.
+  // Note that this may correspond to a proxy or load balancer address.
+  network::Address client;
+
   /**
    * Returns whether the encoding is considered acceptable in the
    * response. See RFC 2616 section 14.3 for details.
@@ -661,57 +713,6 @@ std::string encode(const hashmap<std::string, std::string>& query);
 } // namespace query {
 
 
-// Represents a Uniform Resource Locator:
-//   scheme://domain|ip:port/path?query#fragment
-//
-// This is actually a URI-reference (see 4.1 of RFC 3986).
-//
-// TODO(bmahler): The default port should depend on the scheme!
-struct URL
-{
-  URL(const std::string& _scheme,
-      const std::string& _domain,
-      const uint16_t _port = 80,
-      const std::string& _path = "/",
-      const hashmap<std::string, std::string>& _query =
-        (hashmap<std::string, std::string>()),
-      const Option<std::string>& _fragment = None())
-    : scheme(_scheme),
-      domain(_domain),
-      port(_port),
-      path(_path),
-      query(_query),
-      fragment(_fragment) {}
-
-  URL(const std::string& _scheme,
-      const net::IP& _ip,
-      const uint16_t _port = 80,
-      const std::string& _path = "/",
-      const hashmap<std::string, std::string>& _query =
-        (hashmap<std::string, std::string>()),
-      const Option<std::string>& _fragment = None())
-    : scheme(_scheme),
-      ip(_ip),
-      port(_port),
-      path(_path),
-      query(_query),
-      fragment(_fragment) {}
-
-  Option<std::string> scheme;
-
-  // TODO(benh): Consider using unrestricted union for 'domain' and 'ip'.
-  Option<std::string> domain;
-  Option<net::IP> ip;
-  Option<uint16_t> port;
-  std::string path;
-  hashmap<std::string, std::string> query;
-  Option<std::string> fragment;
-};
-
-
-std::ostream& operator<<(std::ostream& stream, const URL& url);
-
-
 // TODO(bmahler): Consolidate these functions into a single
 // http::request function that takes a 'Request' object.
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/d347bf56/3rdparty/libprocess/include/process/system.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/system.hpp b/3rdparty/libprocess/include/process/system.hpp
index 264d948..9b49c95 100644
--- a/3rdparty/libprocess/include/process/system.hpp
+++ b/3rdparty/libprocess/include/process/system.hpp
@@ -182,7 +182,7 @@ private:
       object.values["mem_free_bytes"] = memory.get().free.bytes();
     }
 
-    return http::OK(object, request.query.get("jsonp"));
+    return http::OK(object, request.url.query.get("jsonp"));
   }
 
   metrics::Gauge load_1min;

http://git-wip-us.apache.org/repos/asf/mesos/blob/d347bf56/3rdparty/libprocess/src/decoder.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/decoder.hpp b/3rdparty/libprocess/src/decoder.hpp
index 67a5135..d348463 100644
--- a/3rdparty/libprocess/src/decoder.hpp
+++ b/3rdparty/libprocess/src/decoder.hpp
@@ -108,13 +108,6 @@ private:
     CHECK(decoder->request == NULL);
 
     decoder->request = new http::Request();
-    decoder->request->headers.clear();
-    decoder->request->method.clear();
-    decoder->request->path.clear();
-    decoder->request->url.clear();
-    decoder->request->fragment.clear();
-    decoder->request->query.clear();
-    decoder->request->body.clear();
 
     return 0;
   }
@@ -124,7 +117,7 @@ private:
   {
     DataDecoder* decoder = (DataDecoder*) p->data;
     CHECK_NOTNULL(decoder->request);
-    decoder->request->path.append(data, length);
+    decoder->request->url.path.append(data, length);
     return 0;
   }
 
@@ -140,7 +133,12 @@ private:
   {
     DataDecoder* decoder = (DataDecoder*) p->data;
     CHECK_NOTNULL(decoder->request);
-    decoder->request->fragment.append(data, length);
+
+    if (decoder->request->url.fragment.isNone()) {
+      decoder->request->url.fragment = "";
+    }
+
+    decoder->request->url.fragment->append(data, length);
     return 0;
   }
 #endif // !(HTTP_PARSER_VERSION_MAJOR >= 2)
@@ -149,7 +147,6 @@ private:
   {
     DataDecoder* decoder = (DataDecoder*) p->data;
     CHECK_NOTNULL(decoder->request);
-    decoder->request->url.append(data, length);
     int result = 0;
 
 #if (HTTP_PARSER_VERSION_MAJOR >= 2)
@@ -248,7 +245,7 @@ private:
 
     CHECK_NOTNULL(decoder->request);
 
-    decoder->request->query =  decoded.get();
+    decoder->request->url.query = decoded.get();
 
     Option<std::string> encoding =
       decoder->request->headers.get("Content-Encoding");

http://git-wip-us.apache.org/repos/asf/mesos/blob/d347bf56/3rdparty/libprocess/src/help.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/help.cpp b/3rdparty/libprocess/src/help.cpp
index d358b93..822c084 100644
--- a/3rdparty/libprocess/src/help.cpp
+++ b/3rdparty/libprocess/src/help.cpp
@@ -109,7 +109,7 @@ void Help::initialize()
 Future<http::Response> Help::help(const http::Request& request)
 {
   // Split the path by '/'.
-  vector<string> tokens = strings::tokenize(request.path, "/");
+  vector<string> tokens = strings::tokenize(request.url.path, "/");
 
   Option<string> id = None();
   Option<string> name = None();

http://git-wip-us.apache.org/repos/asf/mesos/blob/d347bf56/3rdparty/libprocess/src/logging.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/logging.cpp b/3rdparty/libprocess/src/logging.cpp
index db76abe..bb1131f 100644
--- a/3rdparty/libprocess/src/logging.cpp
+++ b/3rdparty/libprocess/src/logging.cpp
@@ -29,8 +29,8 @@ namespace process {
 
 Future<http::Response> Logging::toggle(const http::Request& request)
 {
-  Option<std::string> level = request.query.get("level");
-  Option<std::string> duration = request.query.get("duration");
+  Option<std::string> level = request.url.query.get("level");
+  Option<std::string> duration = request.url.query.get("duration");
 
   if (level.isNone() && duration.isNone()) {
     return http::OK(stringify(FLAGS_v) + "\n");

http://git-wip-us.apache.org/repos/asf/mesos/blob/d347bf56/3rdparty/libprocess/src/metrics/metrics.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/metrics/metrics.cpp b/3rdparty/libprocess/src/metrics/metrics.cpp
index 943ba63..0cf844c 100644
--- a/3rdparty/libprocess/src/metrics/metrics.cpp
+++ b/3rdparty/libprocess/src/metrics/metrics.cpp
@@ -115,8 +115,8 @@ Future<http::Response> MetricsProcess::_snapshot(const http::Request& request)
   // Parse the 'timeout' parameter.
   Option<Duration> timeout;
 
-  if (request.query.contains("timeout")) {
-    string parameter = request.query.get("timeout").get();
+  if (request.url.query.contains("timeout")) {
+    string parameter = request.url.query.get("timeout").get();
 
     Try<Duration> duration = Duration::parse(parameter);
 
@@ -192,7 +192,7 @@ Future<http::Response> MetricsProcess::__snapshot(
     }
   }
 
-  return http::OK(object, request.query.get("jsonp"));
+  return http::OK(object, request.url.query.get("jsonp"));
 }
 
 }  // namespace internal {

http://git-wip-us.apache.org/repos/asf/mesos/blob/d347bf56/3rdparty/libprocess/src/process.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/process.cpp b/3rdparty/libprocess/src/process.cpp
index 7a2b911..d1c81f1 100644
--- a/3rdparty/libprocess/src/process.cpp
+++ b/3rdparty/libprocess/src/process.cpp
@@ -556,11 +556,11 @@ static Message* parse(Request* request)
   }
 
   // Now determine 'to'.
-  size_t index = request->path.find('/', 1);
+  size_t index = request->url.path.find('/', 1);
   index = index != string::npos ? index - 1 : string::npos;
 
   // Decode possible percent-encoded 'to'.
-  Try<string> decode = http::decode(request->path.substr(1, index));
+  Try<string> decode = http::decode(request->url.path.substr(1, index));
 
   if (decode.isError()) {
     VLOG(2) << "Failed to decode URL path: " << decode.get();
@@ -570,8 +570,8 @@ static Message* parse(Request* request)
   const UPID to(decode.get(), __address__);
 
   // And now determine 'name'.
-  index = index != string::npos ? index + 2: request->path.size();
-  const string name = request->path.substr(index);
+  index = index != string::npos ? index + 2: request->url.path.size();
+  const string name = request->url.path.substr(index);
 
   VLOG(2) << "Parsed message name '" << name
           << "' for " << to << " from " << from.get();
@@ -2226,11 +2226,11 @@ bool ProcessManager::handle(
       Option<string> agent = request->headers.get("User-Agent");
       if (agent.getOrElse("").find("libprocess/") == string::npos) {
         if (accepted) {
-          VLOG(2) << "Accepted libprocess message to " << request->path;
+          VLOG(2) << "Accepted libprocess message to " << request->url.path;
           dispatch(proxy, &HttpProxy::enqueue, Accepted(), *request);
         } else {
           VLOG(1) << "Failed to handle libprocess message to "
-                  << request->path << ": not found";
+                  << request->url.path << ": not found";
           dispatch(proxy, &HttpProxy::enqueue, NotFound(), *request);
         }
       }
@@ -2240,7 +2240,7 @@ bool ProcessManager::handle(
     }
 
     VLOG(1) << "Failed to handle libprocess message: "
-            << request->method << " " << request->path
+            << request->method << " " << request->url.path
             << " (User-Agent: " << request->headers["User-Agent"] << ")";
 
     delete request;
@@ -2249,8 +2249,8 @@ bool ProcessManager::handle(
 
   // Treat this as an HTTP request. Start by checking that the path
   // starts with a '/' (since the code below assumes as much).
-  if (request->path.find('/') != 0) {
-    VLOG(1) << "Returning '400 Bad Request' for '" << request->path << "'";
+  if (request->url.path.find('/') != 0) {
+    VLOG(1) << "Returning '400 Bad Request' for '" << request->url.path << "'";
 
     // Get the HttpProxy pid for this socket.
     PID<HttpProxy> proxy = socket_manager->proxy(socket);
@@ -2265,8 +2265,8 @@ bool ProcessManager::handle(
   }
 
   // Ignore requests with relative paths (i.e., contain "/..").
-  if (request->path.find("/..") != string::npos) {
-    VLOG(1) << "Returning '404 Not Found' for '" << request->path
+  if (request->url.path.find("/..") != string::npos) {
+    VLOG(1) << "Returning '404 Not Found' for '" << request->url.path
             << "' (ignoring requests with relative paths)";
 
     // Get the HttpProxy pid for this socket.
@@ -2282,13 +2282,13 @@ bool ProcessManager::handle(
   }
 
   // Split the path by '/'.
-  vector<string> tokens = strings::tokenize(request->path, "/");
+  vector<string> tokens = strings::tokenize(request->url.path, "/");
 
   // Try and determine a receiver, otherwise try and delegate.
   ProcessReference receiver;
 
   if (tokens.size() == 0 && delegate != "") {
-    request->path = "/" + delegate;
+    request->url.path = "/" + delegate;
     receiver = use(UPID(delegate, __address__));
   } else if (tokens.size() > 0) {
     // Decode possible percent-encoded path.
@@ -2302,7 +2302,7 @@ bool ProcessManager::handle(
 
   if (!receiver && delegate != "") {
     // Try and delegate the request.
-    request->path = "/" + delegate + request->path;
+    request->url.path = "/" + delegate + request->url.path;
     receiver = use(UPID(delegate, __address__));
   }
 
@@ -2313,7 +2313,7 @@ bool ProcessManager::handle(
       Option<Response> rejection = rule->apply(socket, *request);
       if (rejection.isSome()) {
         VLOG(1) << "Returning '"<< rejection.get().status << "' for '"
-                << request->path << "' (firewall rule forbids request)";
+                << request->url.path << "' (firewall rule forbids request)";
 
         // TODO(arojas): Get rid of the duplicated code to return an
         // error.
@@ -2343,7 +2343,7 @@ bool ProcessManager::handle(
   }
 
   // This has no receiver, send error response.
-  VLOG(1) << "Returning '404 Not Found' for '" << request->path << "'";
+  VLOG(1) << "Returning '404 Not Found' for '" << request->url.path << "'";
 
   // Get the HttpProxy pid for this socket.
   PID<HttpProxy> proxy = socket_manager->proxy(socket);
@@ -2924,7 +2924,7 @@ Future<Response> ProcessManager::__processes__(const Request&)
           const Request& request = *event.request;
 
           object.values["method"] = request.method;
-          object.values["url"] = request.url;
+          object.values["url"] = stringify(request.url);
 
           events->values.push_back(object);
         }
@@ -3073,12 +3073,12 @@ void ProcessBase::visit(const DispatchEvent& event)
 void ProcessBase::visit(const HttpEvent& event)
 {
   VLOG(1) << "Handling HTTP event for process '" << pid.id << "'"
-          << " with path: '" << event.request->path << "'";
+          << " with path: '" << event.request->url.path << "'";
 
-  CHECK(event.request->path.find('/') == 0); // See ProcessManager::handle.
+  CHECK(event.request->url.path.find('/') == 0); // See ProcessManager::handle.
 
   // Split the path by '/'.
-  vector<string> tokens = strings::tokenize(event.request->path, "/");
+  vector<string> tokens = strings::tokenize(event.request->url.path, "/");
   CHECK(tokens.size() >= 1);
   CHECK_EQ(pid.id, http::decode(tokens[0]).get());
 
@@ -3087,7 +3087,7 @@ void ProcessBase::visit(const HttpEvent& event)
 
   // Remove the 'id' prefix from the path.
   string name = strings::remove(
-      event.request->path, "/" + tokens[0], strings::PREFIX);
+      event.request->url.path, "/" + tokens[0], strings::PREFIX);
 
   name = strings::trim(name, strings::PREFIX, "/");
 
@@ -3151,7 +3151,8 @@ void ProcessBase::visit(const HttpEvent& event)
     return;
   }
 
-  VLOG(1) << "Returning '404 Not Found' for '" << event.request->path << "'";
+  VLOG(1) << "Returning '404 Not Found' for"
+          << " '" << event.request->url.path << "'";
 
   // Get the HttpProxy pid for this socket.
   PID<HttpProxy> proxy = socket_manager->proxy(event.socket);

http://git-wip-us.apache.org/repos/asf/mesos/blob/d347bf56/3rdparty/libprocess/src/tests/benchmarks.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/tests/benchmarks.cpp b/3rdparty/libprocess/src/tests/benchmarks.cpp
index 97c81b8..bb9ced8 100644
--- a/3rdparty/libprocess/src/tests/benchmarks.cpp
+++ b/3rdparty/libprocess/src/tests/benchmarks.cpp
@@ -95,10 +95,10 @@ private:
     }
 
     hashmap<string, Option<string>> parameters {
-      {"server", request.query.get("server")},
-      {"messageSize", request.query.get("messageSize")},
-      {"requests", request.query.get("requests")},
-      {"concurrency", request.query.get("concurrency")},
+      {"server", request.url.query.get("server")},
+      {"messageSize", request.url.query.get("messageSize")},
+      {"requests", request.url.query.get("requests")},
+      {"concurrency", request.url.query.get("concurrency")},
     };
 
     // Ensure all parameters were provided.

http://git-wip-us.apache.org/repos/asf/mesos/blob/d347bf56/3rdparty/libprocess/src/tests/decoder_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/tests/decoder_tests.cpp b/3rdparty/libprocess/src/tests/decoder_tests.cpp
index 6994fa9..858b40f 100644
--- a/3rdparty/libprocess/src/tests/decoder_tests.cpp
+++ b/3rdparty/libprocess/src/tests/decoder_tests.cpp
@@ -50,21 +50,21 @@ TEST(DecoderTest, Request)
 
   Request* request = requests[0];
   EXPECT_EQ("GET", request->method);
-  EXPECT_EQ("/path/file.json", request->path);
-  EXPECT_EQ("/path/file.json?key1=value1&key2=value2#fragment", request->url);
-  EXPECT_EQ("fragment", request->fragment);
+
+  EXPECT_EQ("/path/file.json", request->url.path);
+  EXPECT_SOME_EQ("fragment", request->url.fragment);
+  EXPECT_EQ(2u, request->url.query.size());
+  EXPECT_SOME_EQ("value1", request->url.query.get("key1"));
+  EXPECT_SOME_EQ("value2", request->url.query.get("key2"));
+
   EXPECT_TRUE(request->body.empty());
   EXPECT_FALSE(request->keepAlive);
 
-  EXPECT_EQ(3, request->headers.size());
+  EXPECT_EQ(3u, request->headers.size());
   EXPECT_SOME_EQ("localhost", request->headers.get("Host"));
   EXPECT_SOME_EQ("close", request->headers.get("Connection"));
   EXPECT_SOME_EQ("compress, gzip", request->headers.get("Accept-Encoding"));
 
-  EXPECT_EQ(2, request->query.size());
-  EXPECT_SOME_EQ("value1", request->query.get("key1"));
-  EXPECT_SOME_EQ("value2", request->query.get("key2"));
-
   delete request;
 }
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/d347bf56/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 d0b9399..a52561e 100644
--- a/3rdparty/libprocess/src/tests/http_tests.cpp
+++ b/3rdparty/libprocess/src/tests/http_tests.cpp
@@ -395,10 +395,10 @@ http::Response validateGetWithoutQuery(const http::Request& request)
 {
   EXPECT_NE(process::address(), request.client);
   EXPECT_EQ("GET", request.method);
-  EXPECT_THAT(request.path, EndsWith("get"));
+  EXPECT_THAT(request.url.path, EndsWith("get"));
   EXPECT_EQ("", request.body);
-  EXPECT_EQ("", request.fragment);
-  EXPECT_TRUE(request.query.empty());
+  EXPECT_NONE(request.url.fragment);
+  EXPECT_TRUE(request.url.query.empty());
 
   return http::OK();
 }
@@ -408,11 +408,11 @@ http::Response validateGetWithQuery(const http::Request& request)
 {
   EXPECT_NE(process::address(), request.client);
   EXPECT_EQ("GET", request.method);
-  EXPECT_THAT(request.path, EndsWith("get"));
+  EXPECT_THAT(request.url.path, EndsWith("get"));
   EXPECT_EQ("", request.body);
-  EXPECT_EQ("", request.fragment);
-  EXPECT_EQ("bar", request.query.at("foo"));
-  EXPECT_EQ(1, request.query.size());
+  EXPECT_NONE(request.url.fragment);
+  EXPECT_EQ("bar", request.url.query.at("foo"));
+  EXPECT_EQ(1, request.url.query.size());
 
   return http::OK();
 }
@@ -573,10 +573,10 @@ TEST(HTTPTest, PipeEquality)
 http::Response validatePost(const http::Request& request)
 {
   EXPECT_EQ("POST", request.method);
-  EXPECT_THAT(request.path, EndsWith("post"));
+  EXPECT_THAT(request.url.path, EndsWith("post"));
   EXPECT_EQ("This is the payload.", request.body);
-  EXPECT_EQ("", request.fragment);
-  EXPECT_TRUE(request.query.empty());
+  EXPECT_NONE(request.url.fragment);
+  EXPECT_TRUE(request.url.query.empty());
 
   return http::OK();
 }
@@ -623,9 +623,9 @@ TEST(HTTPTest, Post)
 http::Response validateDelete(const http::Request& request)
 {
   EXPECT_EQ("DELETE", request.method);
-  EXPECT_THAT(request.path, EndsWith("delete"));
+  EXPECT_THAT(request.url.path, EndsWith("delete"));
   EXPECT_TRUE(request.body.empty());
-  EXPECT_TRUE(request.query.empty());
+  EXPECT_TRUE(request.url.query.empty());
 
   return http::OK();
 }


[07/10] mesos git commit: Refactored http::internal::Request to take a Request object.

Posted by bm...@apache.org.
Refactored http::internal::Request to take a Request object.

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


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

Branch: refs/heads/master
Commit: 127a2181491464eb2dff7947bc91562cd788f3e3
Parents: 9b05418
Author: Benjamin Mahler <be...@gmail.com>
Authored: Thu Sep 17 17:02:51 2015 -0700
Committer: Benjamin Mahler <be...@gmail.com>
Committed: Mon Sep 28 11:09:55 2015 -0700

----------------------------------------------------------------------
 3rdparty/libprocess/src/http.cpp | 170 ++++++++++++++++++++--------------
 1 file changed, 102 insertions(+), 68 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/127a2181/3rdparty/libprocess/src/http.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/http.cpp b/3rdparty/libprocess/src/http.cpp
index c93e7e0..d992533 100644
--- a/3rdparty/libprocess/src/http.cpp
+++ b/3rdparty/libprocess/src/http.cpp
@@ -759,29 +759,20 @@ void _decode(
 Future<Response> _request(
     Socket socket,
     const Address& address,
-    const URL& url,
-    const string& method,
-    bool streamingResponse,
-    const Option<Headers>& _headers,
-    const Option<string>& body,
-    const Option<string>& contentType);
+    const Request& request,
+    bool streamedResponse);
 
 
-Future<Response> request(
-    const URL& url,
-    const string& method,
-    bool streamedResponse,
-    const Option<Headers>& headers,
-    const Option<string>& body,
-    const Option<string>& contentType)
+Future<Response> request(const Request& request, bool streamedResponse)
 {
-  Try<Socket> socket = [&url]() -> Try<Socket> {
+  Try<Socket> socket = [&request]() -> Try<Socket> {
     // Default to 'http' if no scheme was specified.
-    if (url.scheme.isNone() || url.scheme == string("http")) {
+    if (request.url.scheme.isNone() ||
+        request.url.scheme == string("http")) {
       return Socket::create(Socket::POLL);
     }
 
-    if (url.scheme == string("https")) {
+    if (request.url.scheme == string("https")) {
 #ifdef USE_SSL_SOCKET
       return Socket::create(Socket::SSL);
 #else
@@ -798,86 +789,78 @@ Future<Response> request(
 
   Address address;
 
-  if (url.ip.isSome()) {
-    address.ip = url.ip.get();
-  } else if (url.domain.isNone()) {
+  if (request.url.ip.isSome()) {
+    address.ip = request.url.ip.get();
+  } else if (request.url.domain.isNone()) {
     return Failure("Expecting url.ip or url.domain to be set");
   } else {
-    Try<net::IP> ip = net::getIP(url.domain.get(), AF_INET);
+    Try<net::IP> ip = net::getIP(request.url.domain.get(), AF_INET);
 
     if (ip.isError()) {
       return Failure("Failed to determine IP of domain '" +
-                     url.domain.get() + "': " + ip.error());
+                     request.url.domain.get() + "': " + ip.error());
     }
 
     address.ip = ip.get();
   }
 
-  if (url.port.isNone()) {
+  if (request.url.port.isNone()) {
     return Failure("Expecting url.port to be set");
   }
 
-  address.port = url.port.get();
+  address.port = request.url.port.get();
 
   return socket->connect(address)
     .then(lambda::bind(&_request,
                        socket.get(),
                        address,
-                       url,
-                       method,
-                       streamedResponse,
-                       headers,
-                       body,
-                       contentType));
+                       request,
+                       streamedResponse));
 }
 
 
 Future<Response> _request(
     Socket socket,
     const Address& address,
-    const URL& url,
-    const string& method,
-    bool streamedResponse,
-    const Option<Headers>& _headers,
-    const Option<string>& body,
-    const Option<string>& contentType)
+    const Request& request,
+    bool streamedResponse)
 {
   std::ostringstream out;
 
-  out << method << " /" << strings::remove(url.path, "/", strings::PREFIX);
+  out << request.method
+      << " /" << strings::remove(request.url.path, "/", strings::PREFIX);
 
-  if (!url.query.empty()) {
+  if (!request.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) {
+    foreachpair (const string& key, const string& value, request.url.query) {
       query.push_back(key + "=" + value);
     }
 
     out << "?" << strings::join("&", query);
   }
 
-  if (url.fragment.isSome()) {
-    out << "#" << url.fragment.get();
+  if (request.url.fragment.isSome()) {
+    out << "#" << request.url.fragment.get();
   }
 
   out << " HTTP/1.1\r\n";
 
-  // Set up the headers as necessary.
-  Headers headers;
-
-  if (_headers.isSome()) {
-    headers = _headers.get();
-  }
+  // Overwrite headers as necessary.
+  Headers headers = request.headers;
 
   // Need to specify the 'Host' header.
-  if (url.domain.isSome()) {
+  if (request.url.domain.isSome()) {
     // Use ONLY domain for standard ports.
-    if (url.port.isNone() || url.port == 80 || url.port == 443) {
-      headers["Host"] = url.domain.get();
+    if (request.url.port.isNone() ||
+        request.url.port == 80 ||
+        request.url.port == 443) {
+      headers["Host"] = request.url.domain.get();
     } else {
       // Add port for non-standard ports.
-      headers["Host"] = url.domain.get() + ":" + stringify(url.port.get());
+      headers["Host"] =
+        request.url.domain.get() + ":" + stringify(request.url.port.get());
     }
   } else {
     headers["Host"] = stringify(address);
@@ -886,15 +869,8 @@ Future<Response> _request(
   // Tell the server to close the connection when it's done.
   headers["Connection"] = "close";
 
-  // Overwrite Content-Type if necessary.
-  if (contentType.isSome()) {
-    headers["Content-Type"] = contentType.get();
-  }
-
-  // Make sure the Content-Length is set correctly if necessary.
-  if (body.isSome()) {
-    headers["Content-Length"] = stringify(body.get().length());
-  }
+  // Make sure the Content-Length is set correctly.
+  headers["Content-Length"] = stringify(request.body.length());
 
   // TODO(bmahler): Use a 'Request' and a 'RequestEncoder' here!
   // Currently this does not handle 'gzip' content encoding,
@@ -909,10 +885,7 @@ Future<Response> _request(
   }
 
   out << "\r\n";
-
-  if (body.isSome()) {
-    out << body.get();
-  }
+  out << request.body;
 
   // Need to disambiguate the Socket::recv for binding below.
   Future<string> (Socket::*recv)(const Option<ssize_t>&) = &Socket::recv;
@@ -939,7 +912,16 @@ Future<Response> get(
     const URL& url,
     const Option<Headers>& headers)
 {
-  return internal::request(url, "GET", false, headers, None(), None());
+  Request request;
+  request.method = "GET";
+  request.url = url;
+  request.keepAlive = false;
+
+  if (headers.isSome()) {
+    request.headers = headers.get();
+  }
+
+  return internal::request(request, false);
 }
 
 
@@ -981,7 +963,24 @@ Future<Response> post(
     return Failure("Attempted to do a POST with a Content-Type but no body");
   }
 
-  return internal::request(url, "POST", false, headers, body, contentType);
+  Request request;
+  request.method = "POST";
+  request.url = url;
+  request.keepAlive = false;
+
+  if (headers.isSome()) {
+    request.headers = headers.get();
+  }
+
+  if (body.isSome()) {
+    request.body = body.get();
+  }
+
+  if (contentType.isSome()) {
+    request.headers["Content-Type"] = contentType.get();
+  }
+
+  return internal::request(request, false);
 }
 
 
@@ -1007,7 +1006,16 @@ Future<Response> requestDelete(
     const URL& url,
     const Option<Headers>& headers)
 {
-  return internal::request(url, "DELETE", false, headers, None(), None());
+  Request request;
+  request.method = "DELETE";
+  request.url = url;
+  request.keepAlive = false;
+
+  if (headers.isSome()) {
+    request.headers = headers.get();
+  }
+
+  return internal::request(request, false);
 }
 
 
@@ -1035,7 +1043,16 @@ Future<Response> get(
     const URL& url,
     const Option<Headers>& headers)
 {
-  return internal::request(url, "GET", true, headers, None(), None());
+  Request request;
+  request.method = "GET";
+  request.url = url;
+  request.keepAlive = false;
+
+  if (headers.isSome()) {
+    request.headers = headers.get();
+  }
+
+  return internal::request(request, true);
 }
 
 
@@ -1077,7 +1094,24 @@ Future<Response> post(
     return Failure("Attempted to do a POST with a Content-Type but no body");
   }
 
-  return internal::request(url, "POST", true, headers, body, contentType);
+  Request request;
+  request.method = "POST";
+  request.url = url;
+  request.keepAlive = false;
+
+  if (body.isSome()) {
+    request.body = body.get();
+  }
+
+  if (headers.isSome()) {
+    request.headers = headers.get();
+  }
+
+  if (contentType.isSome()) {
+    request.headers["Content-Type"] = contentType.get();
+  }
+
+  return internal::request(request, true);
 }