Repository: mesos Updated Branches: refs/heads/master b8bec2027 -> 3544df756
Added /call parsing and validation. Review: https://reviews.apache.org/r/36720 Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/8e4d1c6e Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/8e4d1c6e Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/8e4d1c6e Branch: refs/heads/master Commit: 8e4d1c6e4fd1be2fe05db045f034b84bf19e04af Parents: b8bec20 Author: Anand Mazumdar <[email protected]> Authored: Tue Aug 4 13:16:58 2015 -0700 Committer: Benjamin Mahler <[email protected]> Committed: Tue Aug 4 14:03:56 2015 -0700 ---------------------------------------------------------------------- src/master/http.cpp | 54 ++++++++++++++++++++++++++++++++++++++- src/tests/http_api_tests.cpp | 12 ++++++--- 2 files changed, 61 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/8e4d1c6e/src/master/http.cpp ---------------------------------------------------------------------- diff --git a/src/master/http.cpp b/src/master/http.cpp index 3772e39..32e8a23 100644 --- a/src/master/http.cpp +++ b/src/master/http.cpp @@ -67,9 +67,11 @@ using process::http::Accepted; using process::http::BadRequest; using process::http::InternalServerError; using process::http::NotFound; +using process::http::NotImplemented; using process::http::OK; using process::http::TemporaryRedirect; using process::http::Unauthorized; +using process::http::UnsupportedMediaType; using process::metrics::internal::MetricsProcess; @@ -320,7 +322,57 @@ const string Master::Http::CALL_HELP = HELP( Future<Response> Master::Http::call(const Request& request) const { - return Accepted(); + scheduler::Call call; + + // TODO(anand): Content type values are case-insensitive. + Option<string> contentType = request.headers.get("Content-Type"); + + if (contentType.isNone()) { + return BadRequest("Expecting 'Content-Type' to be present"); + } + + if (contentType.get() == APPLICATION_PROTOBUF) { + if (!call.ParseFromString(request.body)) { + return BadRequest("Failed to parse body into Call protobuf"); + } + } else if (contentType.get() == APPLICATION_JSON) { + Try<JSON::Value> value = JSON::parse(request.body); + + if (value.isError()) { + return BadRequest("Failed to parse body into JSON: " + value.error()); + } + + Try<scheduler::Call> parse = + ::protobuf::parse<scheduler::Call>(value.get()); + + if (parse.isError()) { + return BadRequest("Failed to convert JSON into Call protobuf: " + + parse.error()); + } + + call = parse.get(); + } else { + return UnsupportedMediaType( + string("Expecting 'Content-Type' of ") + + APPLICATION_JSON + " or " + APPLICATION_PROTOBUF); + } + + // Default to sending back JSON. + ContentType responseContentType = ContentType::JSON; + + // TODO(anand): Use request.acceptsMediaType() once available. + Option<string> acceptType = request.headers.get("Accept"); + + if (acceptType.get() == APPLICATION_PROTOBUF) { + responseContentType = ContentType::PROTOBUF; + } + + // Silence unused warning for now. + (void)responseContentType; + + // TODO(anand): Handle the call. + + return NotImplemented(); } http://git-wip-us.apache.org/repos/asf/mesos/blob/8e4d1c6e/src/tests/http_api_tests.cpp ---------------------------------------------------------------------- diff --git a/src/tests/http_api_tests.cpp b/src/tests/http_api_tests.cpp index 64bbeb6..586d112 100644 --- a/src/tests/http_api_tests.cpp +++ b/src/tests/http_api_tests.cpp @@ -32,7 +32,7 @@ using mesos::internal::master::Master; using process::Future; using process::PID; -using process::http::Accepted; +using process::http::BadRequest; using process::http::Response; namespace mesos { @@ -43,19 +43,23 @@ namespace tests { class HttpApiTest : public MesosTest {}; -// Ensures that the master returns 202 from the /call stub. -TEST_F(HttpApiTest, Call) +// TODO(anand): Add additional tests for validation. +TEST_F(HttpApiTest, NoContentType) { Try<PID<Master>> master = StartMaster(); ASSERT_SOME(master); + // Expect a BadRequest when 'Content-Type' is omitted. + // + // TODO(anand): Send a valid call here to ensure that + // the BadRequest is only due to the missing header. Future<Response> response = process::http::post( master.get(), "call", None(), None()); - AWAIT_EXPECT_RESPONSE_STATUS_EQ(Accepted().status, response); + AWAIT_EXPECT_RESPONSE_STATUS_EQ(BadRequest().status, response); } } // namespace tests {
