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