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 <brillo/http/http_connection_fake.h>
6
7#include <base/logging.h>
8#include <brillo/bind_lambda.h>
9#include <brillo/http/http_request.h>
10#include <brillo/mime_utils.h>
11#include <brillo/streams/memory_stream.h>
12#include <brillo/strings/string_utils.h>
13
14namespace brillo {
15namespace http {
16namespace fake {
17
18Connection::Connection(const std::string& url,
19                       const std::string& method,
20                       const std::shared_ptr<http::Transport>& transport)
21    : http::Connection(transport), request_(url, method) {
22  VLOG(1) << "fake::Connection created: " << method;
23}
24
25Connection::~Connection() {
26  VLOG(1) << "fake::Connection destroyed";
27}
28
29bool Connection::SendHeaders(const HeaderList& headers,
30                             brillo::ErrorPtr* /* error */) {
31  request_.AddHeaders(headers);
32  return true;
33}
34
35bool Connection::SetRequestData(StreamPtr stream,
36                                brillo::ErrorPtr* /* error */) {
37  request_.SetData(std::move(stream));
38  return true;
39}
40
41bool Connection::FinishRequest(brillo::ErrorPtr*  /* error */) {
42  using brillo::string_utils::ToString;
43  request_.AddHeaders(
44      {{request_header::kContentLength, ToString(request_.GetData().size())}});
45  fake::Transport* transport = static_cast<fake::Transport*>(transport_.get());
46  CHECK(transport) << "Expecting a fake transport";
47  auto handler = transport->GetHandler(request_.GetURL(), request_.GetMethod());
48  if (handler.is_null()) {
49    LOG(ERROR) << "Received unexpected " << request_.GetMethod()
50               << " request at " << request_.GetURL();
51    response_.ReplyText(status_code::NotFound,
52                        "<html><body>Not found</body></html>",
53                        brillo::mime::text::kHtml);
54  } else {
55    handler.Run(request_, &response_);
56  }
57  return true;
58}
59
60RequestID Connection::FinishRequestAsync(
61    const SuccessCallback& success_callback,
62    const ErrorCallback& error_callback) {
63  // Make sure the produced Closure holds a reference to the instance of this
64  // connection.
65  auto connection = std::static_pointer_cast<Connection>(shared_from_this());
66  auto callback = [](std::shared_ptr<Connection> connection,
67                     const SuccessCallback& success_callback,
68                     const ErrorCallback& error_callback) {
69    connection->FinishRequestAsyncHelper(success_callback, error_callback);
70  };
71  transport_->RunCallbackAsync(FROM_HERE,
72                               base::Bind(callback,
73                                          base::Passed(&connection),
74                                          success_callback,
75                                          error_callback));
76  return 1;
77}
78
79void Connection::FinishRequestAsyncHelper(
80    const SuccessCallback& success_callback,
81    const ErrorCallback& error_callback) {
82  brillo::ErrorPtr error;
83  if (!FinishRequest(&error)) {
84    error_callback.Run(1, error.get());
85  } else {
86    std::unique_ptr<Response> response{new Response{shared_from_this()}};
87    success_callback.Run(1, std::move(response));
88  }
89}
90
91int Connection::GetResponseStatusCode() const {
92  return response_.GetStatusCode();
93}
94
95std::string Connection::GetResponseStatusText() const {
96  return response_.GetStatusText();
97}
98
99std::string Connection::GetProtocolVersion() const {
100  return response_.GetProtocolVersion();
101}
102
103std::string Connection::GetResponseHeader(
104    const std::string& header_name) const {
105  return response_.GetHeader(header_name);
106}
107
108StreamPtr Connection::ExtractDataStream(brillo::ErrorPtr* error) {
109  // HEAD requests must not return body.
110  if (request_.GetMethod() != request_type::kHead) {
111    return MemoryStream::OpenRef(response_.GetData(), error);
112  } else {
113    // Return empty data stream for HEAD requests.
114    return MemoryStream::OpenCopyOf(nullptr, 0, error);
115  }
116}
117
118}  // namespace fake
119}  // namespace http
120}  // namespace brillo
121