response.cc revision 31a6379d5f773cb40312d2085e07f30cf3ac685d
1// Copyright 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <libwebserv/response.h>
6
7#include <algorithm>
8
9#include <base/json/json_writer.h>
10#include <base/logging.h>
11#include <base/values.h>
12#include <chromeos/http/http_request.h>
13#include <chromeos/mime_utils.h>
14#include <chromeos/strings/string_utils.h>
15#include <libwebserv/protocol_handler.h>
16
17namespace libwebserv {
18
19Response::Response(ProtocolHandler* handler, const std::string& request_id)
20    : handler_{handler}, request_id_{request_id} {
21}
22
23Response::~Response() {
24  if (!reply_sent_) {
25    ReplyWithError(chromeos::http::status_code::InternalServerError,
26                   "Internal server error");
27  }
28}
29
30void Response::AddHeader(const std::string& header_name,
31                         const std::string& value) {
32  headers_.emplace(header_name, value);
33}
34
35void Response::AddHeaders(
36    const std::vector<std::pair<std::string, std::string>>& headers) {
37  headers_.insert(headers.begin(), headers.end());
38}
39
40void Response::Reply(int status_code,
41                     const void* data,
42                     size_t data_size,
43                     const std::string& mime_type) {
44  status_code_ = status_code;
45  const uint8_t* byte_ptr = static_cast<const uint8_t*>(data);
46  data_.assign(byte_ptr, byte_ptr + data_size);
47  AddHeader(chromeos::http::response_header::kContentType, mime_type);
48  SendResponse();
49}
50
51void Response::ReplyWithText(int status_code,
52                             const std::string& text,
53                             const std::string& mime_type) {
54  Reply(status_code, text.data(), text.size(), mime_type);
55}
56
57void Response::ReplyWithJson(int status_code, const base::Value* json) {
58  std::string text;
59  base::JSONWriter::WriteWithOptions(json,
60                                     base::JSONWriter::OPTIONS_PRETTY_PRINT,
61                                     &text);
62  std::string mime_type = chromeos::mime::AppendParameter(
63      chromeos::mime::application::kJson,
64      chromeos::mime::parameters::kCharset,
65      "utf-8");
66  ReplyWithText(status_code, text, mime_type);
67}
68
69void Response::ReplyWithJson(int status_code,
70                             const std::map<std::string, std::string>& json) {
71  base::DictionaryValue json_value;
72  for (const auto& pair : json) {
73    json_value.SetString(pair.first, pair.second);
74  }
75  ReplyWithJson(status_code, &json_value);
76}
77
78void Response::Redirect(int status_code, const std::string& redirect_url) {
79  AddHeader(chromeos::http::response_header::kLocation, redirect_url);
80  ReplyWithError(status_code, "");
81}
82
83void Response::ReplyWithError(int status_code, const std::string& error_text) {
84  status_code_ = status_code;
85  data_.assign(error_text.begin(), error_text.end());
86  SendResponse();
87}
88
89void Response::ReplyWithErrorNotFound() {
90  ReplyWithError(chromeos::http::status_code::NotFound, "Not Found");
91}
92
93void Response::SendResponse() {
94  CHECK(!reply_sent_) << "Response already sent";
95  reply_sent_ = true;
96  handler_->CompleteRequest(request_id_, status_code_, headers_, data_);
97}
98
99}  // namespace libwebserv
100