blob: 8fc49f7c44c84f98733b920d94cc05f00083db7b [file] [log] [blame]
Daniel Erat35f65872015-08-17 20:59:29 -06001// 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.
Alex Vakulenko039da312015-02-03 08:58:55 -080014
15#include <libwebserv/response.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 <chromeos/http/http_request.h>
23#include <chromeos/mime_utils.h>
24#include <chromeos/strings/string_utils.h>
Alex Vakulenko31a63792015-02-03 12:44:57 -080025#include <libwebserv/protocol_handler.h>
Alex Vakulenko039da312015-02-03 08:58:55 -080026
27namespace libwebserv {
28
Alex Vakulenko31a63792015-02-03 12:44:57 -080029Response::Response(ProtocolHandler* handler, const std::string& request_id)
30 : handler_{handler}, request_id_{request_id} {
Alex Vakulenko039da312015-02-03 08:58:55 -080031}
32
33Response::~Response() {
34 if (!reply_sent_) {
35 ReplyWithError(chromeos::http::status_code::InternalServerError,
36 "Internal server error");
37 }
38}
39
Alex Vakulenko039da312015-02-03 08:58:55 -080040void Response::AddHeader(const std::string& header_name,
41 const std::string& value) {
42 headers_.emplace(header_name, value);
43}
44
45void Response::AddHeaders(
46 const std::vector<std::pair<std::string, std::string>>& headers) {
47 headers_.insert(headers.begin(), headers.end());
48}
49
50void Response::Reply(int status_code,
51 const void* data,
52 size_t data_size,
53 const std::string& mime_type) {
54 status_code_ = status_code;
55 const uint8_t* byte_ptr = static_cast<const uint8_t*>(data);
56 data_.assign(byte_ptr, byte_ptr + data_size);
57 AddHeader(chromeos::http::response_header::kContentType, mime_type);
58 SendResponse();
59}
60
61void Response::ReplyWithText(int status_code,
62 const std::string& text,
63 const std::string& mime_type) {
64 Reply(status_code, text.data(), text.size(), mime_type);
65}
66
67void Response::ReplyWithJson(int status_code, const base::Value* json) {
68 std::string text;
Alex Vakulenkoe88b8062015-06-15 12:53:22 -070069 base::JSONWriter::WriteWithOptions(
70 *json, base::JSONWriter::OPTIONS_PRETTY_PRINT, &text);
Alex Vakulenko039da312015-02-03 08:58:55 -080071 std::string mime_type = chromeos::mime::AppendParameter(
72 chromeos::mime::application::kJson,
73 chromeos::mime::parameters::kCharset,
74 "utf-8");
75 ReplyWithText(status_code, text, mime_type);
76}
77
78void Response::ReplyWithJson(int status_code,
79 const std::map<std::string, std::string>& json) {
80 base::DictionaryValue json_value;
81 for (const auto& pair : json) {
82 json_value.SetString(pair.first, pair.second);
83 }
84 ReplyWithJson(status_code, &json_value);
85}
86
87void Response::Redirect(int status_code, const std::string& redirect_url) {
88 AddHeader(chromeos::http::response_header::kLocation, redirect_url);
89 ReplyWithError(status_code, "");
90}
91
92void Response::ReplyWithError(int status_code, const std::string& error_text) {
93 status_code_ = status_code;
94 data_.assign(error_text.begin(), error_text.end());
95 SendResponse();
96}
97
98void Response::ReplyWithErrorNotFound() {
99 ReplyWithError(chromeos::http::status_code::NotFound, "Not Found");
100}
101
102void Response::SendResponse() {
103 CHECK(!reply_sent_) << "Response already sent";
104 reply_sent_ = true;
Alex Vakulenko31a63792015-02-03 12:44:57 -0800105 handler_->CompleteRequest(request_id_, status_code_, headers_, data_);
Alex Vakulenko039da312015-02-03 08:58:55 -0800106}
107
108} // namespace libwebserv