#vbmc: Add ProxyRequest and ProxyResponse ProxyRequest/Response inherit ecclesia::HttpClient::HttpRequest/Response This is done to improve code consistency and readability. This will also help us add new params in Request and Response structs. PiperOrigin-RevId: 704820928 Change-Id: Ie0f564733dfb4f9574d507570df9bd45fe78c455
diff --git a/cper/plugin.cc b/cper/plugin.cc index 4944916..c73d02f 100644 --- a/cper/plugin.cc +++ b/cper/plugin.cc
@@ -23,6 +23,7 @@ #include "proxy.h" #include "proxy_builder.h" #include "redfish_plugin.h" +#include "request_response.h" #include "sse_plugin/event.h" #include "events.pb.h" #include "sse_plugin/events_manager.h" @@ -39,8 +40,6 @@ constexpr absl::string_view kMachineHealthResourceName = "ots-cn-health-status"; constexpr absl::string_view kRequestIdHeader = "vbmc-internal:ReqID"; -using HttpResponse = ::ecclesia::HttpClient::HttpResponse; -using HttpRequest = ::ecclesia::HttpClient::HttpRequest; using ::ecclesia::HttpResponseCode::HTTP_CODE_BAD_REQUEST; using ::ecclesia::HttpResponseCode::HTTP_CODE_FORBIDDEN; using ::ecclesia::HttpResponseCode::HTTP_CODE_REQUEST_OK; @@ -58,8 +57,7 @@ } CperEventsPlugin::RequestAction CperEventsPlugin::PreprocessRequest( - RedfishPlugin::RequestVerb request_verb, - ecclesia::HttpClient::HttpRequest& request) { + RedfishPlugin::RequestVerb request_verb, ProxyRequest& request) { std::vector<std::pair<RedfishPlugin::RequestVerb, absl::string_view>> paths_to_handle = { {RedfishPlugin::RequestVerb::kPut, put_processed_events_path_}, @@ -69,10 +67,9 @@ return proxy_->GetRequestAction(request_verb, request, paths_to_handle); } -absl::StatusOr<ecclesia::HttpClient::HttpResponse> -CperEventsPlugin::HandleRequest( +absl::StatusOr<ProxyResponse> CperEventsPlugin::HandleRequest( RedfishPlugin::RequestVerb verb, - std::unique_ptr<ecclesia::HttpClient::HttpRequest> http_request) { + std::unique_ptr<ProxyRequest> http_request) { VLOG(kVlogVerbosity) << "Request uri: " << http_request->uri; // Making a copy to pass to latency monitor as request gets moved. @@ -96,20 +93,16 @@ /*field_values=*/{}); } - return ecclesia::HttpClient::HttpResponse{ - .code = HTTP_CODE_BAD_REQUEST, - .body = - absl::StrCat("Unable to handle request on uri: ", http_request->uri), - .headers = {{"Content-Type", "text/plain"}}, - }; + return ProxyResponse( + HTTP_CODE_BAD_REQUEST, + absl::StrCat("Unable to handle request on uri: ", http_request->uri), + {{"Content-Type", "text/plain"}}); } -absl::StatusOr<ecclesia::HttpClient::HttpResponse> -CperEventsPlugin::HandleGetHealth( - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request) { - ecclesia::HttpClient::HttpResponse response = { - .code = HTTP_CODE_BAD_REQUEST, - .headers = {{"Content-Type", "text/plain"}}}; +absl::StatusOr<ProxyResponse> CperEventsPlugin::HandleGetHealth( + std::unique_ptr<ProxyRequest> request) { + ProxyResponse response(HTTP_CODE_BAD_REQUEST, + {{"Content-Type", "text/plain"}}); if (events_manager_.IsServing() || events_manager_.IsStopping()) { response.code = HTTP_CODE_REQUEST_OK; nlohmann::json json_response = { @@ -137,12 +130,10 @@ return response; } -absl::StatusOr<ecclesia::HttpClient::HttpResponse> -CperEventsPlugin::HandlePutProcessedEvents( - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request) { - ecclesia::HttpClient::HttpResponse response = { - .code = HTTP_CODE_BAD_REQUEST, - .headers = {{"Content-Type", "text/plain"}}}; +absl::StatusOr<ProxyResponse> CperEventsPlugin::HandlePutProcessedEvents( + std::unique_ptr<ProxyRequest> request) { + ProxyResponse response(HTTP_CODE_BAD_REQUEST, + {{"Content-Type", "text/plain"}}); if (events_manager_.IsStopping()) { response.body = "vBMC is stopping"; @@ -232,9 +223,8 @@ return response; } -absl::Status CperEventsPlugin::Subscribe( - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request, - EventHandler* handler) { +absl::Status CperEventsPlugin::Subscribe(std::unique_ptr<ProxyRequest> request, + EventHandler* handler) { VLOG(kVlogVerbosity) << "Request uri: " << request->uri; if (proxy_->GetPath(request->uri) == subscribe_events_path_) { absl::string_view request_id = request->headers[kRequestIdHeader]; @@ -249,8 +239,7 @@ "Connection id is not set or is different"); } // Only accept the stream for the collector we received PUT request - auto response = - ecclesia::HttpClient::HttpResponse{.code = HTTP_CODE_REQUEST_OK}; + auto response = ProxyResponse(HTTP_CODE_REQUEST_OK); if (absl::Status status = handler->OnResponse(response); !status.ok()) { LOG(ERROR) << "OnResponse failed: " << status; return absl::InternalError(
diff --git a/cper/plugin.h b/cper/plugin.h index 6875f66..13ea597 100644 --- a/cper/plugin.h +++ b/cper/plugin.h
@@ -8,11 +8,11 @@ #include "absl/log/log.h" #include "absl/status/status.h" #include "absl/status/statusor.h" -#include "redfish_query_engine/http/client.h" #include "cper/manager.h" #include "proxy.h" #include "proxy_config.pb.h" #include "redfish_plugin.h" +#include "request_response.h" #include "sse_plugin/collector_storage_manager.h" #include "sse_plugin/storage_manager.h" #include "voyager/priority_queue.hpp" @@ -40,16 +40,14 @@ ~CperEventsPlugin() override; - RequestAction PreprocessRequest( - RedfishPlugin::RequestVerb verb, - ecclesia::HttpClient::HttpRequest& request) override; + RequestAction PreprocessRequest(RedfishPlugin::RequestVerb verb, + ProxyRequest& request) override; - absl::StatusOr<ecclesia::HttpClient::HttpResponse> HandleRequest( + absl::StatusOr<ProxyResponse> HandleRequest( RedfishPlugin::RequestVerb verb, - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request) override; - absl::Status Subscribe( - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request, - EventHandler* event_handler) override; + std::unique_ptr<ProxyRequest> request) override; + absl::Status Subscribe(std::unique_ptr<ProxyRequest> request, + EventHandler* event_handler) override; absl::Status Initialize(milotic::Proxy* proxy) override; @@ -57,12 +55,12 @@ CperEventsPlugin& operator=(const CperEventsPlugin&) = delete; private: - absl::StatusOr<ecclesia::HttpClient::HttpResponse> HandleGetHealth( - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request); - absl::StatusOr<ecclesia::HttpClient::HttpResponse> HandlePutProcessedEvents( - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request); - absl::StatusOr<ecclesia::HttpClient::HttpResponse> HandleFetchHealthRollup( - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request); + absl::StatusOr<ProxyResponse> HandleGetHealth( + std::unique_ptr<ProxyRequest> request); + absl::StatusOr<ProxyResponse> HandlePutProcessedEvents( + std::unique_ptr<ProxyRequest> request); + absl::StatusOr<ProxyResponse> HandleFetchHealthRollup( + std::unique_ptr<ProxyRequest> request); voyager::TelemetryPriorityQueue events_queue_; milotic::EventStorageManager* storage_manager_;
diff --git a/mock_redfish_plugin.h b/mock_redfish_plugin.h index b0fb040..d786e09 100644 --- a/mock_redfish_plugin.h +++ b/mock_redfish_plugin.h
@@ -8,8 +8,8 @@ #include "gmock.h" #include "absl/status/status.h" #include "absl/status/statusor.h" -#include "redfish_query_engine/http/client.h" #include "redfish_plugin.h" +#include "request_response.h" #include "sse/sse_parser.h" #include "google/protobuf/message.h" @@ -17,28 +17,24 @@ class MockRedfishPlugin : public milotic::RedfishPlugin { public: MOCK_METHOD(milotic::RedfishPlugin::RequestAction, PreprocessRequest, - (RequestVerb verb, ecclesia::HttpClient::HttpRequest& request), - (override)); - MOCK_METHOD(absl::StatusOr<ecclesia::HttpClient::HttpResponse>, HandleRequest, - (RequestVerb verb, - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request), + (RequestVerb verb, ProxyRequest& request), (override)); + MOCK_METHOD(absl::StatusOr<ProxyResponse>, HandleRequest, + (RequestVerb verb, std::unique_ptr<ProxyRequest> request), (override)); MOCK_METHOD(absl::Status, Initialize, (milotic::Proxy * proxy), (override)); MOCK_METHOD(absl::Status, Subscribe, - (std::unique_ptr<ecclesia::HttpClient::HttpRequest>, - RedfishPlugin::EventHandler*), + (std::unique_ptr<ProxyRequest>, RedfishPlugin::EventHandler*), (override)); MOCK_METHOD(absl::StatusOr<std::unique_ptr<RedfishPlugin::EventHandler>>, BidirectionalStream, - (std::unique_ptr<ecclesia::HttpClient::HttpRequest>, - RedfishPlugin::EventHandler*), + (std::unique_ptr<ProxyRequest>, RedfishPlugin::EventHandler*), (override)); }; class MockEventHandler : public milotic::RedfishPlugin::EventHandler { public: - MOCK_METHOD(absl::Status, OnResponse, - (const ecclesia::HttpClient::HttpResponse& response), (override)); + MOCK_METHOD(absl::Status, OnResponse, (const ProxyResponse& response), + (override)); MOCK_METHOD(absl::Status, OnEvent, (const milotic::ServerSentEvent& response), (override)); MOCK_METHOD(absl::Status, OnEvent, (const google::protobuf::Message& event_message),
diff --git a/monitoring.h b/monitoring.h index 293dab4..f067566 100644 --- a/monitoring.h +++ b/monitoring.h
@@ -11,7 +11,7 @@ #include "absl/time/clock.h" #include "absl/time/time.h" #include <source_location> -#include "redfish_query_engine/http/client.h" +#include "request_response.h" namespace milotic { @@ -106,8 +106,8 @@ }; template <typename... FieldT> -absl::StatusOr<ecclesia::HttpClient::HttpResponse> CaptureResponseCode( - const absl::StatusOr<ecclesia::HttpClient::HttpResponse>& http_response, +absl::StatusOr<ProxyResponse> CaptureResponseCode( + const absl::StatusOr<ProxyResponse>& http_response, metrics::EventCounter<absl::string_view, int, FieldT...>* event_counter, absl::string_view url, metrics::FieldValues<FieldT...> field_values, const std::source_location& location = std::source_location::current()) {
diff --git a/proxy.cc b/proxy.cc index a84bd15..486a8c5 100644 --- a/proxy.cc +++ b/proxy.cc
@@ -18,7 +18,6 @@ #include "absl/time/time.h" #include "absl/types/span.h" #include "redfish_query_engine/file/uds.h" -#include "redfish_query_engine/http/client.h" #include "grpcpp/impl/service_type.h" #include "grpcpp/security/auth_context.h" #include "grpcpp/server_builder.h" @@ -26,6 +25,7 @@ #include "metrics.h" #include "proxy_config.pb.h" #include "redfish_plugin.h" +#include "request_response.h" #include "resource_authz.h" #include "utils/status_macros.h" #include "voyager/deferrable_priority_queue.hpp" @@ -74,7 +74,7 @@ RedfishPlugin::RequestAction Proxy::GetRequestAction( RedfishPlugin::RequestVerb request_verb, - const ecclesia::HttpClient::HttpRequest& request, + const ProxyRequest& request, const std::vector<std::pair<RedfishPlugin::RequestVerb, absl::string_view>>& paths_to_handle) const { const std::string request_path = GetPath(request.uri); @@ -90,9 +90,9 @@ return action_if_no_match; } -std::unique_ptr<Proxy::Request> Proxy::CreateRequest( +std::unique_ptr<ProxyRequest> Proxy::CreateRequest( absl::string_view redfish_id) const { - auto request = std::make_unique<Proxy::Request>(); + auto request = std::make_unique<ProxyRequest>(); request->uri = GetUrl(redfish_id); // TODO: b/290975573 - Use better URL parsing. constexpr absl::string_view kSeparator = "://"; @@ -108,7 +108,7 @@ } absl::StatusOr<RedfishPlugin*> Proxy::GetRequestHandler( - RedfishPlugin::RequestVerb verb, Proxy::Request& request) { + RedfishPlugin::RequestVerb verb, ProxyRequest& request) { if (!handler_initialized_) return absl::UnavailableError("Handlers not initialized"); @@ -130,15 +130,15 @@ return absl::UnimplementedError("Request not handled."); } -absl::StatusOr<Proxy::Response> Proxy::DispatchRequest( +absl::StatusOr<ProxyResponse> Proxy::DispatchRequest( RedfishPlugin::RequestVerb verb, - std::unique_ptr<Proxy::Request> http_request) { + std::unique_ptr<ProxyRequest> http_request) { ASSIGN_OR_RETURN(RedfishPlugin * handler, GetRequestHandler(verb, *http_request)); return handler->HandleRequest(verb, std::move(http_request)); } -absl::Status Proxy::Subscribe(std::unique_ptr<Request> http_request, +absl::Status Proxy::Subscribe(std::unique_ptr<ProxyRequest> http_request, RedfishPlugin::EventHandler* event_handler) { ASSIGN_OR_RETURN( RedfishPlugin * handler, @@ -147,7 +147,7 @@ } absl::StatusOr<std::unique_ptr<RedfishPlugin::EventHandler>> -Proxy::BidirectionalStream(std::unique_ptr<Request> http_request, +Proxy::BidirectionalStream(std::unique_ptr<ProxyRequest> http_request, RedfishPlugin::EventHandler* event_handler) { ASSIGN_OR_RETURN( RedfishPlugin * handler, @@ -158,7 +158,7 @@ absl::StatusOr<std::unique_ptr<Proxy::RequestJob>> Proxy::DispatchRequestToQueue(RedfishPlugin::RequestVerb verb, - std::unique_ptr<Proxy::Request> http_request, + std::unique_ptr<ProxyRequest> http_request, Proxy::RequestPriority priority) { if (queue_ == nullptr) { return absl::UnavailableError("Queue not initialized"); @@ -265,7 +265,7 @@ handler(response_); } -absl::StatusOr<std::unique_ptr<Proxy::Request>> Proxy::CreateAuthorizedRequest( +absl::StatusOr<std::unique_ptr<ProxyRequest>> Proxy::CreateAuthorizedRequest( RedfishPlugin::RequestVerb verb, absl::string_view redfish_id, const grpc::AuthContext& auth_context) const { AuthorizationContext context{.grpc_context = auth_context,
diff --git a/proxy.h b/proxy.h index dacd1a6..63fffac 100644 --- a/proxy.h +++ b/proxy.h
@@ -19,7 +19,6 @@ #include "absl/time/time.h" #include "absl/types/span.h" #include "redfish_query_engine/file/uds.h" -#include "redfish_query_engine/http/client.h" #include "grpcpp/completion_queue.h" #include "grpcpp/impl/service_type.h" #include "grpcpp/security/auth_context.h" @@ -29,6 +28,7 @@ #include "grpcpp/support/status.h" #include "proxy_config.pb.h" #include "redfish_plugin.h" +#include "request_response.h" #include "resource_authz.h" #include "ssh_client.h" #include "voyager/deferrable_priority_queue.hpp" @@ -60,16 +60,14 @@ class Proxy { public: - using Response = ecclesia::HttpClient::HttpResponse; - using Request = ecclesia::HttpClient::HttpRequest; using RequestPriority = voyager::TelemetryPriorityQueue::QueuePriority; class RequestJob : public voyager::Job { public: using Handler = - absl::AnyInvocable<void(const absl::StatusOr<Proxy::Response>&)>; + absl::AnyInvocable<void(const absl::StatusOr<ProxyResponse>&)>; RequestJob(Proxy& proxy, RedfishPlugin::RequestVerb verb, - std::unique_ptr<Proxy::Request> request) + std::unique_ptr<ProxyRequest> request) : proxy_(proxy), verb_(verb), request_(std::move(request)) {} RequestJob(RequestJob&&) = delete; RequestJob(const RequestJob&) = delete; @@ -77,15 +75,15 @@ return static_cast<RequestJob&>(generic_job).RunImpl(); } void Handle(Handler handler) ABSL_LOCKS_EXCLUDED(handler_mutex_); - absl::StatusOr<Proxy::Response>& response() { return response_; } + absl::StatusOr<ProxyResponse>& response() { return response_; } private: absl::Status RunImpl() ABSL_LOCKS_EXCLUDED(handler_mutex_); Proxy& proxy_; RedfishPlugin::RequestVerb verb_; - std::unique_ptr<Proxy::Request> request_; - absl::StatusOr<Proxy::Response> response_; + std::unique_ptr<ProxyRequest> request_; + absl::StatusOr<ProxyResponse> response_; absl::Mutex handler_mutex_; Handler handler_ ABSL_GUARDED_BY(handler_mutex_); bool has_run_ ABSL_GUARDED_BY(handler_mutex_) = false; @@ -119,9 +117,10 @@ const Resources& GetResources() const { return resources_; } std::string GetUrl(absl::string_view redfish_id) const; std::string GetPath(absl::string_view url) const; - std::unique_ptr<Request> CreateRequest(absl::string_view redfish_id) const; + std::unique_ptr<ProxyRequest> CreateRequest( + absl::string_view redfish_id) const; - absl::StatusOr<std::unique_ptr<Request>> CreateAuthorizedRequest( + absl::StatusOr<std::unique_ptr<ProxyRequest>> CreateAuthorizedRequest( RedfishPlugin::RequestVerb verb, absl::string_view redfish_id, const grpc::AuthContext& auth_context) const; @@ -132,20 +131,22 @@ // If the request path does not match any path, the request will be passed to // the next plugin. RedfishPlugin::RequestAction GetRequestAction( - RedfishPlugin::RequestVerb verb, - const ecclesia::HttpClient::HttpRequest& request, + RedfishPlugin::RequestVerb verb, const ProxyRequest& request, const std::vector<std::pair<RedfishPlugin::RequestVerb, absl::string_view>>& paths_to_handle) const; - absl::StatusOr<Response> DispatchRequest( - RedfishPlugin::RequestVerb verb, std::unique_ptr<Request> http_request); + absl::StatusOr<ProxyResponse> DispatchRequest( + RedfishPlugin::RequestVerb verb, + std::unique_ptr<ProxyRequest> http_request); absl::StatusOr<std::unique_ptr<RequestJob>> DispatchRequestToQueue( - RedfishPlugin::RequestVerb verb, std::unique_ptr<Request> http_request, + RedfishPlugin::RequestVerb verb, + std::unique_ptr<ProxyRequest> http_request, RequestPriority priority = RequestPriority::kLow); std::unique_ptr<RequestJob> CreateRequestJob( - RedfishPlugin::RequestVerb verb, std::unique_ptr<Request> http_request) { + RedfishPlugin::RequestVerb verb, + std::unique_ptr<ProxyRequest> http_request) { return std::make_unique<RequestJob>(*this, verb, std::move(http_request)); } @@ -156,11 +157,11 @@ absl::string_view GetNetworkEndpoint() const { return network_endpoint_; } - absl::Status Subscribe(std::unique_ptr<Request> http_request, + absl::Status Subscribe(std::unique_ptr<ProxyRequest> http_request, RedfishPlugin::EventHandler* handler); absl::StatusOr<std::unique_ptr<RedfishPlugin::EventHandler>> - BidirectionalStream(std::unique_ptr<Request> http_request, + BidirectionalStream(std::unique_ptr<ProxyRequest> http_request, RedfishPlugin::EventHandler* handler); absl::Status ConfigGrpcAndStart( @@ -229,7 +230,7 @@ } absl::StatusOr<RedfishPlugin*> GetRequestHandler( - RedfishPlugin::RequestVerb verb, Proxy::Request& request); + RedfishPlugin::RequestVerb verb, ProxyRequest& request); std::string network_endpoint_; voyager::DeferrablePriorityQueue* queue_;
diff --git a/proxy_redfishv1_impl.cc b/proxy_redfishv1_impl.cc index 4caa0a6..9c65dd8 100644 --- a/proxy_redfishv1_impl.cc +++ b/proxy_redfishv1_impl.cc
@@ -15,6 +15,7 @@ #include "grpcpp/support/status.h" #include "proxy.h" #include "redfish_plugin.h" +#include "request_response.h" #include "voyager/priority_queue.hpp" namespace milotic { @@ -39,12 +40,12 @@ grpc::Status ProxyRedfishV1Impl::DispatchRequest( RedfishPlugin::RequestVerb verb, const ::redfish::v1::Request *request, redfish::v1::Response *response, const grpc::AuthContext &auth_context) { - absl::StatusOr<std::unique_ptr<Proxy::Request>> status_or_http_request = + absl::StatusOr<std::unique_ptr<ProxyRequest>> status_or_http_request = proxy_.CreateAuthorizedRequest(verb, request->url(), auth_context); if (!status_or_http_request.ok()) { return ConvertStatus(status_or_http_request.status()); } - std::unique_ptr<Proxy::Request> http_request = + std::unique_ptr<ProxyRequest> http_request = *std::move(status_or_http_request); /* Copy http request headers to request */ @@ -75,7 +76,7 @@ "Job error"); } - absl::StatusOr<Proxy::Response> &result = job.value()->response(); + absl::StatusOr<ProxyResponse> &result = job.value()->response(); if (!result.ok()) return ConvertStatus(result.status()); /* Copy response headers back */
diff --git a/proxy_redfishv1_impl_test.cc b/proxy_redfishv1_impl_test.cc index 5320eb3..bcb0439 100644 --- a/proxy_redfishv1_impl_test.cc +++ b/proxy_redfishv1_impl_test.cc
@@ -22,6 +22,7 @@ #include "proxy.h" #include "proxy_config.pb.h" #include "redfish_plugin.h" +#include "request_response.h" #include "voyager/deferrable_priority_queue.hpp" #include "util/task/status_macros.h" @@ -41,6 +42,8 @@ using ::testing::status::StatusIs; using ::milotic::Proxy; +using ::milotic::ProxyRequest; +using ::milotic::ProxyResponse; using ::milotic::RedfishPlugin; using MockPlugin = ::milotic::MockRedfishPlugin; @@ -89,17 +92,17 @@ CreateProxyService("test_endpoint", &queue)); EXPECT_CALL(test_server.plugin, PreprocessRequest) .WillRepeatedly(Return(RedfishPlugin::RequestAction::kHandle)); - Proxy::Request converted_http_request; + ProxyRequest converted_http_request; EXPECT_CALL(test_server.plugin, HandleRequest(RedfishPlugin::RequestVerb::kGet, - Pointee(Field("uri", &Proxy::Request::uri, + Pointee(Field("uri", &ProxyRequest::uri, "test_endpoint/some/resource")))) .WillOnce(DoAll(SaveArgPointee<1>(&converted_http_request), - Return(Proxy::Response{ - .code = 200, - .body = R"json({"Name": "test json"})json", - .headers = {{"Content-Type", "application/json"}, - {"OData-Version", "4.0"}}}))); + Return(ProxyResponse{ + {.code = 200, + .body = R"json({"Name": "test json"})json", + .headers = {{"Content-Type", "application/json"}, + {"OData-Version", "4.0"}}}}))); auto request = ecclesia::ParseTextAsProtoOrDie<redfish::v1::Request>(R"pb( url: "/some/resource" @@ -134,13 +137,13 @@ HandleRequest( RedfishPlugin::RequestVerb::kPost, Pointee(AllOf( - Field("uri", &Proxy::Request::uri, "test_endpoint/some/resource"), - Field("headers", &Proxy::Request::headers, + Field("uri", &ProxyRequest::uri, "test_endpoint/some/resource"), + Field("headers", &ProxyRequest::headers, Contains(Pair("Content-Type", "application/json"))))))) .WillOnce(Return( - Proxy::Response{.code = 200, - .body = R"json({"Name": "test json response"})json", - .headers = {{"Content-Type", "application/json"}}})); + ProxyResponse{{.code = 200, + .body = R"json({"Name": "test json response"})json", + .headers = {{"Content-Type", "application/json"}}}})); auto request = ecclesia::ParseTextAsProtoOrDie<redfish::v1::Request>(R"pb( url: "/some/resource" @@ -167,13 +170,13 @@ HandleRequest( RedfishPlugin::RequestVerb::kGet, Pointee(AllOf( - Field("uri", &Proxy::Request::uri, "test_endpoint/some/resource"), - Field("headers", &Proxy::Request::headers, + Field("uri", &ProxyRequest::uri, "test_endpoint/some/resource"), + Field("headers", &ProxyRequest::headers, Contains(Pair("Host", "test_endpoint"))))))) .WillOnce(Return( - Proxy::Response{.code = 200, - .body = R"json({"Name": "test json"})json", - .headers = {{"Content-Type", "application/json"}}})); + ProxyResponse{{.code = 200, + .body = R"json({"Name": "test json"})json", + .headers = {{"Content-Type", "application/json"}}}})); auto request = ecclesia::ParseTextAsProtoOrDie<redfish::v1::Request>(R"pb( url: "/some/resource" @@ -200,16 +203,16 @@ HandleRequest( RedfishPlugin::RequestVerb::kGet, Pointee(AllOf( - Field("uri", &Proxy::Request::uri, "test_endpoint/some/resource"), - Field("headers", &Proxy::Request::headers, + Field("uri", &ProxyRequest::uri, "test_endpoint/some/resource"), + Field("headers", &ProxyRequest::headers, Contains(Pair("Host", "test_endpoint"))))))) .WillOnce(Return( - Proxy::Response{.code = 200, - .body = "some data", - .headers = { - {"OData-Version", "4.0"}, - {"Content-Type", "application/octet-stream"}, - }})); + ProxyResponse{{.code = 200, + .body = "some data", + .headers = { + {"OData-Version", "4.0"}, + {"Content-Type", "application/octet-stream"}, + }}})); auto request = ecclesia::ParseTextAsProtoOrDie<redfish::v1::Request>(R"pb( url: "/some/resource" @@ -239,15 +242,15 @@ HandleRequest( RedfishPlugin::RequestVerb::kGet, Pointee(AllOf( - Field("uri", &Proxy::Request::uri, "test_endpoint/some/resource"), - Field("headers", &Proxy::Request::headers, + Field("uri", &ProxyRequest::uri, "test_endpoint/some/resource"), + Field("headers", &ProxyRequest::headers, Contains(Pair("Host", "test_endpoint"))))))) .WillOnce(Return( - Proxy::Response{.code = 200, - .body = R"json({"Name": "test json response"})json", - .headers = { - {"OData-Version", "4.0"}, - }})); + ProxyResponse{{.code = 200, + .body = R"json({"Name": "test json response"})json", + .headers = { + {"OData-Version", "4.0"}, + }}})); auto request = ecclesia::ParseTextAsProtoOrDie<redfish::v1::Request>(R"pb( url: "/some/resource"
diff --git a/proxy_test.cc b/proxy_test.cc index ea5553a..2fe16f3 100644 --- a/proxy_test.cc +++ b/proxy_test.cc
@@ -17,11 +17,11 @@ #include "absl/time/clock.h" #include "absl/time/time.h" #include "absl/types/span.h" -#include "redfish_query_engine/http/client.h" #include "redfish_query_engine/http/codes.h" #include "fake_auth_context.h" #include "mock_redfish_plugin.h" #include "redfish_plugin.h" +#include "request_response.h" #include "resource_authz.h" #include "sse/sse_parser.h" #include "voyager/deferrable_priority_queue.hpp" @@ -50,8 +50,8 @@ using ::google::protobuf::contrib::parse_proto::ParseTextProtoOrDie; -using HttpRequest = ecclesia::HttpClient::HttpRequest; -using HttpResponse = ecclesia::HttpClient::HttpResponse; +using ProxyRequest = milotic::ProxyRequest; +using ProxyResponse = milotic::ProxyResponse; using RequestVerb = milotic::RedfishPlugin::RequestVerb; using RequestAction = milotic::RedfishPlugin::RequestAction; using MockPlugin = milotic::MockRedfishPlugin; @@ -59,12 +59,11 @@ TEST(TestPlugins, no_plugins_ok) { milotic::Proxy proxy("test_endpoint"); - auto request = std::make_unique<HttpRequest>(); + auto request = std::make_unique<ProxyRequest>(); request->uri = "test/uri"; - absl::StatusOr<ecclesia::HttpClient::HttpResponse> result = - proxy.DispatchRequest(milotic::RedfishPlugin::RequestVerb::kGet, - std::move(request)); + absl::StatusOr<ProxyResponse> result = proxy.DispatchRequest( + milotic::RedfishPlugin::RequestVerb::kGet, std::move(request)); EXPECT_THAT(result, StatusIs(absl::StatusCode::kUnimplemented)); } @@ -73,33 +72,33 @@ EXPECT_CALL(*default_plugin, Initialize).WillOnce(Return(absl::OkStatus())); EXPECT_CALL(*default_plugin, PreprocessRequest(RequestVerb::kGet, - Field(&HttpRequest::uri, "test/uri"))) + Field(&ProxyRequest::uri, "test/uri"))) .WillOnce(Return(RequestAction::kHandle)); EXPECT_CALL(*default_plugin, HandleRequest(RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, "test/uri")))) - .WillOnce(Invoke([](RequestVerb, std::unique_ptr<HttpRequest> req) { + Pointee(Field(&ProxyRequest::uri, "test/uri")))) + .WillOnce(Invoke([](RequestVerb, std::unique_ptr<ProxyRequest> req) { req.reset(); // take ownership and delete - return HttpResponse{ + return ProxyResponse{{ .code = ecclesia::HTTP_CODE_BAD_REQUEST, .body = "test body.", .headers = {{"test-header", "test-header-value"}}, - }; + }}; })); auto plugin = std::make_unique<StrictMock<MockPlugin>>(); EXPECT_CALL(*plugin, Initialize).WillOnce(Return(absl::OkStatus())); EXPECT_CALL(*plugin, PreprocessRequest(RequestVerb::kGet, - Field(&HttpRequest::uri, "test/uri"))) + Field(&ProxyRequest::uri, "test/uri"))) .WillOnce(Return(RequestAction::kNext)); std::unique_ptr<milotic::RedfishPlugin> plugins[] = { std::move(plugin), std::move(default_plugin)}; milotic::Proxy proxy("test_endpoint", absl::MakeSpan(plugins)); - auto request = std::make_unique<HttpRequest>(); + auto request = std::make_unique<ProxyRequest>(); request->uri = "test/uri"; - absl::StatusOr<ecclesia::HttpClient::HttpResponse> result = + absl::StatusOr<ProxyResponse> result = proxy.DispatchRequest(RequestVerb::kGet, std::move(request)); EXPECT_THAT(result, IsOkAndHolds(FieldsAre( @@ -111,25 +110,25 @@ auto plugin = std::make_unique<StrictMock<MockPlugin>>(); EXPECT_CALL(*plugin, Initialize).WillOnce(Return(absl::OkStatus())); EXPECT_CALL(*plugin, PreprocessRequest(RequestVerb::kGet, - Field(&HttpRequest::uri, "test/uri"))) + Field(&ProxyRequest::uri, "test/uri"))) .WillOnce(Return(RequestAction::kHandle)); EXPECT_CALL(*plugin, HandleRequest(RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, "test/uri")))) - .WillOnce(Invoke([](RequestVerb, std::unique_ptr<HttpRequest> req) { - return HttpResponse{ + Pointee(Field(&ProxyRequest::uri, "test/uri")))) + .WillOnce(Invoke([](RequestVerb, std::unique_ptr<ProxyRequest> req) { + return ProxyResponse{{ .code = ecclesia::HTTP_CODE_REQUEST_OK, .body = "plugin body.", - }; + }}; })); std::unique_ptr<milotic::RedfishPlugin> plugins[] = {std::move(plugin)}; milotic::Proxy proxy("test_endpoint", absl::MakeSpan(plugins)); - auto request = std::make_unique<HttpRequest>(); + auto request = std::make_unique<ProxyRequest>(); request->uri = "test/uri"; - absl::StatusOr<ecclesia::HttpClient::HttpResponse> result = + absl::StatusOr<ProxyResponse> result = proxy.DispatchRequest(RequestVerb::kGet, std::move(request)); EXPECT_THAT(result, IsOkAndHolds(FieldsAre(ecclesia::HTTP_CODE_REQUEST_OK, "plugin body.", _))); @@ -139,22 +138,22 @@ auto plugin = std::make_unique<StrictMock<MockPlugin>>(); EXPECT_CALL(*plugin, Initialize).WillOnce(Return(absl::OkStatus())); EXPECT_CALL(*plugin, PreprocessRequest(RequestVerb::kGet, - Field(&HttpRequest::uri, "test/uri"))) + Field(&ProxyRequest::uri, "test/uri"))) .WillOnce(Return(RequestAction::kHandle)); EXPECT_CALL(*plugin, HandleRequest(RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, "test/uri")))) - .WillOnce(Invoke([](RequestVerb, std::unique_ptr<HttpRequest> req) { + Pointee(Field(&ProxyRequest::uri, "test/uri")))) + .WillOnce(Invoke([](RequestVerb, std::unique_ptr<ProxyRequest> req) { return absl::InternalError("plugin error"); })); std::unique_ptr<milotic::RedfishPlugin> plugins[] = {std::move(plugin)}; milotic::Proxy proxy("test_endpoint", absl::MakeSpan(plugins)); - auto request = std::make_unique<HttpRequest>(); + auto request = std::make_unique<ProxyRequest>(); request->uri = "test/uri"; - absl::StatusOr<ecclesia::HttpClient::HttpResponse> result = + absl::StatusOr<ProxyResponse> result = proxy.DispatchRequest(RequestVerb::kGet, std::move(request)); EXPECT_THAT(result, StatusIs(absl::StatusCode::kInternal)); } @@ -178,26 +177,26 @@ EXPECT_CALL(*default_plugin, Initialize).WillOnce(Return(absl::OkStatus())); EXPECT_CALL(*default_plugin, PreprocessRequest(RequestVerb::kGet, - Field(&HttpRequest::uri, "test/uri/modified"))) + Field(&ProxyRequest::uri, "test/uri/modified"))) .WillOnce(Return(RequestAction::kHandle)); EXPECT_CALL( *default_plugin, HandleRequest(RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, "test/uri/modified")))) - .WillOnce(Invoke([](RequestVerb, std::unique_ptr<HttpRequest> req) { + Pointee(Field(&ProxyRequest::uri, "test/uri/modified")))) + .WillOnce(Invoke([](RequestVerb, std::unique_ptr<ProxyRequest> req) { req.reset(); // take ownership and delete - return HttpResponse{ + return ProxyResponse{{ .code = ecclesia::HTTP_CODE_BAD_REQUEST, .body = "test body.", .headers = {{"test-header", "test-header-value"}}, - }; + }}; })); auto plugin = std::make_unique<StrictMock<MockPlugin>>(); EXPECT_CALL(*plugin, Initialize).WillOnce(Return(absl::OkStatus())); EXPECT_CALL(*plugin, PreprocessRequest(RequestVerb::kGet, - Field(&HttpRequest::uri, "test/uri"))) - .WillOnce(Invoke([](RequestVerb, HttpRequest& request) { + Field(&ProxyRequest::uri, "test/uri"))) + .WillOnce(Invoke([](RequestVerb, ProxyRequest& request) { request.uri = "test/uri/modified"; return RequestAction::kNext; })); @@ -206,10 +205,10 @@ std::move(plugin), std::move(default_plugin)}; milotic::Proxy proxy("test_endpoint", absl::MakeSpan(plugins)); - auto request = std::make_unique<HttpRequest>(); + auto request = std::make_unique<ProxyRequest>(); request->uri = "test/uri"; - absl::StatusOr<ecclesia::HttpClient::HttpResponse> result = + absl::StatusOr<ProxyResponse> result = proxy.DispatchRequest(RequestVerb::kGet, std::move(request)); EXPECT_THAT(result, IsOkAndHolds(FieldsAre( @@ -221,24 +220,24 @@ auto plugin = std::make_unique<StrictMock<MockPlugin>>(); EXPECT_CALL(*plugin, Initialize).WillOnce(Return(absl::OkStatus())); EXPECT_CALL(*plugin, PreprocessRequest(RequestVerb::kGet, - Field(&HttpRequest::uri, "test/uri"))) + Field(&ProxyRequest::uri, "test/uri"))) .WillOnce(Return(RequestAction::kDrop)); std::unique_ptr<milotic::RedfishPlugin> plugins[] = {std::move(plugin)}; milotic::Proxy proxy("test_endpoint", absl::MakeSpan(plugins)); - auto request = std::make_unique<HttpRequest>(); + auto request = std::make_unique<ProxyRequest>(); request->uri = "test/uri"; - absl::StatusOr<ecclesia::HttpClient::HttpResponse> result = + absl::StatusOr<ProxyResponse> result = proxy.DispatchRequest(RequestVerb::kGet, std::move(request)); EXPECT_THAT(result, StatusIs(absl::StatusCode::kUnavailable)); } constexpr int kFakeEventsCount = 2; template <typename Event = milotic::ServerSentEvent> -absl::Status FakeEvents(const HttpResponse& response, - std::unique_ptr<HttpRequest> request, +absl::Status FakeEvents(const ProxyResponse& response, + std::unique_ptr<ProxyRequest> request, milotic::RedfishPlugin::EventHandler* event_handler) { absl::Status status = event_handler->OnResponse(response); if (!status.ok()) return status; @@ -256,23 +255,23 @@ auto plugin = std::make_unique<StrictMock<MockPlugin>>(); EXPECT_CALL(*plugin, Initialize).WillOnce(Return(absl::OkStatus())); EXPECT_CALL(*plugin, PreprocessRequest(RequestVerb::kSubscribe, - Field(&HttpRequest::uri, "test/uri"))) + Field(&ProxyRequest::uri, "test/uri"))) .WillOnce(Return(RequestAction::kHandle)); EXPECT_CALL(*plugin, - Subscribe(Pointee(Field(&HttpRequest::uri, "test/uri")), _)) + Subscribe(Pointee(Field(&ProxyRequest::uri, "test/uri")), _)) .WillOnce( - Invoke(absl::bind_front(FakeEvents<>, HttpResponse{.code = 200}))); + Invoke(absl::bind_front(FakeEvents<>, ProxyResponse{{.code = 200}}))); std::unique_ptr<milotic::RedfishPlugin> plugins[] = {std::move(plugin)}; milotic::Proxy proxy("test_endpoint", absl::MakeSpan(plugins)); - auto request = std::make_unique<HttpRequest>(); + auto request = std::make_unique<ProxyRequest>(); request->uri = "test/uri"; MockEventHandler handler; ON_CALL(handler, IsCancelled()).WillByDefault(Return(false)); ::testing::InSequence event_sequence; - EXPECT_CALL(handler, OnResponse(Field(&HttpResponse::code, 200))) + EXPECT_CALL(handler, OnResponse(Field(&ProxyResponse::code, 200))) .WillOnce(Return(absl::OkStatus())); EXPECT_CALL(handler, OnEvent(MatcherCast<const Event&>(Field(&Event::id, "0")))) @@ -287,22 +286,22 @@ auto plugin = std::make_unique<StrictMock<MockPlugin>>(); EXPECT_CALL(*plugin, Initialize).WillOnce(Return(absl::OkStatus())); EXPECT_CALL(*plugin, PreprocessRequest(RequestVerb::kSubscribe, - Field(&HttpRequest::uri, "test/uri"))) + Field(&ProxyRequest::uri, "test/uri"))) .WillOnce(Return(RequestAction::kHandle)); EXPECT_CALL(*plugin, - Subscribe(Pointee(Field(&HttpRequest::uri, "test/uri")), _)) + Subscribe(Pointee(Field(&ProxyRequest::uri, "test/uri")), _)) .WillOnce( - Invoke(absl::bind_front(FakeEvents<>, HttpResponse{.code = 200}))); + Invoke(absl::bind_front(FakeEvents<>, ProxyResponse{{.code = 200}}))); std::unique_ptr<milotic::RedfishPlugin> plugins[] = {std::move(plugin)}; milotic::Proxy proxy("test_endpoint", absl::MakeSpan(plugins)); - auto request = std::make_unique<HttpRequest>(); + auto request = std::make_unique<ProxyRequest>(); request->uri = "test/uri"; StrictMock<MockEventHandler> handler; ON_CALL(handler, IsCancelled()).WillByDefault(Return(false)); - EXPECT_CALL(handler, OnResponse(Field(&HttpResponse::code, 200))) + EXPECT_CALL(handler, OnResponse(Field(&ProxyResponse::code, 200))) .WillOnce(Return(absl::InternalError("Test error"))); EXPECT_THAT(proxy.Subscribe(std::move(request), &handler), @@ -314,23 +313,23 @@ auto plugin = std::make_unique<StrictMock<MockPlugin>>(); EXPECT_CALL(*plugin, Initialize).WillOnce(Return(absl::OkStatus())); EXPECT_CALL(*plugin, PreprocessRequest(RequestVerb::kSubscribe, - Field(&HttpRequest::uri, "test/uri"))) + Field(&ProxyRequest::uri, "test/uri"))) .WillOnce(Return(RequestAction::kHandle)); EXPECT_CALL(*plugin, - Subscribe(Pointee(Field(&HttpRequest::uri, "test/uri")), _)) + Subscribe(Pointee(Field(&ProxyRequest::uri, "test/uri")), _)) .WillOnce( - Invoke(absl::bind_front(FakeEvents<>, HttpResponse{.code = 200}))); + Invoke(absl::bind_front(FakeEvents<>, ProxyResponse{{.code = 200}}))); std::unique_ptr<milotic::RedfishPlugin> plugins[] = {std::move(plugin)}; milotic::Proxy proxy("test_endpoint", absl::MakeSpan(plugins)); - auto request = std::make_unique<HttpRequest>(); + auto request = std::make_unique<ProxyRequest>(); request->uri = "test/uri"; StrictMock<MockEventHandler> handler; EXPECT_CALL(handler, IsCancelled()).WillRepeatedly(Return(false)); ::testing::InSequence event_sequence; - EXPECT_CALL(handler, OnResponse(Field(&HttpResponse::code, 200))) + EXPECT_CALL(handler, OnResponse(Field(&ProxyResponse::code, 200))) .WillOnce(Return(absl::OkStatus())); EXPECT_CALL(handler, OnEvent(MatcherCast<const Event&>(Field(&Event::id, "0")))) @@ -344,20 +343,20 @@ auto plugin = std::make_unique<StrictMock<MockPlugin>>(); EXPECT_CALL(*plugin, Initialize).WillOnce(Return(absl::OkStatus())); EXPECT_CALL(*plugin, PreprocessRequest(RequestVerb::kBidirectionalStream, - Field(&HttpRequest::uri, "test/uri"))) + Field(&ProxyRequest::uri, "test/uri"))) .WillOnce(Return(RequestAction::kHandle)); auto write_handler = std::make_unique<MockEventHandler>(); auto* write_handler_ptr = write_handler.get(); StrictMock<MockEventHandler> read_handler; - EXPECT_CALL(*plugin, - BidirectionalStream(Pointee(Field(&HttpRequest::uri, "test/uri")), - Pointer(&read_handler))) + EXPECT_CALL(*plugin, BidirectionalStream( + Pointee(Field(&ProxyRequest::uri, "test/uri")), + Pointer(&read_handler))) .WillOnce(Return(std::move(write_handler))); std::unique_ptr<milotic::RedfishPlugin> plugins[] = {std::move(plugin)}; milotic::Proxy proxy("test_endpoint", absl::MakeSpan(plugins)); - auto request = std::make_unique<HttpRequest>(); + auto request = std::make_unique<ProxyRequest>(); request->uri = "test/uri"; EXPECT_THAT(proxy.BidirectionalStream(std::move(request), &read_handler), @@ -366,15 +365,13 @@ TEST(TestCreateRequest, EndpointNameIsCopiedToHostHeader) { milotic::Proxy proxy("hostname.test:1234"); - std::unique_ptr<milotic::Proxy::Request> request = - proxy.CreateRequest("some/resource"); + std::unique_ptr<ProxyRequest> request = proxy.CreateRequest("some/resource"); EXPECT_THAT(request->headers, Contains(Pair("Host", "hostname.test:1234"))); } TEST(TestCreateRequest, EndpointProtocolIsRemoved) { milotic::Proxy proxy("https://hostname.test:1234"); - std::unique_ptr<milotic::Proxy::Request> request = - proxy.CreateRequest("some/resource"); + std::unique_ptr<ProxyRequest> request = proxy.CreateRequest("some/resource"); EXPECT_THAT(request->headers, Contains(Pair("Host", "hostname.test:1234"))); } @@ -384,7 +381,7 @@ EXPECT_CALL(*plugin, PreprocessRequest) .WillOnce(Return(RequestAction::kHandle)); EXPECT_CALL(*plugin, HandleRequest(RequestVerb::kGet, _)) - .WillOnce(Return(HttpResponse{.code = 200, .body = "test body"})); + .WillOnce(Return(ProxyResponse{{.code = 200, .body = "test body"}})); voyager::DeferrablePriorityQueue queue(1); std::unique_ptr<milotic::RedfishPlugin> plugins[] = {std::move(plugin)}; @@ -394,7 +391,7 @@ auto request_job = proxy.CreateRequestJob( RequestVerb::kGet, proxy.CreateRequest("/test_resource")); - absl::StatusOr<HttpResponse> called_with; + absl::StatusOr<ProxyResponse> called_with; request_job->Handle(handler.AsStdFunction()); ASSERT_OK(proxy.DispatchRequestToQueue(std::move(request_job))); @@ -402,8 +399,8 @@ ASSERT_OK(queue.ProcessQueue(1)); EXPECT_THAT(called_with, - IsOkAndHolds(AllOf(Field(&HttpResponse::code, 200), - Field(&HttpResponse::body, "test body")))); + IsOkAndHolds(AllOf(Field(&ProxyResponse::code, 200), + Field(&ProxyResponse::body, "test body")))); } TEST(TestDispatchRequest, HandlerRunsIfRequestIsAlreadyCompleted) { @@ -412,7 +409,7 @@ EXPECT_CALL(*plugin, PreprocessRequest) .WillOnce(Return(RequestAction::kHandle)); EXPECT_CALL(*plugin, HandleRequest(RequestVerb::kGet, _)) - .WillOnce(Return(HttpResponse{.code = 200, .body = "test body"})); + .WillOnce(Return(ProxyResponse{{.code = 200, .body = "test body"}})); voyager::DeferrablePriorityQueue queue(1); std::unique_ptr<milotic::RedfishPlugin> plugins[] = {std::move(plugin)}; @@ -427,8 +424,8 @@ ASSERT_OK(queue.ProcessQueue(1)); EXPECT_CALL( handler, - Call(IsOkAndHolds(AllOf(Field(&HttpResponse::code, 200), - Field(&HttpResponse::body, "test body"))))); + Call(IsOkAndHolds(AllOf(Field(&ProxyResponse::code, 200), + Field(&ProxyResponse::body, "test body"))))); job->Handle(handler.AsStdFunction()); } @@ -438,7 +435,7 @@ EXPECT_CALL(*plugin, PreprocessRequest) .WillRepeatedly(Return(RequestAction::kHandle)); EXPECT_CALL(*plugin, HandleRequest(RequestVerb::kGet, _)) - .WillOnce(Return(HttpResponse{.code = 200, .body = "test body"})); + .WillOnce(Return(ProxyResponse{{.code = 200, .body = "test body"}})); voyager::DeferrablePriorityQueue queue(1); std::unique_ptr<milotic::RedfishPlugin> plugins[] = {std::move(plugin)}; @@ -448,7 +445,7 @@ auto request_job = proxy.CreateRequestJob( RequestVerb::kGet, proxy.CreateRequest("/test_resource")); - absl::StatusOr<HttpResponse> called_with; + absl::StatusOr<ProxyResponse> called_with; request_job->Handle(handler.AsStdFunction()); absl::Time run_after = absl::Now() + absl::Seconds(1); ASSERT_OK(proxy.DispatchRequestToQueue(std::move(request_job), @@ -458,8 +455,8 @@ absl::Time ran_at; EXPECT_CALL( handler, - Call(IsOkAndHolds(AllOf(Field(&HttpResponse::code, 200), - Field(&HttpResponse::body, "test body"))))) + Call(IsOkAndHolds(AllOf(Field(&ProxyResponse::code, 200), + Field(&ProxyResponse::body, "test body"))))) .WillOnce(InvokeWithoutArgs([&ran_at] { ran_at = absl::Now(); })); ASSERT_OK(queue.ProcessQueue(1)); @@ -480,7 +477,7 @@ auto request_job = proxy.CreateRequestJob( RequestVerb::kGet, proxy.CreateRequest("/test_resource")); - absl::StatusOr<HttpResponse> called_with; + absl::StatusOr<ProxyResponse> called_with; request_job->Handle(handler.AsStdFunction()); ASSERT_OK(proxy.DispatchRequestToQueue(std::move(request_job))); @@ -493,7 +490,7 @@ TEST(TestProxyConfig, DispatchRequestToQueueFailsIfNotConfigured) { milotic::Proxy proxy("test_endpoint"); EXPECT_THAT(proxy.DispatchRequestToQueue(RequestVerb::kGet, - std::make_unique<HttpRequest>()), + std::make_unique<ProxyRequest>()), StatusIs(absl::StatusCode::kUnavailable)); } @@ -507,40 +504,37 @@ TEST(TestGetRequestAction, NoMatchReturnsNext) { milotic::Proxy proxy("test_endpoint"); - EXPECT_EQ(proxy.GetRequestAction(RequestVerb::kGet, - HttpRequest{.uri = "/test/resource"}, - {{RequestVerb::kGet, "/other/resource"}}), - RequestAction::kNext); + EXPECT_EQ( + proxy.GetRequestAction(RequestVerb::kGet, ProxyRequest("/test/resource"), + {{RequestVerb::kGet, "/other/resource"}}), + RequestAction::kNext); } TEST(TestGetRequestAction, MatchReturnsHandle) { milotic::Proxy proxy("test_endpoint"); - EXPECT_EQ( - proxy.GetRequestAction(RequestVerb::kGet, - HttpRequest{.uri = "test_endpoint/test/resource"}, - {{RequestVerb::kGet, "/other/resource"}, - {RequestVerb::kGet, "/test/resource"}}), - RequestAction::kHandle); + EXPECT_EQ(proxy.GetRequestAction(RequestVerb::kGet, + ProxyRequest("test_endpoint/test/resource"), + {{RequestVerb::kGet, "/other/resource"}, + {RequestVerb::kGet, "/test/resource"}}), + RequestAction::kHandle); } TEST(TestGetRequestAction, ResourceWithMultipleVerbsReturnsHandle) { milotic::Proxy proxy("test_endpoint"); - EXPECT_EQ( - proxy.GetRequestAction(RequestVerb::kGet, - HttpRequest{.uri = "test_endpoint/test/resource"}, - {{RequestVerb::kPost, "/test/resource"}, - {RequestVerb::kGet, "/test/resource"}, - {RequestVerb::kPatch, "/test/resource"}}), - RequestAction::kHandle); + EXPECT_EQ(proxy.GetRequestAction(RequestVerb::kGet, + ProxyRequest("test_endpoint/test/resource"), + {{RequestVerb::kPost, "/test/resource"}, + {RequestVerb::kGet, "/test/resource"}, + {RequestVerb::kPatch, "/test/resource"}}), + RequestAction::kHandle); } TEST(TestGetRequestAction, NonMatchingVerbReturnsDrop) { milotic::Proxy proxy("test_endpoint"); - EXPECT_EQ( - proxy.GetRequestAction(RequestVerb::kGet, - HttpRequest{.uri = "test_endpoint/test/resource"}, - {{RequestVerb::kPost, "/test/resource"}}), - RequestAction::kDrop); + EXPECT_EQ(proxy.GetRequestAction(RequestVerb::kGet, + ProxyRequest("test_endpoint/test/resource"), + {{RequestVerb::kPost, "/test/resource"}}), + RequestAction::kDrop); } TEST(TestProxyAuthz, AuthorizationPolicyIsApplied) {
diff --git a/proxy_voyager_impl.cc b/proxy_voyager_impl.cc index 91ad1b1..11f6ea6 100644 --- a/proxy_voyager_impl.cc +++ b/proxy_voyager_impl.cc
@@ -14,7 +14,6 @@ #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/time/time.h" -#include "redfish_query_engine/http/client.h" #include "grpcpp/support/status.h" #include "grpc/status.h" #include "grpcpp/impl/service_type.h" @@ -26,6 +25,7 @@ #include "proxy.h" #include "proxy_config.pb.h" #include "redfish_plugin.h" +#include "request_response.h" #include "sse/sse_parser.h" #include "google/protobuf/map.h" #include "google/protobuf/message.h" @@ -43,7 +43,7 @@ constexpr absl::string_view kReqIdHeader = "vbmc-internal:ReqID"; constexpr int kLogThrottleFrequencySec = 10; -absl::StatusOr<std::unique_ptr<Proxy::Request>> CreateRequestHelper( +static absl::StatusOr<std::unique_ptr<ProxyRequest>> CreateRequestHelper( const Proxy &proxy, RedfishPlugin::RequestVerb verb, const RequestFqp &req_fqp, const google::protobuf::Map<std::string, std::string> &http_headers, @@ -52,10 +52,10 @@ if (!path.ok()) { return path.status(); } - absl::StatusOr<std::unique_ptr<Proxy::Request>> status_or_http_request = + absl::StatusOr<std::unique_ptr<ProxyRequest>> status_or_http_request = proxy.CreateAuthorizedRequest(verb, *path, auth_context); if (!status_or_http_request.ok()) return status_or_http_request; - std::unique_ptr<Proxy::Request> http_request = + std::unique_ptr<ProxyRequest> http_request = *std::move(status_or_http_request); /* Copy http request headers to request */ for (const auto &[key, value] : http_headers) { @@ -71,8 +71,8 @@ } // Create Voyager Update from Http response. -void SetUpdateFromHTTP(Update *update, const Proxy::Response &response, - const Fqp &fqp) { +static void SetUpdateFromHTTP(Update *update, const ProxyResponse &response, + const Fqp &fqp) { /* Copy response headers back */ for (const auto &[key, value] : response.headers) { // HTTP headers names are not case sensitive. Changing consistently to @@ -92,7 +92,7 @@ update->set_code(response.code); } -Proxy::RequestPriority MapRequestPriority( +static Proxy::RequestPriority MapRequestPriority( third_party_voyager::FqpPriority priority) { switch (priority) { case third_party_voyager::FQP_PRI_LOW: @@ -134,7 +134,7 @@ "Unsupported encoding"); } - absl::StatusOr<std::unique_ptr<Proxy::Request>> http_request = + absl::StatusOr<std::unique_ptr<ProxyRequest>> http_request = CreateRequestHelper(proxy_, verb, req_fqp, request->http_headers(), auth_context); if (!http_request.ok()) return ConvertStatus(http_request.status()); @@ -151,7 +151,7 @@ return grpc::Status(static_cast<grpc::StatusCode>(GRPC_STATUS_INTERNAL), std::string("Job error")); } - absl::StatusOr<Proxy::Response> &result = job.value()->response(); + absl::StatusOr<ProxyResponse> &result = job.value()->response(); if (!result.ok()) return ConvertStatus(result.status()); @@ -173,7 +173,7 @@ << "Ignoring multiple requests"; } const RequestFqp &req_fqp = request->req_fqp()[0]; - absl::StatusOr<std::unique_ptr<Proxy::Request>> http_request = + absl::StatusOr<std::unique_ptr<ProxyRequest>> http_request = CreateRequestHelper(proxy_, verb, req_fqp, request->http_headers(), auth_context); if (!http_request.ok()) return ConvertStatus(http_request.status()); @@ -207,7 +207,7 @@ "Job error"); } - absl::StatusOr<Proxy::Response> &result = job.value()->response(); + absl::StatusOr<ProxyResponse> &result = job.value()->response(); if (!result.ok()) return ConvertStatus(result.status()); SetUpdateFromHTTP(response, *result, req_fqp.fqp()); @@ -225,7 +225,7 @@ } const RequestFqp &req_fqp = request->req_fqp()[0]; - absl::StatusOr<std::unique_ptr<Proxy::Request>> http_request = + absl::StatusOr<std::unique_ptr<ProxyRequest>> http_request = CreateRequestHelper(proxy_, RedfishPlugin::RequestVerb::kSubscribe, req_fqp, request->http_headers(), *context->auth_context()); @@ -241,7 +241,7 @@ : context_(context), writer_(writer), req_fqp_(request->req_fqp()[0]) { update_.set_req_id(request->req_id()); } - absl::Status OnResponse(const Proxy::Response &http_response) override { + absl::Status OnResponse(const ProxyResponse &http_response) override { writer_->SendInitialMetadata(); if (context_->IsCancelled()) { return absl::CancelledError();
diff --git a/proxy_voyager_impl_test.cc b/proxy_voyager_impl_test.cc index 5b81a2f..2087def 100644 --- a/proxy_voyager_impl_test.cc +++ b/proxy_voyager_impl_test.cc
@@ -25,6 +25,7 @@ #include "proxy.h" #include "proxy_config.pb.h" #include "redfish_plugin.h" +#include "request_response.h" #include "sse/sse_parser.h" #include "voyager/deferrable_priority_queue.hpp" #include "voyager/voyager_telemetry.grpc.pb.h" @@ -49,6 +50,8 @@ using ::testing::status::StatusIs; using ::milotic::Proxy; +using ::milotic::ProxyRequest; +using ::milotic::ProxyResponse; using ::milotic::RedfishPlugin; using MockPlugin = milotic::MockRedfishPlugin; @@ -102,13 +105,13 @@ HandleRequest( RedfishPlugin::RequestVerb::kGet, Pointee(AllOf( - Field("uri", &Proxy::Request::uri, "test_endpoint/some/resource"), - Field("headers", &Proxy::Request::headers, + Field("uri", &ProxyRequest::uri, "test_endpoint/some/resource"), + Field("headers", &ProxyRequest::headers, Contains(Pair("X-Test-Header", "test_value"))))))) .WillOnce( - Return(Proxy::Response{.code = 200, - .body = R"json({"Name": "test json"})json", - .headers = {{"Content-Type", "text/json"}}})); + Return(ProxyResponse{{.code = 200, + .body = R"json({"Name": "test json"})json", + .headers = {{"Content-Type", "text/json"}}}})); auto request = ecclesia::ParseTextAsProtoOrDie<third_party_voyager::Request>(R"pb( @@ -151,13 +154,13 @@ HandleRequest( RedfishPlugin::RequestVerb::kGet, Pointee(AllOf( - Field("uri", &Proxy::Request::uri, "test_endpoint/some/resource"), - Field("headers", &Proxy::Request::headers, + Field("uri", &ProxyRequest::uri, "test_endpoint/some/resource"), + Field("headers", &ProxyRequest::headers, Contains(Pair("Host", "test_endpoint"))))))) .WillOnce( - Return(Proxy::Response{.code = 200, - .body = R"json({"Name": "test json"})json", - .headers = {{"Content-Type", "text/json"}}})); + Return(ProxyResponse{{.code = 200, + .body = R"json({"Name": "test json"})json", + .headers = {{"Content-Type", "text/json"}}}})); grpc::ClientContext context; third_party_voyager::Update response; milotic::DeferredStatus status; @@ -179,15 +182,15 @@ HandleRequest( RedfishPlugin::RequestVerb::kPost, Pointee(AllOf( - Field("uri", &Proxy::Request::uri, "test_endpoint/some/resource"), - Field("headers", &Proxy::Request::headers, + Field("uri", &ProxyRequest::uri, "test_endpoint/some/resource"), + Field("headers", &ProxyRequest::headers, Contains(Pair("X-Test-Header", "test_value"))), - Field("headers", &Proxy::Request::headers, + Field("headers", &ProxyRequest::headers, Contains(Pair("Content-Type", "application/json"))))))) .WillOnce( - Return(Proxy::Response{.code = 200, - .body = R"json({"Name": "response"})json", - .headers = {{"Content-Type", "text/json"}}})); + Return(ProxyResponse{{.code = 200, + .body = R"json({"Name": "response"})json", + .headers = {{"Content-Type", "text/json"}}}})); auto request = ecclesia::ParseTextAsProtoOrDie<third_party_voyager::SetRequest>(R"pb( @@ -227,15 +230,15 @@ HandleRequest( RedfishPlugin::RequestVerb::kPost, Pointee(AllOf( - Field("uri", &Proxy::Request::uri, "test_endpoint/some/resource"), - Field("headers", &Proxy::Request::headers, + Field("uri", &ProxyRequest::uri, "test_endpoint/some/resource"), + Field("headers", &ProxyRequest::headers, Contains(Pair("X-Test-Header", "test_value"))), - Field("headers", &Proxy::Request::headers, + Field("headers", &ProxyRequest::headers, Not(Contains(Pair("Content-Type", _)))))))) .WillOnce( - Return(Proxy::Response{.code = 200, - .body = R"json({"Name": "response"})json", - .headers = {{"Content-Type", "text/json"}}})); + Return(ProxyResponse{{.code = 200, + .body = R"json({"Name": "response"})json", + .headers = {{"Content-Type", "text/json"}}}})); auto request = ecclesia::ParseTextAsProtoOrDie<third_party_voyager::SetRequest>(R"pb( @@ -314,14 +317,15 @@ EXPECT_CALL(test_server.plugin, PreprocessRequest) .WillRepeatedly(Return(RedfishPlugin::RequestAction::kHandle)); - EXPECT_CALL(test_server.plugin, - Subscribe(Pointee(Field(&Proxy::Request::uri, - "test_endpoint/some/resource")), - _)) - .WillOnce([](std::unique_ptr<Proxy::Request>, + EXPECT_CALL( + test_server.plugin, + Subscribe( + Pointee(Field(&ProxyRequest::uri, "test_endpoint/some/resource")), _)) + .WillOnce([](std::unique_ptr<ProxyRequest>, RedfishPlugin::EventHandler* handler) { - EXPECT_OK(handler->OnResponse(Proxy::Response{ - .code = 200, .headers = {{"Content-Type", "text/event-stream"}}})); + EXPECT_OK(handler->OnResponse(ProxyResponse{ + {.code = 200, + .headers = {{"Content-Type", "text/event-stream"}}}})); EXPECT_OK( handler->OnEvent(milotic::ServerSentEvent{.event = "test_event", .data = "test data 1", @@ -404,14 +408,15 @@ EXPECT_CALL(test_server.plugin, PreprocessRequest) .WillRepeatedly(Return(RedfishPlugin::RequestAction::kHandle)); - EXPECT_CALL(test_server.plugin, - Subscribe(Pointee(Field(&Proxy::Request::uri, - "test_endpoint/some/resource")), - _)) - .WillOnce([](std::unique_ptr<Proxy::Request>, + EXPECT_CALL( + test_server.plugin, + Subscribe( + Pointee(Field(&ProxyRequest::uri, "test_endpoint/some/resource")), _)) + .WillOnce([](std::unique_ptr<ProxyRequest>, RedfishPlugin::EventHandler* handler) { - EXPECT_OK(handler->OnResponse(Proxy::Response{ - .code = 200, .headers = {{"Content-Type", "text/event-stream"}}})); + EXPECT_OK(handler->OnResponse(ProxyResponse{ + {.code = 200, + .headers = {{"Content-Type", "text/event-stream"}}}})); third_party_voyager::Update update; update.mutable_data_points()->Add()->set_json( R"json({"key": 1000})json"); @@ -462,14 +467,15 @@ EXPECT_CALL(test_server.plugin, PreprocessRequest) .WillRepeatedly(Return(RedfishPlugin::RequestAction::kHandle)); - EXPECT_CALL(test_server.plugin, - Subscribe(Pointee(Field(&Proxy::Request::uri, - "test_endpoint/some/resource")), - _)) - .WillOnce([](std::unique_ptr<Proxy::Request>, + EXPECT_CALL( + test_server.plugin, + Subscribe( + Pointee(Field(&ProxyRequest::uri, "test_endpoint/some/resource")), _)) + .WillOnce([](std::unique_ptr<ProxyRequest>, RedfishPlugin::EventHandler* handler) { - EXPECT_OK(handler->OnResponse(Proxy::Response{ - .code = 200, .headers = {{"Content-Type", "text/event-stream"}}})); + EXPECT_OK(handler->OnResponse(ProxyResponse{ + {.code = 200, + .headers = {{"Content-Type", "text/event-stream"}}}})); third_party_voyager::Update update; update.mutable_data_points()->Add()->set_json( R"json({"key": 1000})json"); @@ -538,19 +544,19 @@ testing::InSequence seq; EXPECT_CALL(test_server.plugin, HandleRequest(RedfishPlugin::RequestVerb::kGet, - Pointee(Field(&Proxy::Request::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/test/high")))) - .WillOnce(Return(Proxy::Response{.code = 200})); + .WillOnce(Return(ProxyResponse{{.code = 200}})); EXPECT_CALL(test_server.plugin, - HandleRequest(RedfishPlugin::RequestVerb::kGet, - Pointee(Field(&Proxy::Request::uri, - "test_endpoint/test/med")))) - .WillOnce(Return(Proxy::Response{.code = 200})); + HandleRequest( + RedfishPlugin::RequestVerb::kGet, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/test/med")))) + .WillOnce(Return(ProxyResponse{{.code = 200}})); EXPECT_CALL(test_server.plugin, - HandleRequest(RedfishPlugin::RequestVerb::kGet, - Pointee(Field(&Proxy::Request::uri, - "test_endpoint/test/low")))) - .WillOnce(Return(Proxy::Response{.code = 200})); + HandleRequest( + RedfishPlugin::RequestVerb::kGet, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/test/low")))) + .WillOnce(Return(ProxyResponse{{.code = 200}})); third_party_voyager::Update update_low; auto request_low =
diff --git a/redfish_grpc_passthrough.cc b/redfish_grpc_passthrough.cc index 4999076..1c726e4 100644 --- a/redfish_grpc_passthrough.cc +++ b/redfish_grpc_passthrough.cc
@@ -11,7 +11,6 @@ #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/string_view.h" -#include "redfish_query_engine/http/client.h" #include "redfish_query_engine/redfish/transport/grpc.h" #include "redfish_query_engine/redfish/transport/interface.h" #include "grpcpp/security/credentials.h" @@ -19,6 +18,7 @@ #include "proxy.h" #include "proxy_builder.h" #include "redfish_plugin.h" +#include "request_response.h" namespace milotic { @@ -44,19 +44,14 @@ return absl::OkStatus(); } -absl::StatusOr<ecclesia::HttpClient::HttpResponse> -RedfishGrpcPassthroughPlugin::HandleRequest( - RedfishPlugin::RequestVerb verb, - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request) { +absl::StatusOr<ProxyResponse> RedfishGrpcPassthroughPlugin::HandleRequest( + RedfishPlugin::RequestVerb verb, std::unique_ptr<ProxyRequest> request) { absl::StatusOr<ecclesia::RedfishTransport::Result> result = redfish_transport_->Get(proxy_->GetPath(request->uri)); if (!result.ok()) { return result.status(); } - ecclesia::HttpClient::HttpResponse response = { - .code = result->code, - .headers = result->headers, - }; + ProxyResponse response(result->code, result->headers); if (std::holds_alternative<nlohmann::json>(result->body)) { response.body = std::get<nlohmann::json>(result->body).dump(); response.headers["Content-Type"] = "application/json";
diff --git a/redfish_grpc_passthrough.h b/redfish_grpc_passthrough.h index 5766ab3..a3a5bb8 100644 --- a/redfish_grpc_passthrough.h +++ b/redfish_grpc_passthrough.h
@@ -7,11 +7,11 @@ #include "absl/log/log.h" #include "absl/status/status.h" #include "absl/status/statusor.h" -#include "redfish_query_engine/http/client.h" #include "redfish_query_engine/redfish/transport/interface.h" #include "proxy_config.pb.h" #include "redfish_plugin.h" #include "remote_credentials.h" +#include "request_response.h" namespace milotic { class RedfishGrpcPassthroughPlugin : public RedfishPlugin { @@ -20,19 +20,17 @@ const milotic_grpc_proxy::Plugin::RedfishGrpc& config) : config_(config) {} - RequestAction PreprocessRequest( - RedfishPlugin::RequestVerb verb, - ecclesia::HttpClient::HttpRequest& request) override { + RequestAction PreprocessRequest(RedfishPlugin::RequestVerb verb, + ProxyRequest& request) override { return RequestAction::kHandle; } - absl::StatusOr<ecclesia::HttpClient::HttpResponse> HandleRequest( + absl::StatusOr<ProxyResponse> HandleRequest( RedfishPlugin::RequestVerb verb, - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request) override; + std::unique_ptr<ProxyRequest> request) override; - absl::Status Subscribe( - std::unique_ptr<ecclesia::HttpClient::HttpRequest> /*request*/, - EventHandler* /*handler*/) override { + absl::Status Subscribe(std::unique_ptr<ProxyRequest> /*request*/, + EventHandler* /*handler*/) override { return absl::UnknownError("Function should never be called"); }
diff --git a/redfish_passthrough_plugin.cc b/redfish_passthrough_plugin.cc index 6a14f08..3553c11 100644 --- a/redfish_passthrough_plugin.cc +++ b/redfish_passthrough_plugin.cc
@@ -19,6 +19,7 @@ #include "proxy_builder.h" #include "proxy_config.pb.h" #include "redfish_plugin.h" +#include "request_response.h" #include "sse/sse_parser.h" namespace milotic { @@ -79,40 +80,44 @@ .low_speed_time = config.sse_low_speed_time_sec(), }) {} -absl::StatusOr<ecclesia::HttpClient::HttpResponse> -RedfishPassthroughPluginBase ::HandleRequest( +absl::StatusOr<ProxyResponse> RedfishPassthroughPluginBase ::HandleRequest( RedfishPlugin::RequestVerb verb, - std::unique_ptr<ecclesia::HttpClient::HttpRequest> http_request) { + std::unique_ptr<ProxyRequest> http_request) { // Making a copy to pass to latency monitor as request gets moved. std::string uri = http_request->uri; LatencyMonitor latency_monitor( &CommonMetrics::Get().passthrough_request_latency, {VerbToString(verb), uri}); - absl::StatusOr<ecclesia::HttpClient::HttpResponse> response; + absl::StatusOr<ecclesia::HttpClient::HttpResponse> http_response; switch (verb) { case RedfishPlugin::RequestVerb::kPost: - response = http_client_.Post(std::move(http_request)); + http_response = http_client_.Post(std::move(http_request)); break; case RedfishPlugin::RequestVerb::kGet: - response = http_client_.Get(std::move(http_request)); + http_response = http_client_.Get(std::move(http_request)); break; case RedfishPlugin::RequestVerb::kPatch: - response = http_client_.Patch(std::move(http_request)); + http_response = http_client_.Patch(std::move(http_request)); break; case RedfishPlugin::RequestVerb::kDelete: - response = http_client_.Delete(std::move(http_request)); + http_response = http_client_.Delete(std::move(http_request)); break; default: return absl::UnimplementedError("HTTP method not implemented"); } - return CaptureResponseCode(response, + if (!http_response.ok()) { + return CaptureResponseCode(http_response.status(), + &CommonMetrics::Get().passthrough_response_code, + uri, /*field_values=*/{}); + ; + } + return CaptureResponseCode(ProxyResponse(*http_response), &CommonMetrics::Get().passthrough_response_code, uri, /*field_values=*/{}); } absl::Status RedfishPassthroughPluginBase ::Subscribe( - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request, - EventHandler* handler) { + std::unique_ptr<ProxyRequest> request, EventHandler* handler) { class IncrementalResponseHandler : public ecclesia::HttpClient::IncrementalResponseHandler { public: @@ -127,7 +132,7 @@ absl::Status OnResponseHeaders( const ecclesia::HttpClient::HttpResponse& response) override { latency_monitor_.reset(); - absl::Status status = handler_->OnResponse(response); + absl::Status status = handler_->OnResponse(ProxyResponse(response)); if (!status.ok()) return status; std::optional<absl::string_view> content_type = GetHeader(response.headers, "Content-type");
diff --git a/redfish_passthrough_plugin.h b/redfish_passthrough_plugin.h index adfec94..bd570c5 100644 --- a/redfish_passthrough_plugin.h +++ b/redfish_passthrough_plugin.h
@@ -8,6 +8,7 @@ #include "redfish_query_engine/http/curl_client.h" #include "proxy_config.pb.h" #include "redfish_plugin.h" +#include "request_response.h" namespace milotic { @@ -33,21 +34,21 @@ virtual ~RedfishPassthroughPluginBase() = default; RequestAction PreprocessRequest(RedfishPlugin::RequestVerb verb, - ecclesia::HttpClient::HttpRequest&) override { + ProxyRequest& /*request*/) override { if (verb == RedfishPlugin::RequestVerb::kInternal) { return RequestAction::kDrop; } return RequestAction::kHandle; } - absl::StatusOr<ecclesia::HttpClient::HttpResponse> HandleRequest( + absl::StatusOr<ProxyResponse> HandleRequest( RedfishPlugin::RequestVerb verb, - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request) override; + std::unique_ptr<ProxyRequest> request) override; - absl::Status Subscribe(std::unique_ptr<ecclesia::HttpClient::HttpRequest>, + absl::Status Subscribe(std::unique_ptr<ProxyRequest> /*request*/, EventHandler* handler) override; - absl::Status Initialize(Proxy*) override; + absl::Status Initialize(Proxy* /*proxy*/) override; RedfishPassthroughPluginBase(const RedfishPassthroughPluginBase&) = delete; RedfishPassthroughPluginBase& operator=(const RedfishPassthroughPluginBase&) = @@ -60,8 +61,9 @@ class RedfishPassthroughPlugin : public RedfishPassthroughPluginBase { public: - RedfishPassthroughPlugin( + explicit RedfishPassthroughPlugin( const milotic_grpc_proxy::Plugin::RedfishPassthrough& config); + private: ecclesia::CurlHttpClient curl_http_client_; ecclesia::CurlHttpClient subscribe_curl_http_client_;
diff --git a/redfish_passthrough_plugin_test.cc b/redfish_passthrough_plugin_test.cc index 67f87c2..47969cb 100644 --- a/redfish_passthrough_plugin_test.cc +++ b/redfish_passthrough_plugin_test.cc
@@ -9,6 +9,7 @@ #include "absl/status/statusor.h" #include "redfish_query_engine/http/client.h" #include "mock_redfish_plugin.h" +#include "request_response.h" #include "sse/sse_parser.h" #include "util/task/status_macros.h" @@ -22,8 +23,10 @@ using ::testing::SaveArg; using ::testing::status::IsOk; -using HttpRequest = ::ecclesia::HttpClient::HttpRequest; -using HttpResponse = ::ecclesia::HttpClient::HttpResponse; +using ProxyRequest = milotic::ProxyRequest; +using ProxyResponse = milotic::ProxyResponse; +using HttpResponse = ecclesia::HttpClient::HttpResponse; +using HttpRequest = ecclesia::HttpClient::HttpRequest; using ::milotic::ServerSentEvent; class MockHttpClient : public ecclesia::HttpClient { @@ -88,7 +91,7 @@ EXPECT_CALL(mock_event_handler, OnEvent(A<const ServerSentEvent&>())) .WillOnce(DoAll(SaveArg<0>(&event), Return(absl::OkStatus()))); - auto request = std::make_unique<HttpRequest>(); + auto request = std::make_unique<ProxyRequest>(); EXPECT_OK(plugin.Subscribe(std::move(request), &mock_event_handler)); EXPECT_EQ(event, ServerSentEvent{.event = "test"}); } @@ -113,7 +116,7 @@ .WillOnce(Return(absl::OkStatus())); EXPECT_CALL(mock_event_handler, OnEvent(A<const ServerSentEvent&>())) .Times(0); - auto request = std::make_unique<HttpRequest>(); + auto request = std::make_unique<ProxyRequest>(); EXPECT_THAT(plugin.Subscribe(std::move(request), &mock_event_handler), Not(IsOk())); } @@ -137,7 +140,7 @@ .WillOnce(Return(absl::OkStatus())); EXPECT_CALL(mock_event_handler, OnEvent(A<const ServerSentEvent&>())) .Times(0); - auto request = std::make_unique<HttpRequest>(); + auto request = std::make_unique<ProxyRequest>(); EXPECT_THAT(plugin.Subscribe(std::move(request), &mock_event_handler), Not(IsOk())); }
diff --git a/redfish_plugin.h b/redfish_plugin.h index e07e9e2..04314ea 100644 --- a/redfish_plugin.h +++ b/redfish_plugin.h
@@ -8,7 +8,7 @@ #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/string_view.h" -#include "redfish_query_engine/http/client.h" +#include "request_response.h" #include "sse/sse_parser.h" #include "google/protobuf/message.h" @@ -49,8 +49,7 @@ // failure starting the stream. Returning an error will terminate the // connection, but using `IsCancelled` to terminate the connection is // preferred if there is no error. - virtual absl::Status OnResponse( - const ecclesia::HttpClient::HttpResponse& response) = 0; + virtual absl::Status OnResponse(const ProxyResponse& response) = 0; // Called with the contents of a new event. Events may be SSE or some proto. // The handler implementation may handle one or both of these. Returning an // error will terminate the connection, but using `IsCancelled` to terminate @@ -72,28 +71,25 @@ // `kSubscribe`, the `Subscribe` method will be called. Otherwise, the // `Handle` method will called. // kNext will continue to the next plugin - virtual RequestAction PreprocessRequest( - RedfishPlugin::RequestVerb verb, - ecclesia::HttpClient::HttpRequest& request) = 0; + virtual RequestAction PreprocessRequest(RedfishPlugin::RequestVerb verb, + ProxyRequest& request) = 0; // Handles a single Redfish request of type verb. // Takes ownership of the request - virtual absl::StatusOr<ecclesia::HttpClient::HttpResponse> HandleRequest( + virtual absl::StatusOr<ProxyResponse> HandleRequest( RedfishPlugin::RequestVerb verb, - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request) = 0; + std::unique_ptr<ProxyRequest> request) = 0; // Subscribe to event source. e.g. SSE. The plugin should call the appropriate // callbacks in `handler`. See the descriptions in the `EventHandler` class. - virtual absl::Status Subscribe( - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request, - EventHandler* handler) = 0; + virtual absl::Status Subscribe(std::unique_ptr<ProxyRequest> request, + EventHandler* handler) = 0; // Start a bidirectional stream. The plugin should call the appropriate // callbacks in `handler`, and return another EventHandler to handle incoming // messages. See the descriptions in the `EventHandler` class. virtual absl::StatusOr<std::unique_ptr<EventHandler>> BidirectionalStream( - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request, - EventHandler* handler) { + std::unique_ptr<ProxyRequest> request, EventHandler* handler) { return absl::UnimplementedError("Not implemented"); }
diff --git a/redfish_resource.cc b/redfish_resource.cc index 883347b..1e9028e 100644 --- a/redfish_resource.cc +++ b/redfish_resource.cc
@@ -11,13 +11,14 @@ #include "nlohmann/json_fwd.hpp" #include "proxy.h" #include "redfish_plugin.h" +#include "request_response.h" namespace milotic { absl::StatusOr<nlohmann::json> GetRedfishResource(Proxy* proxy, absl::string_view id, RedfishExpand expand) { - std::unique_ptr<Proxy::Request> request; + std::unique_ptr<ProxyRequest> request; if (!expand.expand_links && !expand.expand_non_links) { request = proxy->CreateRequest(id); } else { @@ -32,7 +33,7 @@ request = proxy->CreateRequest(absl::StrCat( id, "?$expand=", expand_type, "($levels=", expand.levels, ")")); } - absl::StatusOr<Proxy::Response> response = proxy->DispatchRequest( + absl::StatusOr<ProxyResponse> response = proxy->DispatchRequest( RedfishPlugin::RequestVerb::kGet, std::move(request)); if (!response.ok()) { return response.status();
diff --git a/redfish_resource_test.cc b/redfish_resource_test.cc index 2ad50ea..b0e7273 100644 --- a/redfish_resource_test.cc +++ b/redfish_resource_test.cc
@@ -11,10 +11,13 @@ #include "mock_redfish_plugin.h" #include "proxy.h" #include "redfish_plugin.h" +#include "request_response.h" namespace { using ::milotic::Proxy; +using ::milotic::ProxyRequest; +using ::milotic::ProxyResponse; using ::milotic::RedfishPlugin; using ::testing::AllOf; @@ -37,9 +40,9 @@ .WillOnce(Return(RedfishPlugin::RequestAction::kHandle)); EXPECT_CALL(*handler_plugin, HandleRequest(RedfishPlugin::RequestVerb::kGet, - Pointee(Field(&Proxy::Request::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1")))) - .WillOnce(Return(Proxy::Response{.code = 200, .body{resource}})); + .WillOnce(Return(ProxyResponse{{.code = 200, .body{resource}}})); std::unique_ptr<RedfishPlugin> plugins[] = {std::move(handler_plugin)}; Proxy proxy("test_endpoint", plugins); @@ -59,10 +62,10 @@ .WillOnce(Return(RedfishPlugin::RequestAction::kHandle)); EXPECT_CALL(*handler_plugin, HandleRequest(RedfishPlugin::RequestVerb::kGet, - Pointee(Field(&Proxy::Request::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1")))) .WillOnce(Return( - Proxy::Response{.code = 404, .body = "<<<error report string>>>"})); + ProxyResponse{{.code = 404, .body = "<<<error report string>>>"}})); std::unique_ptr<RedfishPlugin> plugins[] = {std::move(handler_plugin)}; Proxy proxy("test_endpoint", plugins); @@ -81,9 +84,9 @@ .WillOnce(Return(RedfishPlugin::RequestAction::kHandle)); EXPECT_CALL(*handler_plugin, HandleRequest(RedfishPlugin::RequestVerb::kGet, - Pointee(Field(&Proxy::Request::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1")))) - .WillOnce(Return(Proxy::Response{.code = 200, .body = "<<<bad json>>>"})); + .WillOnce(Return(ProxyResponse{{.code = 200, .body = "<<<bad json>>>"}})); std::unique_ptr<RedfishPlugin> plugins[] = {std::move(handler_plugin)}; Proxy proxy("test_endpoint", plugins); @@ -108,9 +111,9 @@ *handler_plugin, HandleRequest( RedfishPlugin::RequestVerb::kGet, - Pointee(Field(&Proxy::Request::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1?$expand=*($levels=1)")))) - .WillOnce(Return(Proxy::Response{.code = 200, .body{resource}})); + .WillOnce(Return(ProxyResponse{{.code = 200, .body{resource}}})); std::unique_ptr<RedfishPlugin> plugins[] = {std::move(handler_plugin)}; Proxy proxy("test_endpoint", plugins); @@ -134,15 +137,15 @@ *handler_plugin, HandleRequest( RedfishPlugin::RequestVerb::kGet, - Pointee(Field(&Proxy::Request::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1?$expand=.($levels=1)")))) - .WillOnce(Return(Proxy::Response{.code = 200, .body{resource}})); + .WillOnce(Return(ProxyResponse{{.code = 200, .body{resource}}})); std::unique_ptr<RedfishPlugin> plugins[] = {std::move(handler_plugin)}; Proxy proxy("test_endpoint", plugins); - EXPECT_OK(milotic::GetRedfishResource( - &proxy, "/redfish/v1", {.expand_non_links = true})); + EXPECT_OK(milotic::GetRedfishResource(&proxy, "/redfish/v1", + {.expand_non_links = true})); } TEST(RedfishResourceTest, ExpandOnlyLinksIsAdded) { @@ -160,15 +163,15 @@ *handler_plugin, HandleRequest( RedfishPlugin::RequestVerb::kGet, - Pointee(Field(&Proxy::Request::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1?$expand=~($levels=1)")))) - .WillOnce(Return(Proxy::Response{.code = 200, .body{resource}})); + .WillOnce(Return(ProxyResponse{{.code = 200, .body{resource}}})); std::unique_ptr<RedfishPlugin> plugins[] = {std::move(handler_plugin)}; Proxy proxy("test_endpoint", plugins); - EXPECT_OK(milotic::GetRedfishResource( - &proxy, "/redfish/v1", {.expand_links = true})); + EXPECT_OK(milotic::GetRedfishResource(&proxy, "/redfish/v1", + {.expand_links = true})); } TEST(RedfishResourceTest, ExpandLevelsSet) { @@ -186,14 +189,14 @@ *handler_plugin, HandleRequest( RedfishPlugin::RequestVerb::kGet, - Pointee(Field(&Proxy::Request::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1?$expand=~($levels=99)")))) - .WillOnce(Return(Proxy::Response{.code = 200, .body{resource}})); + .WillOnce(Return(ProxyResponse{{.code = 200, .body{resource}}})); std::unique_ptr<RedfishPlugin> plugins[] = {std::move(handler_plugin)}; Proxy proxy("test_endpoint", plugins); - EXPECT_OK(milotic::GetRedfishResource( - &proxy, "/redfish/v1", {.expand_links = true, .levels = 99})); + EXPECT_OK(milotic::GetRedfishResource(&proxy, "/redfish/v1", + {.expand_links = true, .levels = 99})); } } // namespace
diff --git a/redfish_session_auth.cc b/redfish_session_auth.cc index 8cf7739..5ceed39 100644 --- a/redfish_session_auth.cc +++ b/redfish_session_auth.cc
@@ -22,7 +22,6 @@ #include "absl/time/clock.h" #include "absl/time/time.h" #include <source_location> -#include "redfish_query_engine/http/client.h" #include "redfish_query_engine/http/codes.h" #include "nlohmann/json_fwd.hpp" #include "metrics.h" @@ -30,11 +29,12 @@ #include "proxy_builder.h" #include "redfish_plugin.h" #include "remote_credentials.h" +#include "request_response.h" namespace milotic { -void InsertBasicAuth(ecclesia::HttpClient::HttpRequest* request, - absl::string_view username, absl::string_view password) { +static void InsertBasicAuth(ProxyRequest* request, absl::string_view username, + absl::string_view password) { std::string encoded; absl::Base64Escape(absl::StrCat(username, ":", password), &encoded); request->headers["Authorization"] = absl::StrCat("Basic ", encoded); @@ -45,8 +45,7 @@ constexpr absl::Duration kSessionExpiryMargin = absl::Seconds(10); RedfishPlugin::RequestAction RedfishSessionAuthPlugin::PreprocessRequest( - RedfishPlugin::RequestVerb verb, - ecclesia::HttpClient::HttpRequest& request) { + RedfishPlugin::RequestVerb verb, ProxyRequest& request) { if (verb == RequestVerb::kInternal) { if (request.uri == proxy_->GetUrl(SessionStateResourcePath())) { return RequestAction::kHandle; @@ -81,23 +80,18 @@ return RequestAction::kNext; } -absl::StatusOr<ecclesia::HttpClient::HttpResponse> -RedfishSessionAuthPlugin::HandleRequest( - RedfishPlugin::RequestVerb verb, - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request) { +absl::StatusOr<ProxyResponse> RedfishSessionAuthPlugin::HandleRequest( + RedfishPlugin::RequestVerb verb, std::unique_ptr<ProxyRequest> request) { if (verb != RequestVerb::kInternal) { return absl::InternalError("Unexpected request"); } absl::MutexLock lock(&token_state_mutex_); - return ecclesia::HttpClient::HttpResponse{ - .code = ecclesia::HttpResponseCode::HTTP_CODE_REQUEST_OK, - .body = std::string(session_state_), - }; + return ProxyResponse(ecclesia::HttpResponseCode::HTTP_CODE_REQUEST_OK, + std::string(session_state_)); } void RedfishSessionAuthPlugin::InsertAuth( - std::optional<absl::string_view> token, - ecclesia::HttpClient::HttpRequest* request) { + std::optional<absl::string_view> token, ProxyRequest* request) { if (token.has_value()) { request->headers["X-Auth-Token"] = *token; } else if (credentials_.username) { @@ -119,7 +113,7 @@ } static absl::StatusOr<std::vector<std::string>> GetSessions( - const Proxy::Response& resp) { + const ProxyResponse& resp) { auto code = ecclesia::HttpResponseCodeFromInt(resp.code); if (code != ecclesia::HttpResponseCode::HTTP_CODE_REQUEST_OK) { return absl::InternalError(absl::StrFormat( @@ -157,7 +151,7 @@ std::unique_ptr<Proxy::RequestJob> job = proxy_->CreateRequestJob( RedfishPlugin::RequestVerb::kGet, proxy_->CreateRequest("/redfish/v1/SessionService/Sessions")); - job->Handle([this](const absl::StatusOr<Proxy::Response>& resp) { + job->Handle([this](const absl::StatusOr<ProxyResponse>& resp) { absl::StatusOr<std::vector<std::string>> sessions; if (!resp.ok()) { LOG(ERROR) << "Failed to check session"; @@ -298,14 +292,14 @@ using ecclesia::HttpResponseCode; assert(proxy_ != nullptr); - std::unique_ptr<Proxy::Request> http_request = + std::unique_ptr<ProxyRequest> http_request = proxy_->CreateRequest("/redfish/v1/SessionService"); // Use the token if it is present. Some implementations restrict access to // SessionService once a session is created. if (token_.has_value()) { InsertAuth(token_, http_request.get()); } - absl::StatusOr<Proxy::Response> result = proxy_->DispatchRequest( + absl::StatusOr<ProxyResponse> result = proxy_->DispatchRequest( RedfishPlugin::RequestVerb::kGet, std::move(http_request)); if (!result.ok()) { return result.status(); @@ -338,7 +332,7 @@ absl::Status RedfishSessionAuthPlugin::GetToken() { assert(proxy_ != nullptr); - std::unique_ptr<Proxy::Request> http_request = + std::unique_ptr<ProxyRequest> http_request = proxy_->CreateRequest("/redfish/v1/SessionService/Sessions"); if (!credentials_.username.has_value()) { return absl::FailedPreconditionError("Username not set"); @@ -348,7 +342,7 @@ *credentials_.username, credentials_.password); http_request->headers["Content-Type"] = "application/json;charset=utf-8"; http_request->headers["OData-Version"] = "4.0"; - absl::StatusOr<Proxy::Response> result = proxy_->DispatchRequest( + absl::StatusOr<ProxyResponse> result = proxy_->DispatchRequest( RedfishPlugin::RequestVerb::kPost, std::move(http_request)); if (!result.ok()) { return result.status(); @@ -390,11 +384,10 @@ } LOG(INFO) << "Deleting session at " << *session_; - std::unique_ptr<Proxy::Request> http_request = - proxy_->CreateRequest(*session_); + std::unique_ptr<ProxyRequest> http_request = proxy_->CreateRequest(*session_); InsertAuth(token_, http_request.get()); - absl::StatusOr<Proxy::Response> result = proxy_->DispatchRequest( + absl::StatusOr<ProxyResponse> result = proxy_->DispatchRequest( RedfishPlugin::RequestVerb::kDelete, std::move(http_request)); if (!result.ok()) { return result.status();
diff --git a/redfish_session_auth.h b/redfish_session_auth.h index fc4aea8..6c139d1 100644 --- a/redfish_session_auth.h +++ b/redfish_session_auth.h
@@ -15,11 +15,11 @@ #include "absl/time/clock.h" #include "absl/time/time.h" #include <source_location> -#include "redfish_query_engine/http/client.h" #include "proxy.h" #include "proxy_config.pb.h" #include "redfish_plugin.h" #include "remote_credentials.h" +#include "request_response.h" namespace milotic { @@ -57,17 +57,15 @@ } } - RequestAction PreprocessRequest( - RedfishPlugin::RequestVerb verb, - ecclesia::HttpClient::HttpRequest& request) override; + RequestAction PreprocessRequest(RedfishPlugin::RequestVerb verb, + ProxyRequest& request) override; - absl::StatusOr<ecclesia::HttpClient::HttpResponse> HandleRequest( + absl::StatusOr<ProxyResponse> HandleRequest( RedfishPlugin::RequestVerb verb, - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request) override; + std::unique_ptr<ProxyRequest> request) override; - absl::Status Subscribe( - std::unique_ptr<ecclesia::HttpClient::HttpRequest> /*request*/, - EventHandler* /*handler*/) override { + absl::Status Subscribe(std::unique_ptr<ProxyRequest> /*request*/, + EventHandler* /*handler*/) override { return absl::UnknownError("Function should never be called"); } @@ -108,7 +106,7 @@ absl::Status DeleteSession() ABSL_EXCLUSIVE_LOCKS_REQUIRED(token_state_mutex_); void InsertAuth(std::optional<absl::string_view> token, - ecclesia::HttpClient::HttpRequest* request); + ProxyRequest* request); absl::Status CheckSession(std::optional<absl::Time> after = std::nullopt) ABSL_LOCKS_EXCLUDED(token_state_mutex_); void SetState(absl::string_view state,
diff --git a/redfish_session_auth_test.cc b/redfish_session_auth_test.cc index 3d61d31..94e63ff 100644 --- a/redfish_session_auth_test.cc +++ b/redfish_session_auth_test.cc
@@ -16,13 +16,13 @@ #include "absl/time/clock.h" #include "absl/time/time.h" #include "absl/types/span.h" -#include "redfish_query_engine/http/client.h" #include "redfish_query_engine/protobuf/parse.h" #include "nlohmann/json_fwd.hpp" #include "mock_redfish_plugin.h" #include "proxy_config.pb.h" #include "redfish_plugin.h" #include "remote_credentials.h" +#include "request_response.h" #include "voyager/deferrable_priority_queue.hpp" #include "thread/thread.h" #include "thread/thread_options.h" @@ -52,8 +52,8 @@ using ::testing::StrictMock; using ::testing::status::IsOkAndHolds; -using HttpRequest = ecclesia::HttpClient::HttpRequest; -using HttpResponse = ecclesia::HttpClient::HttpResponse; +using milotic::ProxyRequest; +using milotic::ProxyResponse; using RequestVerb = milotic::RedfishPlugin::RequestVerb; using RequestAction = milotic::RedfishPlugin::RequestAction; using RedfishSessionAuth = milotic_grpc_proxy::Plugin::RedfishSessionAuth; @@ -95,10 +95,9 @@ milotic::Proxy proxy; }; -HttpResponse ValidSessionService() { - return { - .code = 200, - .body = R"json({ +ProxyResponse ValidSessionService() { + return ProxyResponse(200, + R"json({ "@odata.id": "/redfish/v1/SessionService/", "@odata.type": "#SessionService.v1_0_2.SessionService", "Description": "Session Service", @@ -110,29 +109,26 @@ "@odata.id": "/redfish/v1/SessionService/Sessions" } })json", - .headers = {{"OData-Version", "4.0"}}, - }; + {{"OData-Version", "4.0"}}); } -HttpResponse ValidSession(absl::string_view id, absl::string_view token) { - return { - .code = 201, - .body = absl::StrFormat(R"json({ +ProxyResponse ValidSession(absl::string_view id, absl::string_view token) { + return ProxyResponse( + 201, + absl::StrFormat(R"json({ "@odata.id": "/redfish/v1/SessionService/Sessions/%1$s", "@odata.type": "#Session.v1_2_1.Session", "Id": "%1$s", "Name": "User Session test_session", "UserName": "test_username" })json", - id), - .headers = {{"X-Auth-Token", std::string(token)}, - {"OData-Version", "4.0"}, - {"Location", - absl::StrCat("/redfish/v1/SessionService/Sessions/", id)}}, - }; + id), + {{"X-Auth-Token", std::string(token)}, + {"OData-Version", "4.0"}, + {"Location", absl::StrCat("/redfish/v1/SessionService/Sessions/", id)}}); } -HttpResponse ValidSessions(absl::Span<const absl::string_view> ids) { +ProxyResponse ValidSessions(absl::Span<const absl::string_view> ids) { nlohmann::json json = nlohmann::json::parse(R"json({ "@odata.id": "/redfish/v1/SessionService/Sessions", "@odata.type": "#SessionCollection.SessionCollection", @@ -142,15 +138,11 @@ json["Members"].push_back({{"@odata.id", std::string(id)}}); } json["Members@odata.count"] = ids.size(); - return { - .code = 200, - .body = json.dump(), - .headers = {{"OData-Version", "4.0"}}, - }; + return ProxyResponse(200, json.dump(), {{"OData-Version", "4.0"}}); } absl::StatusOr<std::string> GetState(TestEnv* test_env) { - ASSIGN_OR_RETURN(HttpResponse resp, + ASSIGN_OR_RETURN(ProxyResponse resp, test_env->proxy.DispatchRequest( RequestVerb::kInternal, test_env->proxy.CreateRequest( @@ -166,8 +158,8 @@ const nlohmann::json expected_request = {{"UserName", "test_username"}, {"Password", "test_password"}}; - const HttpResponse session_service = ValidSessionService(); - const HttpResponse session = ValidSession("test_session", "fake-token"); + const ProxyResponse session_service = ValidSessionService(); + const ProxyResponse session = ValidSession("test_session", "fake-token"); auto instance = CreatePlugin(); ON_CALL(*instance, Now()).WillByDefault(Return(absl::Now())); @@ -184,11 +176,11 @@ HandleRequest( RequestVerb::kPost, Pointee(AllOf( - Field(&HttpRequest::uri, + Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions"), - Field(&HttpRequest::body, + Field(&ProxyRequest::body, ResultOf(parse_json, expected_request)), - Field(&HttpRequest::headers, + Field(&ProxyRequest::headers, IsSupersetOf({Pair("Content-Type", "application/json;charset=utf-8"), Pair("OData-Version", "4.0")})))))) @@ -196,7 +188,7 @@ EXPECT_CALL(*default_plugin, HandleRequest( RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService")))) .WillOnce(Return(session_service)); } @@ -205,31 +197,32 @@ *default_plugin, HandleRequest( RequestVerb::kGet, - Pointee(AllOf(Field(&HttpRequest::uri, "test_endpoint/test/url"), - Field(&HttpRequest::headers, + Pointee(AllOf(Field(&ProxyRequest::uri, "test_endpoint/test/url"), + Field(&ProxyRequest::headers, Contains(Pair("X-Auth-Token", "fake-token"))))))) .Times(2) - .WillRepeatedly(Return(HttpResponse{.code = 200, .body = "test body"})); + .WillRepeatedly( + Return(ProxyResponse{{.code = 200, .body = "test body"}})); std::unique_ptr<milotic::RedfishPlugin> plugins[] = { std::move(instance), std::move(default_plugin)}; TestEnv test_env(plugins); for (int i = 0; i < 2; ++i) { - absl::StatusOr<HttpResponse> resp = test_env.proxy.DispatchRequest( + absl::StatusOr<ProxyResponse> resp = test_env.proxy.DispatchRequest( RequestVerb::kGet, test_env.proxy.CreateRequest("/test/url")); EXPECT_THAT(resp, - IsOkAndHolds(AllOf(Field(&HttpResponse::code, 200), - Field(&HttpResponse::body, "test body")))); + IsOkAndHolds(AllOf(Field(&ProxyResponse::code, 200), + Field(&ProxyResponse::body, "test body")))); EXPECT_THAT(GetState(&test_env), IsOkAndHolds(RedfishSessionAuthPlugin::SessionState::kOk)); } } TEST(RedfishSessionAuthTest, SessionAuthRunsAgainOnTimeout) { - const HttpResponse session_service = ValidSessionService(); - const HttpResponse session1 = ValidSession("test_session1", "fake-token-1"); - const HttpResponse session2 = ValidSession("test_session2", "fake-token-2"); + const ProxyResponse session_service = ValidSessionService(); + const ProxyResponse session1 = ValidSession("test_session1", "fake-token-1"); + const ProxyResponse session2 = ValidSession("test_session2", "fake-token-2"); const nlohmann::json expected_request = {{"UserName", "test_username"}, {"Password", "test_password"}}; @@ -248,50 +241,50 @@ EXPECT_CALL( *default_plugin, HandleRequest(RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService")))) .WillOnce(Return(session_service)); testing::InSequence seq; - EXPECT_CALL( - *default_plugin, - HandleRequest( - RequestVerb::kPost, - Pointee(AllOf( - Field(&HttpRequest::uri, - "test_endpoint/redfish/v1/SessionService/Sessions"), - Field(&HttpRequest::body, ResultOf(parse_json, expected_request)), - Field(&HttpRequest::headers, - Not(Contains(Pair("X-Auth-Token", _)))))))) + EXPECT_CALL(*default_plugin, + HandleRequest( + RequestVerb::kPost, + Pointee(AllOf( + Field(&ProxyRequest::uri, + "test_endpoint/redfish/v1/SessionService/Sessions"), + Field(&ProxyRequest::body, + ResultOf(parse_json, expected_request)), + Field(&ProxyRequest::headers, + Not(Contains(Pair("X-Auth-Token", _)))))))) .WillOnce(Return(session1)); EXPECT_CALL(*default_plugin, HandleRequest( RequestVerb::kGet, Pointee(AllOf( - Field(&HttpRequest::uri, "test_endpoint/test/url"), - Field(&HttpRequest::headers, + Field(&ProxyRequest::uri, "test_endpoint/test/url"), + Field(&ProxyRequest::headers, Contains(Pair("X-Auth-Token", "fake-token-1"))))))) - .WillOnce(Return(HttpResponse{.code = 200, .body = "test body"})); + .WillOnce(Return(ProxyResponse{{.code = 200, .body = "test body"}})); EXPECT_CALL(*default_plugin, HandleRequest( RequestVerb::kDelete, Pointee(AllOf( - Field(&HttpRequest::uri, + Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions/" "test_session1"), - Field(&HttpRequest::headers, + Field(&ProxyRequest::headers, Contains(Pair("X-Auth-Token", "fake-token-1"))))))) - .WillOnce(Return(HttpResponse{.code = 204})); + .WillOnce(Return(ProxyResponse{{.code = 204}})); EXPECT_CALL(*default_plugin, HandleRequest( RequestVerb::kPost, Pointee(AllOf( - Field(&HttpRequest::uri, + Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions"), - Field(&HttpRequest::body, + Field(&ProxyRequest::body, ResultOf(parse_json, expected_request)))))) .WillOnce(Return(session2)); @@ -299,29 +292,29 @@ HandleRequest( RequestVerb::kGet, Pointee(AllOf( - Field(&HttpRequest::uri, "test_endpoint/test/url"), - Field(&HttpRequest::headers, + Field(&ProxyRequest::uri, "test_endpoint/test/url"), + Field(&ProxyRequest::headers, Contains(Pair("X-Auth-Token", "fake-token-2"))))))) - .WillOnce(Return(HttpResponse{.code = 200, .body = "test body"})); + .WillOnce(Return(ProxyResponse{{.code = 200, .body = "test body"}})); std::unique_ptr<milotic::RedfishPlugin> plugins[] = { std::move(instance), std::move(default_plugin)}; TestEnv test_env(plugins); for (int i = 0; i < 2; ++i) { - absl::StatusOr<HttpResponse> resp = test_env.proxy.DispatchRequest( + absl::StatusOr<ProxyResponse> resp = test_env.proxy.DispatchRequest( RequestVerb::kGet, test_env.proxy.CreateRequest("/test/url")); EXPECT_THAT(resp, - IsOkAndHolds(AllOf(Field(&HttpResponse::code, 200), - Field(&HttpResponse::body, "test body")))); + IsOkAndHolds(AllOf(Field(&ProxyResponse::code, 200), + Field(&ProxyResponse::body, "test body")))); now += absl::Seconds(1800); } } TEST(RedfishSessionAuthTest, SessionAuthRunsAgainOnForce) { - const HttpResponse session_service = ValidSessionService(); - const HttpResponse session1 = ValidSession("test_session1", "fake-token-1"); - const HttpResponse session2 = ValidSession("test_session2", "fake-token-2"); + const ProxyResponse session_service = ValidSessionService(); + const ProxyResponse session1 = ValidSession("test_session1", "fake-token-1"); + const ProxyResponse session2 = ValidSession("test_session2", "fake-token-2"); const nlohmann::json expected_request = {{"UserName", "test_username"}, {"Password", "test_password"}}; @@ -339,7 +332,7 @@ EXPECT_CALL( *default_plugin, HandleRequest(RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService")))) .WillOnce(Return(session_service)); @@ -348,9 +341,9 @@ HandleRequest( RequestVerb::kPost, Pointee(AllOf( - Field(&HttpRequest::uri, + Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions"), - Field(&HttpRequest::body, + Field(&ProxyRequest::body, ResultOf(parse_json, expected_request)))))) .WillOnce(Return(session1)); @@ -358,29 +351,29 @@ HandleRequest( RequestVerb::kGet, Pointee(AllOf( - Field(&HttpRequest::uri, "test_endpoint/test/url"), - Field(&HttpRequest::headers, + Field(&ProxyRequest::uri, "test_endpoint/test/url"), + Field(&ProxyRequest::headers, Contains(Pair("X-Auth-Token", "fake-token-1"))))))) - .WillOnce(Return(HttpResponse{.code = 200, .body = "test body"})); + .WillOnce(Return(ProxyResponse{{.code = 200, .body = "test body"}})); EXPECT_CALL(*default_plugin, HandleRequest( RequestVerb::kDelete, Pointee(AllOf( - Field(&HttpRequest::uri, + Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions/" "test_session1"), - Field(&HttpRequest::headers, + Field(&ProxyRequest::headers, Contains(Pair("X-Auth-Token", "fake-token-1"))))))) - .WillOnce(Return(HttpResponse{.code = 204})); + .WillOnce(Return(ProxyResponse{{.code = 204}})); EXPECT_CALL(*default_plugin, HandleRequest( RequestVerb::kPost, Pointee(AllOf( - Field(&HttpRequest::uri, + Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions"), - Field(&HttpRequest::body, + Field(&ProxyRequest::body, ResultOf(parse_json, expected_request)))))) .WillOnce(Return(session2)); @@ -388,10 +381,10 @@ HandleRequest( RequestVerb::kGet, Pointee(AllOf( - Field(&HttpRequest::uri, "test_endpoint/test/url"), - Field(&HttpRequest::headers, + Field(&ProxyRequest::uri, "test_endpoint/test/url"), + Field(&ProxyRequest::headers, Contains(Pair("X-Auth-Token", "fake-token-2"))))))) - .WillOnce(Return(HttpResponse{.code = 200, .body = "test body"})); + .WillOnce(Return(ProxyResponse{{.code = 200, .body = "test body"}})); std::unique_ptr<milotic::RedfishPlugin> plugins[] = { std::move(instance), std::move(default_plugin)}; @@ -400,18 +393,18 @@ for (int i = 0; i < 2; ++i) { auto request = test_env.proxy.CreateRequest("/test/url"); request->headers["Force-Refresh-Token"] = "True"; - absl::StatusOr<HttpResponse> resp = + absl::StatusOr<ProxyResponse> resp = test_env.proxy.DispatchRequest(RequestVerb::kGet, std::move(request)); EXPECT_THAT(resp, - IsOkAndHolds(AllOf(Field(&HttpResponse::code, 200), - Field(&HttpResponse::body, "test body")))); + IsOkAndHolds(AllOf(Field(&ProxyResponse::code, 200), + Field(&ProxyResponse::body, "test body")))); } } TEST(RedfishSessionAuthTest, SessionRefreshWorksIfDeleteFails) { - const HttpResponse session_service = ValidSessionService(); - const HttpResponse session1 = ValidSession("test_session1", "fake-token-1"); - const HttpResponse session2 = ValidSession("test_session2", "fake-token-2"); + const ProxyResponse session_service = ValidSessionService(); + const ProxyResponse session1 = ValidSession("test_session1", "fake-token-1"); + const ProxyResponse session2 = ValidSession("test_session2", "fake-token-2"); const nlohmann::json expected_request = {{"UserName", "test_username"}, {"Password", "test_password"}}; @@ -430,7 +423,7 @@ EXPECT_CALL( *default_plugin, HandleRequest(RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService")))) .WillOnce(Return(session_service)); @@ -439,9 +432,9 @@ HandleRequest( RequestVerb::kPost, Pointee(AllOf( - Field(&HttpRequest::uri, + Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions"), - Field(&HttpRequest::body, + Field(&ProxyRequest::body, ResultOf(parse_json, expected_request)))))) .WillOnce(Return(session1)); @@ -449,29 +442,29 @@ HandleRequest( RequestVerb::kGet, Pointee(AllOf( - Field(&HttpRequest::uri, "test_endpoint/test/url"), - Field(&HttpRequest::headers, + Field(&ProxyRequest::uri, "test_endpoint/test/url"), + Field(&ProxyRequest::headers, Contains(Pair("X-Auth-Token", "fake-token-1"))))))) - .WillOnce(Return(HttpResponse{.code = 200, .body = "test body"})); + .WillOnce(Return(ProxyResponse{{.code = 200, .body = "test body"}})); EXPECT_CALL(*default_plugin, HandleRequest( RequestVerb::kDelete, Pointee(AllOf( - Field(&HttpRequest::uri, + Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions/" "test_session1"), - Field(&HttpRequest::headers, + Field(&ProxyRequest::headers, Contains(Pair("X-Auth-Token", "fake-token-1"))))))) - .WillOnce(Return(HttpResponse{.code = 404})); + .WillOnce(Return(ProxyResponse{{.code = 404}})); EXPECT_CALL(*default_plugin, HandleRequest( RequestVerb::kPost, Pointee(AllOf( - Field(&HttpRequest::uri, + Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions"), - Field(&HttpRequest::body, + Field(&ProxyRequest::body, ResultOf(parse_json, expected_request)))))) .WillOnce(Return(session2)); @@ -479,10 +472,10 @@ HandleRequest( RequestVerb::kGet, Pointee(AllOf( - Field(&HttpRequest::uri, "test_endpoint/test/url"), - Field(&HttpRequest::headers, + Field(&ProxyRequest::uri, "test_endpoint/test/url"), + Field(&ProxyRequest::headers, Contains(Pair("X-Auth-Token", "fake-token-2"))))))) - .WillOnce(Return(HttpResponse{.code = 200, .body = "test body"})); + .WillOnce(Return(ProxyResponse{{.code = 200, .body = "test body"}})); std::unique_ptr<milotic::RedfishPlugin> plugins[] = { std::move(instance), std::move(default_plugin)}; @@ -491,17 +484,17 @@ for (int i = 0; i < 2; ++i) { auto request = test_env.proxy.CreateRequest("/test/url"); request->headers["Force-Refresh-Token"] = "True"; - absl::StatusOr<HttpResponse> resp = + absl::StatusOr<ProxyResponse> resp = test_env.proxy.DispatchRequest(RequestVerb::kGet, std::move(request)); EXPECT_THAT(resp, - IsOkAndHolds(AllOf(Field(&HttpResponse::code, 200), - Field(&HttpResponse::body, "test body")))); + IsOkAndHolds(AllOf(Field(&ProxyResponse::code, 200), + Field(&ProxyResponse::body, "test body")))); } } TEST(RedfishSessionAuthTest, ParallelRequestsGetTokenOnce) { - const HttpResponse session_service = ValidSessionService(); - const HttpResponse session = ValidSession("test_session", "fake-token"); + const ProxyResponse session_service = ValidSessionService(); + const ProxyResponse session = ValidSession("test_session", "fake-token"); const nlohmann::json expected_request = {{"UserName", "test_username"}, {"Password", "test_password"}}; @@ -522,18 +515,18 @@ HandleRequest( RequestVerb::kPost, Pointee( - AllOf(Field(&HttpRequest::uri, + AllOf(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions"), - Field(&HttpRequest::body, + Field(&ProxyRequest::body, ResultOf(parse_json, expected_request)))))) .WillOnce(Invoke([&session] { absl::SleepFor(absl::Seconds(1)); - return HttpResponse(session); + return ProxyResponse(session); })); EXPECT_CALL(*default_plugin, HandleRequest( RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService")))) .WillOnce(Return(session_service)); } @@ -542,11 +535,12 @@ *default_plugin, HandleRequest( RequestVerb::kGet, - Pointee(AllOf(Field(&HttpRequest::uri, "test_endpoint/test/url"), - Field(&HttpRequest::headers, + Pointee(AllOf(Field(&ProxyRequest::uri, "test_endpoint/test/url"), + Field(&ProxyRequest::headers, Contains(Pair("X-Auth-Token", "fake-token"))))))) .Times(2) - .WillRepeatedly(Return(HttpResponse{.code = 200, .body = "test body"})); + .WillRepeatedly( + Return(ProxyResponse{{.code = 200, .body = "test body"}})); std::unique_ptr<milotic::RedfishPlugin> plugins[] = { std::move(instance), std::move(default_plugin)}; @@ -561,7 +555,7 @@ proxy.CreateRequest("/test/url")); } milotic::Proxy& proxy; - absl::StatusOr<HttpResponse> resp; + absl::StatusOr<ProxyResponse> resp; }; std::array<RequestThread, 2> threads = {RequestThread(test_env.proxy), @@ -572,19 +566,17 @@ for (RequestThread& thread : threads) { thread.Join(); EXPECT_THAT(thread.resp, - IsOkAndHolds(AllOf(Field(&HttpResponse::code, 200), - Field(&HttpResponse::body, "test body")))); + IsOkAndHolds(AllOf(Field(&ProxyResponse::code, 200), + Field(&ProxyResponse::body, "test body")))); } } TEST(RedfishSessionAuthTest, RequestsTryToRunAfterSessionFail) { - const HttpResponse session_service = ValidSessionService(); + const ProxyResponse session_service = ValidSessionService(); - const HttpResponse session_failure = { - .code = 401, - }; + const ProxyResponse session_failure(401); - HttpResponse missing_token = ValidSession("test_session", ""); + ProxyResponse missing_token = ValidSession("test_session", ""); missing_token.headers.erase("X-Auth-Token"); const nlohmann::json expected_request = {{"UserName", "test_username"}, @@ -601,16 +593,16 @@ EXPECT_CALL( *default_plugin, HandleRequest(RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService")))) .WillRepeatedly(Return(session_service)); EXPECT_CALL(*default_plugin, HandleRequest( RequestVerb::kPost, Pointee(AllOf( - Field(&HttpRequest::uri, + Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions"), - Field(&HttpRequest::body, + Field(&ProxyRequest::body, ResultOf(parse_json, expected_request)))))) .WillOnce(Return(session_failure)) .WillOnce(Return(missing_token)); @@ -619,30 +611,30 @@ *default_plugin, HandleRequest( RequestVerb::kGet, - Pointee(AllOf(Field(&HttpRequest::uri, "test_endpoint/test/url"), - Field(&HttpRequest::headers, + Pointee(AllOf(Field(&ProxyRequest::uri, "test_endpoint/test/url"), + Field(&ProxyRequest::headers, Not(Contains(Pair("X-Auth-Token", _)))))))) .Times(2) - .WillRepeatedly(Return(HttpResponse{.code = 401})); + .WillRepeatedly(Return(ProxyResponse{{.code = 401}})); std::unique_ptr<milotic::RedfishPlugin> plugins[] = { std::move(instance), std::move(default_plugin)}; TestEnv test_env(plugins); for (int i = 0; i < 2; i++) { - absl::StatusOr<HttpResponse> resp = test_env.proxy.DispatchRequest( + absl::StatusOr<ProxyResponse> resp = test_env.proxy.DispatchRequest( RequestVerb::kGet, test_env.proxy.CreateRequest("/test/url")); - EXPECT_THAT(resp, IsOkAndHolds(Field(&HttpResponse::code, 401))); + EXPECT_THAT(resp, IsOkAndHolds(Field(&ProxyResponse::code, 401))); EXPECT_THAT(GetState(&test_env), IsOkAndHolds(RedfishSessionAuthPlugin::SessionState::kFailed)); } } TEST(RedfishSessionAuthTest, RequestsRunIfBadSessionService) { - const HttpResponse not_found = { - .code = 404, + const ProxyResponse not_found( + 404, // This won't normally be there, but we should ignore it if it is. - .body = R"json({ + R"json({ "@odata.id": "/redfish/v1/SessionService/", "@odata.type": "#SessionService.v1_0_2.SessionService", "Description": "Session Service", @@ -653,17 +645,12 @@ "Sessions": { "@odata.id": "/redfish/v1/SessionService/Sessions" } - })json", - }; + })json"); - const HttpResponse invalid_json = { - .code = 200, - .body = "invalid json", - }; + const ProxyResponse invalid_json(200, "invalid json"); - const HttpResponse missing_session_timeout = { - .code = 200, - .body = R"json({ + const ProxyResponse missing_session_timeout(200, + R"json({ "@odata.id": "/redfish/v1/SessionService/", "@odata.type": "#SessionService.v1_0_2.SessionService", "Description": "Session Service", @@ -674,12 +661,10 @@ "@odata.id": "/redfish/v1/SessionService/Sessions" } })json", - .headers = {{"OData-Version", "4.0"}}, - }; + {{"OData-Version", "4.0"}}); - const HttpResponse invalid_session_timeout = { - .code = 200, - .body = R"json({ + const ProxyResponse invalid_session_timeout(200, + R"json({ "@odata.id": "/redfish/v1/SessionService/", "@odata.type": "#SessionService.v1_0_2.SessionService", "Description": "Session Service", @@ -691,10 +676,9 @@ "@odata.id": "/redfish/v1/SessionService/Sessions" } })json", - .headers = {{"OData-Version", "4.0"}}, - }; + {{"OData-Version", "4.0"}}); - const HttpResponse session = ValidSession("test_session", "fake-token"); + const ProxyResponse session = ValidSession("test_session", "fake-token"); auto instance = CreatePlugin(); ON_CALL(*instance, Now()).WillByDefault(Return(absl::Now())); @@ -708,14 +692,14 @@ *default_plugin, HandleRequest( RequestVerb::kPost, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions")))) .WillOnce(Return(session)); EXPECT_CALL( *default_plugin, HandleRequest(RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService")))) .WillOnce(Return(not_found)) .WillOnce(Return(invalid_json)) @@ -726,31 +710,30 @@ *default_plugin, HandleRequest( RequestVerb::kGet, - Pointee(AllOf(Field(&HttpRequest::uri, "test_endpoint/test/url"), - Field(&HttpRequest::headers, + Pointee(AllOf(Field(&ProxyRequest::uri, "test_endpoint/test/url"), + Field(&ProxyRequest::headers, Contains(Pair("X-Auth-Token", "fake-token"))))))) .Times(4) - .WillRepeatedly(Return(HttpResponse{.code = 200, .body = "test body"})); + .WillRepeatedly( + Return(ProxyResponse{{.code = 200, .body = "test body"}})); std::unique_ptr<milotic::RedfishPlugin> plugins[] = { std::move(instance), std::move(default_plugin)}; TestEnv test_env(plugins); for (int i = 0; i < 4; i++) { - absl::StatusOr<HttpResponse> resp = test_env.proxy.DispatchRequest( + absl::StatusOr<ProxyResponse> resp = test_env.proxy.DispatchRequest( RequestVerb::kGet, test_env.proxy.CreateRequest("/test/url")); EXPECT_THAT(resp, - IsOkAndHolds(AllOf(Field(&HttpResponse::code, 200), - Field(&HttpResponse::body, "test body")))); + IsOkAndHolds(AllOf(Field(&ProxyResponse::code, 200), + Field(&ProxyResponse::body, "test body")))); EXPECT_THAT(GetState(&test_env), IsOkAndHolds(RedfishSessionAuthPlugin::SessionState::kOk)); } } TEST(RedfishSessionAuthTest, FallbackToBasicAuth) { - const HttpResponse not_found = { - .code = 404, - }; + const ProxyResponse not_found(404); auto instance = CreatePlugin(); ON_CALL(*instance, Now()).WillByDefault(Return(absl::Now())); @@ -764,7 +747,7 @@ *default_plugin, HandleRequest( RequestVerb::kPost, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions")))) .WillRepeatedly(Return(not_found)); @@ -773,22 +756,22 @@ HandleRequest( RequestVerb::kGet, Pointee(AllOf( - Field(&HttpRequest::uri, "test_endpoint/test/url"), - Field(&HttpRequest::headers, + Field(&ProxyRequest::uri, "test_endpoint/test/url"), + Field(&ProxyRequest::headers, Contains( Pair("Authorization", "Basic dGVzdF91c2VybmFtZTp0ZXN0X3Bhc3N3b3Jk"))))))) - .WillOnce(Return(HttpResponse{.code = 200, .body = "test body"})); + .WillOnce(Return(ProxyResponse{{.code = 200, .body = "test body"}})); std::unique_ptr<milotic::RedfishPlugin> plugins[] = { std::move(instance), std::move(default_plugin)}; TestEnv test_env(plugins); - absl::StatusOr<HttpResponse> resp = test_env.proxy.DispatchRequest( + absl::StatusOr<ProxyResponse> resp = test_env.proxy.DispatchRequest( RequestVerb::kGet, test_env.proxy.CreateRequest("/test/url")); EXPECT_THAT(resp, - IsOkAndHolds(AllOf(Field(&HttpResponse::code, 200), - Field(&HttpResponse::body, "test body")))); + IsOkAndHolds(AllOf(Field(&ProxyResponse::code, 200), + Field(&ProxyResponse::body, "test body")))); EXPECT_THAT(GetState(&test_env), IsOkAndHolds(RedfishSessionAuthPlugin::SessionState::kFailed)); } @@ -811,7 +794,7 @@ *default_plugin, HandleRequest( RequestVerb::kPost, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions")))) .Times(0); @@ -820,29 +803,29 @@ HandleRequest( RequestVerb::kGet, Pointee(AllOf( - Field(&HttpRequest::uri, "test_endpoint/test/url"), - Field(&HttpRequest::headers, + Field(&ProxyRequest::uri, "test_endpoint/test/url"), + Field(&ProxyRequest::headers, Contains( Pair("Authorization", "Basic dGVzdF91c2VybmFtZTp0ZXN0X3Bhc3N3b3Jk"))))))) - .WillOnce(Return(HttpResponse{.code = 200, .body = "test body"})); + .WillOnce(Return(ProxyResponse{{.code = 200, .body = "test body"}})); std::unique_ptr<milotic::RedfishPlugin> plugins[] = { std::move(instance), std::move(default_plugin)}; TestEnv test_env(plugins); - absl::StatusOr<HttpResponse> resp = test_env.proxy.DispatchRequest( + absl::StatusOr<ProxyResponse> resp = test_env.proxy.DispatchRequest( RequestVerb::kGet, test_env.proxy.CreateRequest("/test/url")); EXPECT_THAT(resp, - IsOkAndHolds(AllOf(Field(&HttpResponse::code, 200), - Field(&HttpResponse::body, "test body")))); + IsOkAndHolds(AllOf(Field(&ProxyResponse::code, 200), + Field(&ProxyResponse::body, "test body")))); EXPECT_THAT(GetState(&test_env), IsOkAndHolds(RedfishSessionAuthPlugin::SessionState::kDisabled)); } TEST(RedfishSessionAuthTest, CredentialsReadFromFile) { - const HttpResponse session_service = ValidSessionService(); - const HttpResponse session = ValidSession("test_session", "fake-token"); + const ProxyResponse session_service = ValidSessionService(); + const ProxyResponse session = ValidSession("test_session", "fake-token"); auto instance = CreatePlugin(ecclesia::ParseTextAsProtoOrDie<RedfishSessionAuth>(R"pb( @@ -865,7 +848,7 @@ ON_CALL(*default_plugin, PreprocessRequest) .WillByDefault(Return(RequestAction::kHandle)); - HttpRequest session_request; + ProxyRequest session_request; { ::testing::InSequence redfish_session_sequence; @@ -873,13 +856,13 @@ *default_plugin, HandleRequest( RequestVerb::kPost, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions")))) .WillOnce(DoAll(SaveArgPointee<1>(&session_request), Return(session))); EXPECT_CALL(*default_plugin, HandleRequest( RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService")))) .WillOnce(Return(session_service)); } @@ -887,26 +870,26 @@ EXPECT_CALL(*default_plugin, HandleRequest( RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, "test_endpoint/test/url")))) - .WillOnce(Return(HttpResponse{.code = 200, .body = "test body"})); + Pointee(Field(&ProxyRequest::uri, "test_endpoint/test/url")))) + .WillOnce(Return(ProxyResponse{{.code = 200, .body = "test body"}})); std::unique_ptr<milotic::RedfishPlugin> plugins[] = { std::move(instance), std::move(default_plugin)}; TestEnv test_env(plugins); - absl::StatusOr<HttpResponse> resp = test_env.proxy.DispatchRequest( + absl::StatusOr<ProxyResponse> resp = test_env.proxy.DispatchRequest( RequestVerb::kGet, test_env.proxy.CreateRequest("/test/url")); EXPECT_THAT(resp, - IsOkAndHolds(AllOf(Field(&HttpResponse::code, 200), - Field(&HttpResponse::body, "test body")))); + IsOkAndHolds(AllOf(Field(&ProxyResponse::code, 200), + Field(&ProxyResponse::body, "test body")))); nlohmann::json request = nlohmann::json::parse(session_request.body); EXPECT_EQ(request["UserName"], "new_username"); EXPECT_EQ(request["Password"], "new_password"); } TEST(RedfishSessionAuthTest, CredentialsWithoutUsernameReadFromFile) { - const HttpResponse session_service = ValidSessionService(); - const HttpResponse session = ValidSession("test_session", "fake-token"); + const ProxyResponse session_service = ValidSessionService(); + const ProxyResponse session = ValidSession("test_session", "fake-token"); auto instance = CreatePlugin(ecclesia::ParseTextAsProtoOrDie<RedfishSessionAuth>(R"pb( @@ -928,7 +911,7 @@ ON_CALL(*default_plugin, PreprocessRequest) .WillByDefault(Return(RequestAction::kHandle)); - HttpRequest session_request; + ProxyRequest session_request; { ::testing::InSequence redfish_session_sequence; @@ -936,13 +919,13 @@ *default_plugin, HandleRequest( RequestVerb::kPost, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions")))) .WillOnce(DoAll(SaveArgPointee<1>(&session_request), Return(session))); EXPECT_CALL(*default_plugin, HandleRequest( RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService")))) .WillOnce(Return(session_service)); } @@ -950,26 +933,26 @@ EXPECT_CALL(*default_plugin, HandleRequest( RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, "test_endpoint/test/url")))) - .WillOnce(Return(HttpResponse{.code = 200, .body = "test body"})); + Pointee(Field(&ProxyRequest::uri, "test_endpoint/test/url")))) + .WillOnce(Return(ProxyResponse{{.code = 200, .body = "test body"}})); std::unique_ptr<milotic::RedfishPlugin> plugins[] = { std::move(instance), std::move(default_plugin)}; TestEnv test_env(plugins); - absl::StatusOr<HttpResponse> resp = test_env.proxy.DispatchRequest( + absl::StatusOr<ProxyResponse> resp = test_env.proxy.DispatchRequest( RequestVerb::kGet, test_env.proxy.CreateRequest("/test/url")); EXPECT_THAT(resp, - IsOkAndHolds(AllOf(Field(&HttpResponse::code, 200), - Field(&HttpResponse::body, "test body")))); + IsOkAndHolds(AllOf(Field(&ProxyResponse::code, 200), + Field(&ProxyResponse::body, "test body")))); nlohmann::json request = nlohmann::json::parse(session_request.body); EXPECT_EQ(request["UserName"], "test_username"); EXPECT_EQ(request["Password"], "new_password"); } TEST(RedfishSessionAuthTest, CredentialsErrorCausesRetries) { - const HttpResponse session_service = ValidSessionService(); - const HttpResponse session = ValidSession("test_session", "fake-token"); + const ProxyResponse session_service = ValidSessionService(); + const ProxyResponse session = ValidSession("test_session", "fake-token"); auto instance = CreatePlugin(ecclesia::ParseTextAsProtoOrDie<RedfishSessionAuth>(R"pb( @@ -995,28 +978,29 @@ EXPECT_CALL( *default_plugin, HandleRequest(RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService")))) .WillOnce(Return(session_service)); EXPECT_CALL( *default_plugin, HandleRequest( RequestVerb::kPost, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions")))) .WillOnce(Return(session)); - HttpRequest resource_request_fail; - HttpRequest resource_request_pass; + ProxyRequest resource_request_fail; + ProxyRequest resource_request_pass; EXPECT_CALL(*default_plugin, HandleRequest( RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, "test_endpoint/test/url")))) + Pointee(Field(&ProxyRequest::uri, "test_endpoint/test/url")))) .WillOnce(DoAll(SaveArgPointee<1>(&resource_request_fail), - Return(HttpResponse{.code = 401}))) - .WillOnce(DoAll(SaveArgPointee<1>(&resource_request_pass), - Return(HttpResponse{.code = 200, .body = "test body"}))); + Return(ProxyResponse{{.code = 401}}))) + .WillOnce( + DoAll(SaveArgPointee<1>(&resource_request_pass), + Return(ProxyResponse{{.code = 200, .body = "test body"}}))); std::unique_ptr<milotic::RedfishPlugin> plugins[] = { std::move(instance), std::move(default_plugin)}; @@ -1043,12 +1027,12 @@ const nlohmann::json expected_request = {{"UserName", "test_username"}, {"Password", "test_password"}}; - const HttpResponse session_service = ValidSessionService(); - const HttpResponse session = ValidSession("test_session", "fake-token"); + const ProxyResponse session_service = ValidSessionService(); + const ProxyResponse session = ValidSession("test_session", "fake-token"); constexpr std::string_view sessions_list[] = { "/redfish/v1/SessionService/Session/test_session", "/redfish/v1/SessionService/Sessions/other_session"}; - const HttpResponse sessions = ValidSessions(sessions_list); + const ProxyResponse sessions = ValidSessions(sessions_list); auto instance = CreatePlugin(); ON_CALL(*instance, Now()).WillByDefault(Return(absl::Now())); @@ -1064,10 +1048,11 @@ HandleRequest( RequestVerb::kPost, Pointee(AllOf( - Field(&HttpRequest::uri, + Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions"), - Field(&HttpRequest::body, ResultOf(parse_json, expected_request)), - Field(&HttpRequest::headers, + Field(&ProxyRequest::body, + ResultOf(parse_json, expected_request)), + Field(&ProxyRequest::headers, IsSupersetOf( {Pair("Content-Type", "application/json;charset=utf-8"), Pair("OData-Version", "4.0")})))))) @@ -1075,14 +1060,14 @@ EXPECT_CALL( *default_plugin, HandleRequest(RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService")))) .WillOnce(Return(session_service)); EXPECT_CALL( *default_plugin, HandleRequest( RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions")))) .WillOnce(Return(sessions)); @@ -1096,12 +1081,12 @@ const nlohmann::json expected_request = {{"UserName", "test_username"}, {"Password", "test_password"}}; - const HttpResponse session_service = ValidSessionService(); - const HttpResponse session = ValidSession("test_session", "fake-token"); + const ProxyResponse session_service = ValidSessionService(); + const ProxyResponse session = ValidSession("test_session", "fake-token"); constexpr std::string_view sessions_list[] = { "/redfish/v1/SessionService/Session/test_session", "/redfish/v1/SessionService/Sessions/other_session"}; - const HttpResponse sessions = ValidSessions(sessions_list); + const ProxyResponse sessions = ValidSessions(sessions_list); auto instance = CreatePlugin(ecclesia::ParseTextAsProtoOrDie<RedfishSessionAuth>(R"pb( @@ -1122,10 +1107,11 @@ HandleRequest( RequestVerb::kPost, Pointee(AllOf( - Field(&HttpRequest::uri, + Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions"), - Field(&HttpRequest::body, ResultOf(parse_json, expected_request)), - Field(&HttpRequest::headers, + Field(&ProxyRequest::body, + ResultOf(parse_json, expected_request)), + Field(&ProxyRequest::headers, IsSupersetOf( {Pair("Content-Type", "application/json;charset=utf-8"), Pair("OData-Version", "4.0")})))))) @@ -1133,7 +1119,7 @@ EXPECT_CALL( *default_plugin, HandleRequest(RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService")))) .WillOnce(Return(session_service)); std::vector<absl::Time> session_check_times; @@ -1141,7 +1127,7 @@ *default_plugin, HandleRequest( RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions")))) .Times(2) .WillRepeatedly(DoAll(InvokeWithoutArgs([&session_check_times] { @@ -1164,12 +1150,12 @@ const nlohmann::json expected_request = {{"UserName", "test_username"}, {"Password", "test_password"}}; - const HttpResponse session_service = ValidSessionService(); - const HttpResponse session = ValidSession("test_session", "fake-token"); + const ProxyResponse session_service = ValidSessionService(); + const ProxyResponse session = ValidSession("test_session", "fake-token"); constexpr std::string_view sessions_list[] = { "/redfish/v1/SessionService/Session/test_session", "/redfish/v1/SessionService/Sessions/other_session"}; - const HttpResponse sessions = ValidSessions(sessions_list); + const ProxyResponse sessions = ValidSessions(sessions_list); auto instance = CreatePlugin(ecclesia::ParseTextAsProtoOrDie<RedfishSessionAuth>(R"pb( @@ -1187,7 +1173,7 @@ EXPECT_CALL( *default_plugin, HandleRequest(RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService")))) .WillOnce(Return(session_service)); EXPECT_CALL( @@ -1195,10 +1181,11 @@ HandleRequest( RequestVerb::kPost, Pointee(AllOf( - Field(&HttpRequest::uri, + Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions"), - Field(&HttpRequest::body, ResultOf(parse_json, expected_request)), - Field(&HttpRequest::headers, + Field(&ProxyRequest::body, + ResultOf(parse_json, expected_request)), + Field(&ProxyRequest::headers, IsSupersetOf( {Pair("Content-Type", "application/json;charset=utf-8"), Pair("OData-Version", "4.0")})))))) @@ -1208,10 +1195,10 @@ *default_plugin, HandleRequest( RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions")))) .WillOnce(Return(sessions)) - .WillOnce(Return(HttpResponse{.code = 402})) + .WillOnce(Return(ProxyResponse{{.code = 402}})) .WillOnce(Return(sessions)); std::unique_ptr<milotic::RedfishPlugin> plugins[] = { @@ -1232,12 +1219,12 @@ const nlohmann::json expected_request = {{"UserName", "test_username"}, {"Password", "test_password"}}; - const HttpResponse session_service = ValidSessionService(); - const HttpResponse session = ValidSession("test_session", "fake-token"); + const ProxyResponse session_service = ValidSessionService(); + const ProxyResponse session = ValidSession("test_session", "fake-token"); constexpr std::string_view sessions_list[] = { "/redfish/v1/SessionService/Session/test_session", "/redfish/v1/SessionService/Sessions/other_session"}; - const HttpResponse sessions = ValidSessions(sessions_list); + const ProxyResponse sessions = ValidSessions(sessions_list); auto instance = CreatePlugin(ecclesia::ParseTextAsProtoOrDie<RedfishSessionAuth>(R"pb( @@ -1255,7 +1242,7 @@ EXPECT_CALL( *default_plugin, HandleRequest(RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService")))) .WillOnce(Return(session_service)); EXPECT_CALL( @@ -1263,32 +1250,33 @@ HandleRequest( RequestVerb::kPost, Pointee(AllOf( - Field(&HttpRequest::uri, + Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions"), - Field(&HttpRequest::body, ResultOf(parse_json, expected_request)), - Field(&HttpRequest::headers, + Field(&ProxyRequest::body, + ResultOf(parse_json, expected_request)), + Field(&ProxyRequest::headers, IsSupersetOf( {Pair("Content-Type", "application/json;charset=utf-8"), Pair("OData-Version", "4.0")})))))) .WillOnce(Return(session)) - .WillOnce(Return(HttpResponse{.code = 500})) + .WillOnce(Return(ProxyResponse{{.code = 500}})) .WillOnce(Return(session)); EXPECT_CALL( *default_plugin, HandleRequest( RequestVerb::kGet, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions")))) .WillOnce(Return(sessions)) - .WillOnce(Return(HttpResponse{.code = 401})); - EXPECT_CALL( - *default_plugin, - HandleRequest( - RequestVerb::kGet, - Pointee(AllOf(Field(&HttpRequest::uri, "test_endpoint/test_resource"), - Field(&HttpRequest::headers, - Contains(Pair("X-Auth-Token", "fake-token"))))))) - .WillOnce(Return(HttpResponse{.code = 200})); + .WillOnce(Return(ProxyResponse{{.code = 401}})); + EXPECT_CALL(*default_plugin, + HandleRequest( + RequestVerb::kGet, + Pointee(AllOf( + Field(&ProxyRequest::uri, "test_endpoint/test_resource"), + Field(&ProxyRequest::headers, + Contains(Pair("X-Auth-Token", "fake-token"))))))) + .WillOnce(Return(ProxyResponse{{.code = 200}})); std::unique_ptr<milotic::RedfishPlugin> plugins[] = { std::move(instance), std::move(default_plugin)}; @@ -1303,7 +1291,7 @@ EXPECT_THAT( test_env.proxy.DispatchRequest( RequestVerb::kGet, test_env.proxy.CreateRequest("/test_resource")), - IsOkAndHolds(Field(&HttpResponse::code, 200))); + IsOkAndHolds(Field(&ProxyResponse::code, 200))); EXPECT_THAT(GetState(&test_env), IsOkAndHolds(RedfishSessionAuthPlugin::SessionState::kOk)); } @@ -1313,7 +1301,7 @@ std::unique_ptr<milotic::RedfishPlugin> plugins[] = {std::move(instance)}; TestEnv test_env(plugins); ASSERT_OK_AND_ASSIGN( - HttpResponse resp, + ProxyResponse resp, test_env.proxy.DispatchRequest( RequestVerb::kInternal, test_env.proxy.CreateRequest( @@ -1330,13 +1318,13 @@ EXPECT_CALL(*default_plugin, PreprocessRequest(RequestVerb::kInternal, _)) .WillOnce(Return(RequestAction::kHandle)); EXPECT_CALL(*default_plugin, HandleRequest(RequestVerb::kInternal, _)) - .WillOnce(Return(HttpResponse{.code = 999})); + .WillOnce(Return(ProxyResponse{{.code = 999}})); std::unique_ptr<milotic::RedfishPlugin> plugins[] = { std::move(instance), std::move(default_plugin)}; TestEnv test_env(plugins); ASSERT_OK_AND_ASSIGN( - HttpResponse resp, + ProxyResponse resp, test_env.proxy.DispatchRequest( RequestVerb::kInternal, test_env.proxy.CreateRequest("/some_internal_resource"))); @@ -1345,8 +1333,8 @@ } TEST(RedfishSessionAuthTest, SessionServiceIsAccessedWithToken) { - const HttpResponse session_service = ValidSessionService(); - const HttpResponse session = ValidSession("test_session", "fake-token"); + const ProxyResponse session_service = ValidSessionService(); + const ProxyResponse session = ValidSession("test_session", "fake-token"); auto instance = CreatePlugin(); ON_CALL(*instance, Now()).WillByDefault(Return(absl::Now())); @@ -1359,16 +1347,16 @@ *default_plugin, HandleRequest( RequestVerb::kPost, - Pointee(Field(&HttpRequest::uri, + Pointee(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService/Sessions")))) .WillOnce(Return(session)); EXPECT_CALL( *default_plugin, HandleRequest( RequestVerb::kGet, - Pointee(AllOf(Field(&HttpRequest::uri, + Pointee(AllOf(Field(&ProxyRequest::uri, "test_endpoint/redfish/v1/SessionService"), - Field(&HttpRequest::headers, + Field(&ProxyRequest::headers, Contains(Pair("X-Auth-Token", "fake-token"))))))) .WillOnce(Return(session_service)); @@ -1376,10 +1364,10 @@ *default_plugin, HandleRequest( RequestVerb::kGet, - Pointee(AllOf(Field(&HttpRequest::uri, "test_endpoint/test/url"), - Field(&HttpRequest::headers, + Pointee(AllOf(Field(&ProxyRequest::uri, "test_endpoint/test/url"), + Field(&ProxyRequest::headers, Contains(Pair("X-Auth-Token", "fake-token"))))))) - .WillOnce(Return(HttpResponse{.code = 200, .body = "test body"})); + .WillOnce(Return(ProxyResponse{{.code = 200, .body = "test body"}})); std::unique_ptr<milotic::RedfishPlugin> plugins[] = { std::move(instance), std::move(default_plugin)}; @@ -1387,7 +1375,7 @@ EXPECT_THAT(test_env.proxy.DispatchRequest( RequestVerb::kGet, test_env.proxy.CreateRequest("/test/url")), - IsOkAndHolds(AllOf(Field(&HttpResponse::code, 200), - Field(&HttpResponse::body, "test body")))); + IsOkAndHolds(AllOf(Field(&ProxyResponse::code, 200), + Field(&ProxyResponse::body, "test body")))); } } // namespace
diff --git a/request_response.h b/request_response.h new file mode 100644 index 0000000..7b896b9 --- /dev/null +++ b/request_response.h
@@ -0,0 +1,68 @@ +#ifndef THIRD_PARTY_MILOTIC_INTERNAL_CC_PROXY_REQUEST_RESPONSE_H_ +#define THIRD_PARTY_MILOTIC_INTERNAL_CC_PROXY_REQUEST_RESPONSE_H_ + +#include <string> +#include <utility> + +#include "redfish_query_engine/http/client.h" + +namespace milotic { + +struct ProxyRequest : public ecclesia::HttpClient::HttpRequest { + ProxyRequest() = default; + + explicit ProxyRequest(ecclesia::HttpClient::HttpRequest request) + : ecclesia::HttpClient::HttpRequest{ + .uri = std::move(request.uri), + .unix_socket_path = std::move(request.unix_socket_path), + .body = std::move(request.body), + .headers = std::move(request.headers)} {} + + ProxyRequest(std::string uri_, std::string unix_socket_path_, + std::string body_, ecclesia::HttpClient::HttpHeaders headers_) + : ecclesia::HttpClient::HttpRequest{ + .uri = std::move(uri_), + .unix_socket_path = std::move(unix_socket_path_), + .body = std::move(body_), + .headers = std::move(headers_)} {} + + explicit ProxyRequest(std::string uri_) + : ecclesia::HttpClient::HttpRequest{.uri = std::move(uri_)} {} +}; + +struct ProxyResponse : public ecclesia::HttpClient::HttpResponse { + ProxyResponse() = default; + + explicit ProxyResponse(ecclesia::HttpClient::HttpResponse response) + : ecclesia::HttpClient::HttpResponse{ + .code = response.code, + .body = std::move(response.body), + .headers = std::move(response.headers)} {} + + ProxyResponse(int code_, std::string body_, + ecclesia::HttpClient::HttpHeaders headers_) + : ecclesia::HttpClient::HttpResponse{.code = code_, + .body = std::move(body_), + .headers = std::move(headers_)} {} + + ProxyResponse(int code_, std::string body_) + : ecclesia::HttpClient::HttpResponse{.code = code_, + .body = std::move(body_)} {} + ProxyResponse(int code_, ecclesia::HttpClient::HttpHeaders headers_) + : ecclesia::HttpClient::HttpResponse{.code = code_, + .headers = std::move(headers_)} {} + ProxyResponse(std::string body_, ecclesia::HttpClient::HttpHeaders headers_) + : ecclesia::HttpClient::HttpResponse{.body = std::move(body_), + .headers = std::move(headers_)} {} + + explicit ProxyResponse(int code_) + : ecclesia::HttpClient::HttpResponse{.code = code_} {} + explicit ProxyResponse(std::string body_) + : ecclesia::HttpClient::HttpResponse{.body = std::move(body_)} {} + explicit ProxyResponse(ecclesia::HttpClient::HttpHeaders headers_) + : ecclesia::HttpClient::HttpResponse{.headers = std::move(headers_)} {} +}; + +} // namespace milotic + +#endif // THIRD_PARTY_MILOTIC_INTERNAL_CC_PROXY_REQUEST_RESPONSE_H_
diff --git a/sse_plugin/events_manager.cc b/sse_plugin/events_manager.cc index c7a18e8..62e3e3b 100644 --- a/sse_plugin/events_manager.cc +++ b/sse_plugin/events_manager.cc
@@ -20,12 +20,12 @@ #include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" #include "absl/time/time.h" -#include "redfish_query_engine/http/client.h" #include "redfish_query_engine/http/codes.h" #include "nlohmann/json.hpp" #include "nlohmann/json_fwd.hpp" #include "metrics.h" #include "redfish_plugin.h" +#include "request_response.h" #include "sse/sse_parser.h" #include "sse_plugin/event.h" #include "vendor_events.pb.h" @@ -42,8 +42,6 @@ const int kVlogVerbosity = 1; } // namespace -using HttpResponse = ::ecclesia::HttpClient::HttpResponse; -using HttpRequest = ::ecclesia::HttpClient::HttpRequest; using ::ecclesia::HttpResponseCode::HTTP_CODE_REQUEST_OK; constexpr absl::string_view kRedfishEventServicePath = @@ -65,7 +63,7 @@ init_timer_restart_wait_(absl::Seconds(init_timer_restart_wait_sec)) {} ~RMCEventHandler() override = default; - absl::Status OnResponse(const HttpResponse &response) override; + absl::Status OnResponse(const ProxyResponse &response) override; absl::Status OnEvent(const google::protobuf::Message &event_message) override; absl::Status OnEvent(const milotic::ServerSentEvent &event) override; bool IsCancelled() const override; @@ -181,8 +179,7 @@ // For handling surrogate machines where SSE is not supported if (skip_sse_connection_) { LOG(INFO) << "ignoring SSE connection to RMC"; - rmc_handler.OnResponse(HttpResponse{.code = HTTP_CODE_REQUEST_OK}) - .IgnoreError(); + rmc_handler.OnResponse(ProxyResponse(HTTP_CODE_REQUEST_OK)).IgnoreError(); while (!IsStopping()) { clock_->Sleep(sse_connection_retry_delay_); VLOG(kVlogVerbosity) << "Validing connection to RMC"; @@ -198,7 +195,7 @@ LOG(INFO) << "Calling Subscribe, with LastEventId: " << machine_state_->LastEventId() << " attempt: " << attempt; - std::unique_ptr<HttpRequest> request = + std::unique_ptr<ProxyRequest> request = proxy_->CreateRequest(*sse_uri_response); request->headers = { {"Accept", "text/event-stream;charset=UTF-8"}, @@ -334,9 +331,9 @@ VLOG(kVlogVerbosity) << "GetRedfishbyURI: " << redfish_uri << " field: " << field.to_string(); - std::unique_ptr<HttpRequest> request = proxy_->CreateRequest(redfish_uri); + std::unique_ptr<ProxyRequest> request = proxy_->CreateRequest(redfish_uri); - HttpResponse response; + ProxyResponse response; ASSIGN_OR_RETURN(response, proxy_->DispatchRequest( milotic::RedfishPlugin::RequestVerb::kGet, std::move(request))); @@ -492,7 +489,7 @@ return health_change; } -absl::Status RMCEventHandler::OnResponse(const HttpResponse &response) { +absl::Status RMCEventHandler::OnResponse(const ProxyResponse &response) { VLOG(kVlogVerbosity) << "OnResponse body: " << response.code; if (response.code != HTTP_CODE_REQUEST_OK) { return absl::UnavailableError(absl::StrCat(
diff --git a/ssh_actions_plugin.cc b/ssh_actions_plugin.cc index 8f67f03..268fd22 100644 --- a/ssh_actions_plugin.cc +++ b/ssh_actions_plugin.cc
@@ -14,20 +14,17 @@ #include "absl/synchronization/notification.h" #include "absl/time/time.h" #include <source_location> -#include "redfish_query_engine/http/client.h" #include "redfish_query_engine/http/codes.h" #include "nlohmann/json.hpp" #include "proxy.h" #include "proxy_builder.h" #include "proxy_config.pb.h" #include "redfish_plugin.h" +#include "request_response.h" #include "ssh_client.h" namespace milotic { -using HttpRequest = ecclesia::HttpClient::HttpRequest; -using HttpResponse = ecclesia::HttpClient::HttpResponse; - using SshActionsConfig = ::milotic_grpc_proxy::Plugin::SshActions; SshActionsPlugin::SshActionsPlugin(const SshActionsConfig& config) @@ -71,7 +68,7 @@ } RedfishPlugin::RequestAction SshActionsPlugin::PreprocessRequest( - RedfishPlugin::RequestVerb verb, HttpRequest& request) { + RedfishPlugin::RequestVerb verb, ProxyRequest& request) { if (verb == RedfishPlugin::RequestVerb::kPost && actions_.contains(GetResourceId(request.uri))) { VLOG(1) << "Handle " << request.uri; @@ -81,20 +78,20 @@ } namespace { -HttpResponse ErrorResponse( +ProxyResponse ErrorResponse( const absl::Status& status, std::source_location location = std::source_location::current()) { LOG(ERROR).AtLocation(location.file_name(), static_cast<int>(location.line())) << status; - return HttpResponse{ - .code = ecclesia::HttpResponseCode::HTTP_CODE_ERROR, - .body = status.ToString(absl::StatusToStringMode::kWithNoExtraData), - .headers = {{"Content-Type", "text/plain"}}}; + return ProxyResponse{ + {.code = ecclesia::HttpResponseCode::HTTP_CODE_ERROR, + .body = status.ToString(absl::StatusToStringMode::kWithNoExtraData), + .headers = {{"Content-Type", "text/plain"}}}}; } } // namespace absl::StatusOr<std::string> SshActionsPlugin::GetCommand( const SshActionsPlugin::Action& action, - std::unique_ptr<HttpRequest> request) { + std::unique_ptr<ProxyRequest> request) { // Parse the optional command arguments from the request body. std::string command; auto obj = nlohmann::json::parse(request->body, nullptr, @@ -149,8 +146,8 @@ return command; } -absl::StatusOr<HttpResponse> SshActionsPlugin::HandleRequest( - RedfishPlugin::RequestVerb verb, std::unique_ptr<HttpRequest> request) { +absl::StatusOr<ProxyResponse> SshActionsPlugin::HandleRequest( + RedfishPlugin::RequestVerb verb, std::unique_ptr<ProxyRequest> request) { class Callbacks : public ExecutionCallbacks { public: virtual absl::Status OnStdout(ExecutionContext* context, @@ -212,12 +209,9 @@ if (!result.ok()) { return ErrorResponse(result.status()); } - return HttpResponse{ - .code = ecclesia::HttpResponseCode::HTTP_CODE_REQUEST_OK, - .body = result.value().dump(), - .headers = {{"Content-Type", "application/json"}, - {"OData-Version", "4.0"}}, - }; + return ProxyResponse( + ecclesia::HttpResponseCode::HTTP_CODE_REQUEST_OK, result.value().dump(), + {{"Content-Type", "application/json"}, {"OData-Version", "4.0"}}); } REGISTER_REDFISH_PLUGIN(ssh_actions, SshActionsPlugin);
diff --git a/ssh_actions_plugin.h b/ssh_actions_plugin.h index 3f45a7e..ff7d474 100644 --- a/ssh_actions_plugin.h +++ b/ssh_actions_plugin.h
@@ -9,9 +9,9 @@ #include "absl/status/statusor.h" #include "absl/strings/string_view.h" #include "absl/time/time.h" -#include "redfish_query_engine/http/client.h" #include "proxy_config.pb.h" #include "redfish_plugin.h" +#include "request_response.h" #include "ssh_client.h" namespace milotic { @@ -22,16 +22,15 @@ SshActionsPlugin(const SshActionsPlugin&) = delete; SshActionsPlugin& operator=(const SshActionsPlugin&) = delete; - RequestAction PreprocessRequest( - RedfishPlugin::RequestVerb verb, - ecclesia::HttpClient::HttpRequest& request) override; + RequestAction PreprocessRequest(RedfishPlugin::RequestVerb verb, + ProxyRequest& request) override; - absl::StatusOr<ecclesia::HttpClient::HttpResponse> HandleRequest( + absl::StatusOr<ProxyResponse> HandleRequest( RedfishPlugin::RequestVerb verb, - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request) override; + std::unique_ptr<ProxyRequest> request) override; - absl::Status Subscribe(std::unique_ptr<ecclesia::HttpClient::HttpRequest>, - EventHandler*) override { + absl::Status Subscribe(std::unique_ptr<ProxyRequest> /*request*/, + EventHandler* /*handler*/) override { return absl::UnknownError("Function should never be called"); } @@ -47,8 +46,7 @@ absl::string_view GetResourceId(absl::string_view url); static absl::StatusOr<std::string> GetCommand( - const Action& action, - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request); + const Action& action, std::unique_ptr<ProxyRequest> request); absl::flat_hash_map<std::string, Action> actions_; SshClient::CommandOptions common_command_options_;
diff --git a/ssh_actions_plugin_test.cc b/ssh_actions_plugin_test.cc index 9c30859..af59bc8 100644 --- a/ssh_actions_plugin_test.cc +++ b/ssh_actions_plugin_test.cc
@@ -10,13 +10,13 @@ #include "absl/status/statusor.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" -#include "redfish_query_engine/http/client.h" #include "redfish_query_engine/protobuf/parse.h" #include "nlohmann/json_fwd.hpp" #include "mock_ssh_client.h" #include "proxy.h" #include "proxy_config.pb.h" #include "redfish_plugin.h" +#include "request_response.h" #include "ssh_client.h" #include "voyager/deferrable_priority_queue.hpp" #include "voyager/priority_queue.hpp" @@ -38,8 +38,8 @@ using ::milotic::SshActionsPlugin; using ::voyager::DeferrablePriorityQueue; -using HttpRequest = ::ecclesia::HttpClient::HttpRequest; -using HttpResponse = ::ecclesia::HttpClient::HttpResponse; +using ProxyRequest = ::milotic::ProxyRequest; +using ProxyResponse = ::milotic::ProxyResponse; using SshActionsConfig = milotic_grpc_proxy::Plugin::SshActions; @@ -140,10 +140,10 @@ env.proxy.CreateRequest("/google/v1/Test/Actions/Action.2"))); ASSERT_EQ(job1->Wait(), voyager::Job::JobState::kDone); - ASSERT_OK_AND_ASSIGN(HttpResponse response1, job1->response()); + ASSERT_OK_AND_ASSIGN(ProxyResponse response1, job1->response()); ASSERT_EQ(job2->Wait(), voyager::Job::JobState::kDone); - ASSERT_OK_AND_ASSIGN(HttpResponse response2, job2->response()); + ASSERT_OK_AND_ASSIGN(ProxyResponse response2, job2->response()); EXPECT_EQ(response1.code, 200); const nlohmann::json expected_a = {{"StdOut", "data a1data a2"}, @@ -218,10 +218,10 @@ std::move(request_b))); ASSERT_EQ(job1->Wait(), voyager::Job::JobState::kDone); - ASSERT_OK_AND_ASSIGN(HttpResponse response1, job1->response()); + ASSERT_OK_AND_ASSIGN(ProxyResponse response1, job1->response()); ASSERT_EQ(job2->Wait(), voyager::Job::JobState::kDone); - ASSERT_OK_AND_ASSIGN(HttpResponse response2, job2->response()); + ASSERT_OK_AND_ASSIGN(ProxyResponse response2, job2->response()); EXPECT_EQ(response1.code, 200); const nlohmann::json expected_a = {{"StdOut", "data a1data a2"}, @@ -258,7 +258,7 @@ std::move(request_a))); ASSERT_EQ(job1->Wait(), voyager::Job::JobState::kDone); - ASSERT_OK_AND_ASSIGN(HttpResponse response1, job1->response()); + ASSERT_OK_AND_ASSIGN(ProxyResponse response1, job1->response()); EXPECT_EQ(response1.code, 200); EXPECT_THAT(response1.headers, @@ -278,7 +278,7 @@ std::move(request_a))); ASSERT_EQ(job1->Wait(), voyager::Job::JobState::kDone); - ASSERT_OK_AND_ASSIGN(HttpResponse response1, job1->response()); + ASSERT_OK_AND_ASSIGN(ProxyResponse response1, job1->response()); EXPECT_EQ(response1.code, 500); EXPECT_THAT(response1.headers, @@ -296,7 +296,7 @@ std::move(request_a))); ASSERT_EQ(job1->Wait(), voyager::Job::JobState::kDone); - ASSERT_OK_AND_ASSIGN(HttpResponse response1, job1->response()); + ASSERT_OK_AND_ASSIGN(ProxyResponse response1, job1->response()); EXPECT_EQ(response1.code, 500); EXPECT_THAT(response1.headers,
diff --git a/test_plugin.cc b/test_plugin.cc index 9f58f1f..740b811 100644 --- a/test_plugin.cc +++ b/test_plugin.cc
@@ -5,10 +5,10 @@ #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/string_view.h" -#include "redfish_query_engine/http/client.h" #include "proxy_builder.h" #include "proxy_config.pb.h" #include "redfish_plugin.h" +#include "request_response.h" namespace milotic { @@ -17,35 +17,33 @@ class TestPlugin : public RedfishPlugin { public: explicit TestPlugin(const milotic_grpc_proxy::Plugin::Test& config) - : id(config.fixed_redfish_id()) {} + : id_(config.fixed_redfish_id()) {} - RequestAction PreprocessRequest( - RedfishPlugin::RequestVerb verb, - ecclesia::HttpClient::HttpRequest& request) override { - request.uri = uri; + RequestAction PreprocessRequest(RedfishPlugin::RequestVerb verb, + ProxyRequest& request) override { + request.uri = uri_; return RequestAction::kNext; } - absl::StatusOr<ecclesia::HttpClient::HttpResponse> HandleRequest( + absl::StatusOr<ProxyResponse> HandleRequest( RedfishPlugin::RequestVerb verb, - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request) override { + std::unique_ptr<ProxyRequest> request) override { return absl::UnknownError("Should not be called"); } - absl::Status Subscribe( - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request, - EventHandler*) override { + absl::Status Subscribe(std::unique_ptr<ProxyRequest> request, + EventHandler* /*handler*/) override { return absl::UnknownError("Should not be called"); } - virtual absl::Status Initialize(Proxy* proxy) override { - uri = proxy->GetUrl(id); + absl::Status Initialize(Proxy* proxy) override { + uri_ = proxy->GetUrl(id_); return absl::OkStatus(); }; private: - std::string id; - std::string uri; + std::string id_; + std::string uri_; }; REGISTER_REDFISH_PLUGIN(test, TestPlugin); @@ -53,28 +51,27 @@ // This is a plugin for tests that does nothing. class TestDummyPlugin : public RedfishPlugin { public: - explicit TestDummyPlugin(const milotic_grpc_proxy::Plugin::TestDummy&) {} + explicit TestDummyPlugin( + const milotic_grpc_proxy::Plugin::TestDummy& /*config*/) {} - RequestAction PreprocessRequest( - RedfishPlugin::RequestVerb verb, - ecclesia::HttpClient::HttpRequest& request) override { + RequestAction PreprocessRequest(RedfishPlugin::RequestVerb verb, + ProxyRequest& request) override { assert(false); return RequestAction{}; } - absl::StatusOr<ecclesia::HttpClient::HttpResponse> HandleRequest( + absl::StatusOr<ProxyResponse> HandleRequest( RedfishPlugin::RequestVerb verb, - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request) override { + std::unique_ptr<ProxyRequest> request) override { assert(false); return absl::UnknownError("Should not be called"); } - absl::Status Subscribe( - std::unique_ptr<ecclesia::HttpClient::HttpRequest> request, - EventHandler*) override { + absl::Status Subscribe(std::unique_ptr<ProxyRequest> request, + EventHandler* /*handler*/) override { assert(false); return absl::UnknownError("Should not be called"); } - virtual absl::Status Initialize(Proxy*) override { + absl::Status Initialize(Proxy* /*proxy*/) override { assert(false); return absl::UnknownError("Should not be called"); }