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 = [connection, success_callback, error_callback] { 67 connection->FinishRequestAsyncHelper(success_callback, error_callback); 68 }; 69 transport_->RunCallbackAsync(FROM_HERE, base::Bind(callback)); 70 return 1; 71 } 72 73 void Connection::FinishRequestAsyncHelper( 74 const SuccessCallback& success_callback, 75 const ErrorCallback& error_callback) { 76 brillo::ErrorPtr error; 77 if (!FinishRequest(&error)) { 78 error_callback.Run(1, error.get()); 79 } else { 80 std::unique_ptr<Response> response{new Response{shared_from_this()}}; 81 success_callback.Run(1, std::move(response)); 82 } 83 } 84 85 int Connection::GetResponseStatusCode() const { 86 return response_.GetStatusCode(); 87 } 88 89 std::string Connection::GetResponseStatusText() const { 90 return response_.GetStatusText(); 91 } 92 93 std::string Connection::GetProtocolVersion() const { 94 return response_.GetProtocolVersion(); 95 } 96 97 std::string Connection::GetResponseHeader( 98 const std::string& header_name) const { 99 return response_.GetHeader(header_name); 100 } 101 102 StreamPtr Connection::ExtractDataStream(brillo::ErrorPtr* error) { 103 // HEAD requests must not return body. 104 if (request_.GetMethod() != request_type::kHead) { 105 return MemoryStream::OpenRef(response_.GetData(), error); 106 } else { 107 // Return empty data stream for HEAD requests. 108 return MemoryStream::OpenCopyOf(nullptr, 0, error); 109 } 110 } 111 112 } // namespace fake 113 } // namespace http 114 } // namespace brillo 115