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 14 namespace brillo { 15 namespace http { 16 namespace fake { 17 18 Connection::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 25 Connection::~Connection() { 26 VLOG(1) << "fake::Connection destroyed"; 27 } 28 29 bool Connection::SendHeaders(const HeaderList& headers, 30 brillo::ErrorPtr* /* error */) { 31 request_.AddHeaders(headers); 32 return true; 33 } 34 35 bool Connection::SetRequestData(StreamPtr stream, 36 brillo::ErrorPtr* /* error */) { 37 request_.SetData(std::move(stream)); 38 return true; 39 } 40 41 bool 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 60 RequestID 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 79 void 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 91 int Connection::GetResponseStatusCode() const { 92 return response_.GetStatusCode(); 93 } 94 95 std::string Connection::GetResponseStatusText() const { 96 return response_.GetStatusText(); 97 } 98 99 std::string Connection::GetProtocolVersion() const { 100 return response_.GetProtocolVersion(); 101 } 102 103 std::string Connection::GetResponseHeader( 104 const std::string& header_name) const { 105 return response_.GetHeader(header_name); 106 } 107 108 StreamPtr 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