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 28namespace libwebserv { 29 30ResponseImpl::ResponseImpl(DBusProtocolHandler* handler, 31 const std::string& request_id) 32 : handler_{handler}, request_id_{request_id} { 33} 34 35ResponseImpl::~ResponseImpl() { 36 if (!reply_sent_) { 37 ReplyWithError(brillo::http::status_code::InternalServerError, 38 "Internal server error"); 39 } 40} 41 42void ResponseImpl::AddHeader(const std::string& header_name, 43 const std::string& value) { 44 headers_.emplace(header_name, value); 45} 46 47void ResponseImpl::AddHeaders( 48 const std::vector<std::pair<std::string, std::string>>& headers) { 49 headers_.insert(headers.begin(), headers.end()); 50} 51 52void 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 62void 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 69void 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 80void 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 89void 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 94void 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 101void ResponseImpl::ReplyWithErrorNotFound() { 102 ReplyWithError(brillo::http::status_code::NotFound, "Not Found"); 103} 104 105void 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