1 // Copyright 2015 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <libwebserv/response_impl.h> 16 17 #include <algorithm> 18 19 #include <base/json/json_writer.h> 20 #include <base/logging.h> 21 #include <base/values.h> 22 #include <brillo/http/http_request.h> 23 #include <brillo/mime_utils.h> 24 #include <brillo/streams/memory_stream.h> 25 #include <brillo/strings/string_utils.h> 26 #include <libwebserv/dbus_protocol_handler.h> 27 28 namespace libwebserv { 29 30 ResponseImpl::ResponseImpl(DBusProtocolHandler* handler, 31 const std::string& request_id) 32 : handler_{handler}, request_id_{request_id} { 33 } 34 35 ResponseImpl::~ResponseImpl() { 36 if (!reply_sent_) { 37 ReplyWithError(brillo::http::status_code::InternalServerError, 38 "Internal server error"); 39 } 40 } 41 42 void ResponseImpl::AddHeader(const std::string& header_name, 43 const std::string& value) { 44 headers_.emplace(header_name, value); 45 } 46 47 void ResponseImpl::AddHeaders( 48 const std::vector<std::pair<std::string, std::string>>& headers) { 49 headers_.insert(headers.begin(), headers.end()); 50 } 51 52 void ResponseImpl::Reply(int status_code, 53 brillo::StreamPtr data_stream, 54 const std::string& mime_type) { 55 CHECK(data_stream); 56 status_code_ = status_code; 57 data_stream_ = std::move(data_stream); 58 AddHeader(brillo::http::response_header::kContentType, mime_type); 59 SendResponse(); 60 } 61 62 void ResponseImpl::ReplyWithText(int status_code, 63 const std::string& text, 64 const std::string& mime_type) { 65 Reply(status_code, brillo::MemoryStream::OpenCopyOf(text, nullptr), 66 mime_type); 67 } 68 69 void ResponseImpl::ReplyWithJson(int status_code, const base::Value* json) { 70 std::string text; 71 base::JSONWriter::WriteWithOptions( 72 *json, base::JSONWriter::OPTIONS_PRETTY_PRINT, &text); 73 std::string mime_type = brillo::mime::AppendParameter( 74 brillo::mime::application::kJson, 75 brillo::mime::parameters::kCharset, 76 "utf-8"); 77 ReplyWithText(status_code, text, mime_type); 78 } 79 80 void ResponseImpl::ReplyWithJson( 81 int status_code, const std::map<std::string, std::string>& json) { 82 base::DictionaryValue json_value; 83 for (const auto& pair : json) { 84 json_value.SetString(pair.first, pair.second); 85 } 86 ReplyWithJson(status_code, &json_value); 87 } 88 89 void ResponseImpl::Redirect(int status_code, const std::string& redirect_url) { 90 AddHeader(brillo::http::response_header::kLocation, redirect_url); 91 ReplyWithError(status_code, ""); 92 } 93 94 void ResponseImpl::ReplyWithError(int status_code, 95 const std::string& error_text) { 96 status_code_ = status_code; 97 data_stream_ = brillo::MemoryStream::OpenCopyOf(error_text, nullptr); 98 SendResponse(); 99 } 100 101 void ResponseImpl::ReplyWithErrorNotFound() { 102 ReplyWithError(brillo::http::status_code::NotFound, "Not Found"); 103 } 104 105 void ResponseImpl::SendResponse() { 106 CHECK(!reply_sent_) << "Response already sent"; 107 reply_sent_ = true; 108 handler_->CompleteRequest(request_id_, status_code_, headers_, 109 std::move(data_stream_)); 110 } 111 112 } // namespace libwebserv 113