response.cc revision e88b8067863605485b966c074ba3bc5384da1763
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(
60      *json, base::JSONWriter::OPTIONS_PRETTY_PRINT, &text);
61  std::string mime_type = chromeos::mime::AppendParameter(
62      chromeos::mime::application::kJson,
63      chromeos::mime::parameters::kCharset,
64      "utf-8");
65  ReplyWithText(status_code, text, mime_type);
66}
67
68void Response::ReplyWithJson(int status_code,
69                             const std::map<std::string, std::string>& json) {
70  base::DictionaryValue json_value;
71  for (const auto& pair : json) {
72    json_value.SetString(pair.first, pair.second);
73  }
74  ReplyWithJson(status_code, &json_value);
75}
76
77void Response::Redirect(int status_code, const std::string& redirect_url) {
78  AddHeader(chromeos::http::response_header::kLocation, redirect_url);
79  ReplyWithError(status_code, "");
80}
81
82void Response::ReplyWithError(int status_code, const std::string& error_text) {
83  status_code_ = status_code;
84  data_.assign(error_text.begin(), error_text.end());
85  SendResponse();
86}
87
88void Response::ReplyWithErrorNotFound() {
89  ReplyWithError(chromeos::http::status_code::NotFound, "Not Found");
90}
91
92void Response::SendResponse() {
93  CHECK(!reply_sent_) << "Response already sent";
94  reply_sent_ = true;
95  handler_->CompleteRequest(request_id_, status_code_, headers_, data_);
96}
97
98}  // namespace libwebserv
99