blob: e03ec211347cd00024228ee54f8283c8ca04a317 [file] [log] [blame]
#include "tlbmc/redfish/response.h"
#include <string_view>
#include "absl/status/status.h"
#include "redfish_v1.pb.h"
#include "grpcpp/support/server_callback.h"
#include "grpcpp/support/status.h"
#include "nlohmann/json.hpp"
namespace milotic_tlbmc {
RedfishResponse::RedfishResponse(grpc::ServerUnaryReactor* reactor,
redfish::v1::Response& grpc_response)
: reactor_(reactor), grpc_response_(&grpc_response) {}
void RedfishResponse::End() {
// Don't send response if end has already been called.
if (end_called_) {
return;
}
end_called_ = true;
// If there is an async resp attached, then we will use it to send the
// response back instead of the reactor.
if (async_resp_ != nullptr) {
for (const auto& element : http_response_.base()) {
async_resp_->res.addHeader(element.name_string(), element.value());
}
async_resp_->res.result(http_response_.result());
async_resp_->res.body() = http_response_.body();
async_resp_->res.jsonValue = json_body_;
return;
}
// If there is no grpc response, then we don't need to send the response.
if (grpc_response_ == nullptr) {
return;
}
auto* headers = grpc_response_->mutable_headers();
for (const auto& element : http_response_.base()) {
// Repeated headers are combined into a ',' separated list. See
// https://www.rfc-editor.org/rfc/rfc9110.html#section-5.3-3.
auto found = headers->find(element.name_string());
if (found == headers->end()) {
(*headers)[element.name_string()] = element.value();
} else {
found->second += ",";
found->second += element.value();
}
}
if (http_response_["OData-Version"] == "4.0") {
*grpc_response_->mutable_json_str() = json_body_.dump(
-1, ' ', true, nlohmann::json::error_handler_t::replace);
} else {
*grpc_response_->mutable_octet_stream() = http_response_.body();
}
grpc_response_->set_code(static_cast<unsigned int>(http_response_.result()));
if (reactor_ != nullptr) {
reactor_->Finish(grpc::Status::OK);
}
}
void RedfishResponse::SetBodyToJson() {
http_response_.base().erase("OData-Version");
SetHeader("OData-Version", "4.0");
}
void RedfishResponse::SetBodyToOctetStream() {
http_response_.base().erase("OData-Version");
}
void RedfishResponse::SetHeader(std::string_view key, std::string_view value) {
http_response_.base().insert(key, value);
}
void RedfishResponse::SetBinaryBody(std::string_view body) {
http_response_.body() = body;
}
void RedfishResponse::SetToNotFound() {
http_response_.result(boost::beast::http::status::not_found);
}
void RedfishResponse::SetToForbidden() {
http_response_.result(boost::beast::http::status::forbidden);
}
void RedfishResponse::SetToNotReady() {
http_response_.result(boost::beast::http::status::service_unavailable);
}
void RedfishResponse::SetToNotReady(std::string_view error_message) {
SetToNotReady();
SetKeyInJsonBody("/error/message", error_message);
}
void RedfishResponse::SetToAbslStatus(const absl::Status& status) {
switch (status.code()) {
case absl::StatusCode::kNotFound:
SetToNotFound();
break;
case absl::StatusCode::kPermissionDenied:
SetToForbidden();
break;
case absl::StatusCode::kUnavailable:
SetToNotReady();
break;
default:
http_response_.result(boost::beast::http::status::internal_server_error);
break;
}
}
} // namespace milotic_tlbmc