TEST_P(SchedulerHttpApiTest, NotAcceptable) { Try<Owned<cluster::Master>> master = StartMaster(); ASSERT_SOME(master); // Retrieve the parameter passed as content type to this test. const string contentType = GetParam(); process::http::Headers headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL); headers["Accept"] = "foo"; // Only subscribe needs to 'Accept' json or protobuf. Call call; call.set_type(Call::SUBSCRIBE); Call::Subscribe* subscribe = call.mutable_subscribe(); subscribe->mutable_framework_info()->CopyFrom(v1::DEFAULT_FRAMEWORK_INFO); Future<Response> response = process::http::streaming::post( master.get()->pid, "api/v1/scheduler", headers, serialize(call, contentType), contentType); AWAIT_EXPECT_RESPONSE_STATUS_EQ(NotAcceptable().status, response); }
// This test sends a unsupported Accept media type for the Accept // header. The response should be NotAcceptable in this case. TEST_P(ExecutorHttpApiTest, NotAcceptable) { Try<PID<Master>> master = StartMaster(); ASSERT_SOME(master); Try<PID<Slave>> slave = StartSlave(); ASSERT_SOME(slave); Future<Nothing> __recover = FUTURE_DISPATCH(_, &Slave::__recover); AWAIT_READY(__recover); // Retrieve the parameter passed as content type to this test. const ContentType contentType = GetParam(); hashmap<string, string> headers; headers["Accept"] = "foo"; // Only subscribe needs to 'Accept' JSON or protobuf. Call call; call.set_type(Call::SUBSCRIBE); call.mutable_framework_id()->set_value("dummy_framework_id"); call.mutable_executor_id()->set_value("dummy_executor_id"); Future<Response> response = process::http::streaming::post( slave.get(), "api/v1/executor", headers, serialize(contentType, call), stringify(contentType)); AWAIT_EXPECT_RESPONSE_STATUS_EQ(NotAcceptable().status, response); Shutdown(); }
// This test sends a unsupported Accept media type for the Accept // header. The response should be NotAcceptable in this case. TEST_P(ExecutorHttpApiTest, NotAcceptable) { Try<Owned<cluster::Master>> master = StartMaster(); ASSERT_SOME(master); Future<Nothing> __recover = FUTURE_DISPATCH(_, &Slave::__recover); Owned<MasterDetector> detector = master.get()->createDetector(); Try<Owned<cluster::Slave>> slave = StartSlave(detector.get()); ASSERT_SOME(slave); AWAIT_READY(__recover); // Wait for recovery to be complete. Clock::pause(); Clock::settle(); // Retrieve the parameter passed as content type to this test. const ContentType contentType = GetParam(); process::http::Headers headers; headers["Accept"] = "foo"; // Only subscribe needs to 'Accept' JSON or protobuf. Call call; call.mutable_framework_id()->set_value("dummy_framework_id"); call.mutable_executor_id()->set_value("dummy_executor_id"); call.set_type(Call::SUBSCRIBE); call.mutable_subscribe(); Future<Response> response = process::http::streaming::post( slave.get()->pid, "api/v1/executor", headers, serialize(contentType, call), stringify(contentType)); AWAIT_EXPECT_RESPONSE_STATUS_EQ(NotAcceptable().status, response); }
Future<http::Response> ResourceProviderManagerProcess::api( const http::Request& request, const Option<Principal>& principal) { if (request.method != "POST") { return MethodNotAllowed({"POST"}, request.method); } v1::resource_provider::Call v1Call; // 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 (!v1Call.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<v1::resource_provider::Call> parse = ::protobuf::parse<v1::resource_provider::Call>(value.get()); if (parse.isError()) { return BadRequest("Failed to convert JSON into Call protobuf: " + parse.error()); } v1Call = parse.get(); } else { return UnsupportedMediaType( string("Expecting 'Content-Type' of ") + APPLICATION_JSON + " or " + APPLICATION_PROTOBUF); } Call call = devolve(v1Call); Option<Error> error = validate(call); if (error.isSome()) { return BadRequest( "Failed to validate resource_provider::Call: " + error->message); } ContentType acceptType; if (request.acceptsMediaType(APPLICATION_JSON)) { acceptType = ContentType::JSON; } else if (request.acceptsMediaType(APPLICATION_PROTOBUF)) { acceptType = ContentType::PROTOBUF; } else { return NotAcceptable( string("Expecting 'Accept' to allow ") + "'" + APPLICATION_PROTOBUF + "' or '" + APPLICATION_JSON + "'"); } switch(call.type()) { case Call::UNKNOWN: { return NotImplemented(); } case Call::SUBSCRIBE: { Pipe pipe; OK ok; ok.headers["Content-Type"] = stringify(acceptType); ok.type = http::Response::PIPE; ok.reader = pipe.reader(); HttpConnection http(pipe.writer(), acceptType); subscribe(http, call.subscribe()); return ok; } case Call::UPDATE: { if (!resourceProviders.contains(call.resource_provider_id())) { return BadRequest("Resource provider cannot be found"); } auto resourceProvider = resourceProviders.at(call.resource_provider_id()); update(&resourceProvider, call.update()); return Accepted(); } } UNREACHABLE(); }