Home | History | Annotate | Download | only in libwebserv
      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