1f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko// Copyright 2014 The Chromium OS Authors. All rights reserved.
2f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko// Use of this source code is governed by a BSD-style license that can be
3f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko// found in the LICENSE file.
4f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
59ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/http/http_request.h>
6f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
7f95a2b9e277726d8793a5849ec6e81c038c22be3Alex Vakulenko#include <base/bind.h>
8f95a2b9e277726d8793a5849ec6e81c038c22be3Alex Vakulenko#include <base/callback.h>
9f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko#include <base/logging.h>
109ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/http/http_form_data.h>
119ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/map_utils.h>
129ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/mime_utils.h>
139ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/streams/memory_stream.h>
149ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/strings/string_utils.h>
15f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
169ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenkonamespace brillo {
17f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkonamespace http {
18f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
19f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko// request_type
20f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_type::kOptions[]               = "OPTIONS";
21f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_type::kGet[]                   = "GET";
22f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_type::kHead[]                  = "HEAD";
23f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_type::kPost[]                  = "POST";
24f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_type::kPut[]                   = "PUT";
25f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_type::kPatch[]                 = "PATCH";
26f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_type::kDelete[]                = "DELETE";
27f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_type::kTrace[]                 = "TRACE";
28f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_type::kConnect[]               = "CONNECT";
29f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_type::kCopy[]                  = "COPY";
30f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_type::kMove[]                  = "MOVE";
31f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
32f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko// request_header
33f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kAccept[]              = "Accept";
34f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kAcceptCharset[]       = "Accept-Charset";
35f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kAcceptEncoding[]      = "Accept-Encoding";
36f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kAcceptLanguage[]      = "Accept-Language";
37f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kAllow[]               = "Allow";
38f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kAuthorization[]       = "Authorization";
39f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kCacheControl[]        = "Cache-Control";
40f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kConnection[]          = "Connection";
41f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kContentEncoding[]     = "Content-Encoding";
42f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kContentLanguage[]     = "Content-Language";
43f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kContentLength[]       = "Content-Length";
44f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kContentLocation[]     = "Content-Location";
45f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kContentMd5[]          = "Content-MD5";
46f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kContentRange[]        = "Content-Range";
47f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kContentType[]         = "Content-Type";
48f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kCookie[]              = "Cookie";
49f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kDate[]                = "Date";
50f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kExpect[]              = "Expect";
51f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kExpires[]             = "Expires";
52f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kFrom[]                = "From";
53f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kHost[]                = "Host";
54f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kIfMatch[]             = "If-Match";
55f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kIfModifiedSince[]     = "If-Modified-Since";
56f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kIfNoneMatch[]         = "If-None-Match";
57f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kIfRange[]             = "If-Range";
58f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kIfUnmodifiedSince[]   = "If-Unmodified-Since";
59f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kLastModified[]        = "Last-Modified";
60f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kMaxForwards[]         = "Max-Forwards";
61f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kPragma[]              = "Pragma";
62f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kProxyAuthorization[]  = "Proxy-Authorization";
63f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kRange[]               = "Range";
64f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kReferer[]             = "Referer";
65f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kTE[]                  = "TE";
66f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kTrailer[]             = "Trailer";
67f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kTransferEncoding[]    = "Transfer-Encoding";
68f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kUpgrade[]             = "Upgrade";
69f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kUserAgent[]           = "User-Agent";
70f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kVia[]                 = "Via";
71f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char request_header::kWarning[]             = "Warning";
72f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
73f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko// response_header
74f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kAcceptRanges[]       = "Accept-Ranges";
75f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kAge[]                = "Age";
76f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kAllow[]              = "Allow";
77f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kCacheControl[]       = "Cache-Control";
78f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kConnection[]         = "Connection";
79f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kContentEncoding[]    = "Content-Encoding";
80f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kContentLanguage[]    = "Content-Language";
81f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kContentLength[]      = "Content-Length";
82f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kContentLocation[]    = "Content-Location";
83f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kContentMd5[]         = "Content-MD5";
84f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kContentRange[]       = "Content-Range";
85f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kContentType[]        = "Content-Type";
86f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kDate[]               = "Date";
87f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kETag[]               = "ETag";
88f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kExpires[]            = "Expires";
89f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kLastModified[]       = "Last-Modified";
90f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kLocation[]           = "Location";
91f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kPragma[]             = "Pragma";
92f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kProxyAuthenticate[]  = "Proxy-Authenticate";
93f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kRetryAfter[]         = "Retry-After";
94f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kServer[]             = "Server";
95f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kSetCookie[]          = "Set-Cookie";
96f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kTrailer[]            = "Trailer";
97f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kTransferEncoding[]   = "Transfer-Encoding";
98f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kUpgrade[]            = "Upgrade";
99f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kVary[]               = "Vary";
100f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kVia[]                = "Via";
101f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kWarning[]            = "Warning";
102f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoconst char response_header::kWwwAuthenticate[]    = "WWW-Authenticate";
103f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
104f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko// ***********************************************************
105f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko// ********************** Request Class **********************
106f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko// ***********************************************************
10705d29044d14a60775ed6c51c75a414eb0cb50347Alex VakulenkoRequest::Request(const std::string& url,
10805d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko                 const std::string& method,
10905d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko                 std::shared_ptr<Transport> transport)
11005d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko    : transport_(transport), request_url_(url), method_(method) {
111f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  VLOG(1) << "http::Request created";
112f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  if (!transport_)
1137c686ea5ca47c2b1c14df27f656ad44a59bb2646Alex Vakulenko    transport_ = http::Transport::CreateDefault();
114f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
115f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
116f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex VakulenkoRequest::~Request() {
117f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  VLOG(1) << "http::Request destroyed";
118f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
119f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
120f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkovoid Request::AddRange(int64_t bytes) {
1218757d061cd87578b5b158e8efcc8a6cf4715c7a1Alex Vakulenko  DCHECK(transport_) << "Request already sent";
122f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  if (bytes < 0) {
123f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko    ranges_.emplace_back(Request::range_value_omitted, -bytes);
124f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  } else {
125f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko    ranges_.emplace_back(bytes, Request::range_value_omitted);
126f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  }
127f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
128f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
129f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkovoid Request::AddRange(uint64_t from_byte, uint64_t to_byte) {
1308757d061cd87578b5b158e8efcc8a6cf4715c7a1Alex Vakulenko  DCHECK(transport_) << "Request already sent";
131f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  ranges_.emplace_back(from_byte, to_byte);
132f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
133f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
1342e1579107504b584d59e4ab036544369321f2a58Alex Vakulenkostd::unique_ptr<Response> Request::GetResponseAndBlock(
1359ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko    brillo::ErrorPtr* error) {
136f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  if (!SendRequestIfNeeded(error) || !connection_->FinishRequest(error))
137f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko    return std::unique_ptr<Response>();
138f95a2b9e277726d8793a5849ec6e81c038c22be3Alex Vakulenko  std::unique_ptr<Response> response(new Response(connection_));
139f95a2b9e277726d8793a5849ec6e81c038c22be3Alex Vakulenko  connection_.reset();
140f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  transport_.reset();  // Indicate that the response has been received
141f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  return response;
142f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
143f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
1448757d061cd87578b5b158e8efcc8a6cf4715c7a1Alex VakulenkoRequestID Request::GetResponse(const SuccessCallback& success_callback,
1458757d061cd87578b5b158e8efcc8a6cf4715c7a1Alex Vakulenko                               const ErrorCallback& error_callback) {
146f95a2b9e277726d8793a5849ec6e81c038c22be3Alex Vakulenko  ErrorPtr error;
147f95a2b9e277726d8793a5849ec6e81c038c22be3Alex Vakulenko  if (!SendRequestIfNeeded(&error)) {
148f95a2b9e277726d8793a5849ec6e81c038c22be3Alex Vakulenko    transport_->RunCallbackAsync(
149ac3059d5edad2af5a75184d1e31133e712c91f60Alex Vakulenko        FROM_HERE, base::Bind(error_callback, 0, base::Owned(error.release())));
150ac3059d5edad2af5a75184d1e31133e712c91f60Alex Vakulenko    return 0;
151f95a2b9e277726d8793a5849ec6e81c038c22be3Alex Vakulenko  }
1528757d061cd87578b5b158e8efcc8a6cf4715c7a1Alex Vakulenko  RequestID id =
1538757d061cd87578b5b158e8efcc8a6cf4715c7a1Alex Vakulenko      connection_->FinishRequestAsync(success_callback, error_callback);
154f95a2b9e277726d8793a5849ec6e81c038c22be3Alex Vakulenko  connection_.reset();
155f95a2b9e277726d8793a5849ec6e81c038c22be3Alex Vakulenko  transport_.reset();  // Indicate that the request has been dispatched.
156ac3059d5edad2af5a75184d1e31133e712c91f60Alex Vakulenko  return id;
157f95a2b9e277726d8793a5849ec6e81c038c22be3Alex Vakulenko}
158f95a2b9e277726d8793a5849ec6e81c038c22be3Alex Vakulenko
1592e1579107504b584d59e4ab036544369321f2a58Alex Vakulenkovoid Request::SetAccept(const std::string& accept_mime_types) {
1608757d061cd87578b5b158e8efcc8a6cf4715c7a1Alex Vakulenko  DCHECK(transport_) << "Request already sent";
161f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  accept_ = accept_mime_types;
162f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
163f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
164f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenkoconst std::string& Request::GetAccept() const {
165f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  return accept_;
166f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
167f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
1682e1579107504b584d59e4ab036544369321f2a58Alex Vakulenkovoid Request::SetContentType(const std::string& contentType) {
1698757d061cd87578b5b158e8efcc8a6cf4715c7a1Alex Vakulenko  DCHECK(transport_) << "Request already sent";
170f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  content_type_ = contentType;
171f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
172f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
173f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenkoconst std::string& Request::GetContentType() const {
174f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  return content_type_;
175f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
176f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
1772e1579107504b584d59e4ab036544369321f2a58Alex Vakulenkovoid Request::AddHeader(const std::string& header, const std::string& value) {
1788757d061cd87578b5b158e8efcc8a6cf4715c7a1Alex Vakulenko  DCHECK(transport_) << "Request already sent";
179f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  headers_.emplace(header, value);
180f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
181f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
182f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkovoid Request::AddHeaders(const HeaderList& headers) {
1838757d061cd87578b5b158e8efcc8a6cf4715c7a1Alex Vakulenko  DCHECK(transport_) << "Request already sent";
184f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  headers_.insert(headers.begin(), headers.end());
185f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
186f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
187f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkobool Request::AddRequestBody(const void* data,
188f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko                             size_t size,
1899ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko                             brillo::ErrorPtr* error) {
190f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  if (!SendRequestIfNeeded(error))
191f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko    return false;
19280663bf89f5ba2c0646f196371a1fa92123855c6Alex Vakulenko  StreamPtr stream = MemoryStream::OpenCopyOf(data, size, error);
19380663bf89f5ba2c0646f196371a1fa92123855c6Alex Vakulenko  return stream && connection_->SetRequestData(std::move(stream), error);
19447e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko}
19547e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko
1969ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenkobool Request::AddRequestBody(StreamPtr stream, brillo::ErrorPtr* error) {
19747e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko  return SendRequestIfNeeded(error) &&
19880663bf89f5ba2c0646f196371a1fa92123855c6Alex Vakulenko         connection_->SetRequestData(std::move(stream), error);
19947e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko}
20047e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko
20147e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenkobool Request::AddRequestBodyAsFormData(std::unique_ptr<FormData> form_data,
2029ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko                                       brillo::ErrorPtr* error) {
20347e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko  AddHeader(request_header::kContentType, form_data->GetContentType());
20447e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko  if (!SendRequestIfNeeded(error))
20547e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko    return false;
20680663bf89f5ba2c0646f196371a1fa92123855c6Alex Vakulenko  return connection_->SetRequestData(form_data->ExtractDataStream(), error);
207f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
208f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
2099ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenkobool Request::AddResponseStream(StreamPtr stream, brillo::ErrorPtr* error) {
2102eed2f9a423b8e776b4d54530c567736c371ba48Nathan Bullock  if (!SendRequestIfNeeded(error))
2112eed2f9a423b8e776b4d54530c567736c371ba48Nathan Bullock    return false;
2122eed2f9a423b8e776b4d54530c567736c371ba48Nathan Bullock  connection_->SetResponseData(std::move(stream));
2132eed2f9a423b8e776b4d54530c567736c371ba48Nathan Bullock  return true;
2142eed2f9a423b8e776b4d54530c567736c371ba48Nathan Bullock}
2152eed2f9a423b8e776b4d54530c567736c371ba48Nathan Bullock
216f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenkoconst std::string& Request::GetRequestURL() const {
217f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  return request_url_;
218f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko}
219f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko
220f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenkoconst std::string& Request::GetRequestMethod() const {
221f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  return method_;
222f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko}
223f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko
2242e1579107504b584d59e4ab036544369321f2a58Alex Vakulenkovoid Request::SetReferer(const std::string& referer) {
2258757d061cd87578b5b158e8efcc8a6cf4715c7a1Alex Vakulenko  DCHECK(transport_) << "Request already sent";
226f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  referer_ = referer;
227f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
228f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
229f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenkoconst std::string& Request::GetReferer() const {
230f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  return referer_;
231f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
232f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
2332e1579107504b584d59e4ab036544369321f2a58Alex Vakulenkovoid Request::SetUserAgent(const std::string& user_agent) {
2348757d061cd87578b5b158e8efcc8a6cf4715c7a1Alex Vakulenko  DCHECK(transport_) << "Request already sent";
235f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  user_agent_ = user_agent;
236f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
237f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
238f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenkoconst std::string& Request::GetUserAgent() const {
239f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  return user_agent_;
240f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
241f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
2429ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenkobool Request::SendRequestIfNeeded(brillo::ErrorPtr* error) {
243f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  if (transport_) {
244f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko    if (!connection_) {
2459ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko      http::HeaderList headers = brillo::MapToVector(headers_);
246f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko      std::vector<std::string> ranges;
247f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko      if (method_ != request_type::kHead) {
248f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko        ranges.reserve(ranges_.size());
249f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko        for (auto p : ranges_) {
250f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko          if (p.first != range_value_omitted ||
251f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko              p.second != range_value_omitted) {
252f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko            std::string range;
253f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko            if (p.first != range_value_omitted) {
2549ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko              range = brillo::string_utils::ToString(p.first);
255f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko            }
256f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko            range += '-';
257f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko            if (p.second != range_value_omitted) {
2589ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko              range += brillo::string_utils::ToString(p.second);
259f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko            }
260f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko            ranges.push_back(range);
261f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko          }
262f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko        }
263f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko      }
264f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko      if (!ranges.empty())
26505d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko        headers.emplace_back(
26605d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko            request_header::kRange,
2679ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko            "bytes=" + brillo::string_utils::Join(",", ranges));
268f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
269f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko      headers.emplace_back(request_header::kAccept, GetAccept());
270f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko      if (method_ != request_type::kGet && method_ != request_type::kHead) {
271f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko        if (!content_type_.empty())
272f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko          headers.emplace_back(request_header::kContentType, content_type_);
273f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko      }
27405d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko      connection_ = transport_->CreateConnection(
27505d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko          request_url_, method_, headers, user_agent_, referer_, error);
276f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko    }
277f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
278f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko    if (connection_)
279f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko      return true;
280f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  } else {
2819ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko    brillo::Error::AddTo(error,
28205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko                           FROM_HERE,
28305d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko                           http::kErrorDomain,
2842e1579107504b584d59e4ab036544369321f2a58Alex Vakulenko                           "response_already_received",
285f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko                           "HTTP response already received");
286f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  }
287f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  return false;
288f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
289f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
290f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko// ************************************************************
291f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko// ********************** Response Class **********************
292f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko// ************************************************************
293f95a2b9e277726d8793a5849ec6e81c038c22be3Alex VakulenkoResponse::Response(const std::shared_ptr<Connection>& connection)
294f95a2b9e277726d8793a5849ec6e81c038c22be3Alex Vakulenko    : connection_{connection} {
295f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  VLOG(1) << "http::Response created";
296f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
297f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
298f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex VakulenkoResponse::~Response() {
299f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  VLOG(1) << "http::Response destroyed";
300f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
301f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
302f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkobool Response::IsSuccessful() const {
303f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  int code = GetStatusCode();
304f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  return code >= status_code::Continue && code < status_code::BadRequest;
305f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
306f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
307f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkoint Response::GetStatusCode() const {
308f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  if (!connection_)
309f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko    return -1;
310f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
311f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  return connection_->GetResponseStatusCode();
312f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
313f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
314f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkostd::string Response::GetStatusText() const {
315f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  if (!connection_)
316f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko    return std::string();
317f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
318f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  return connection_->GetResponseStatusText();
319f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
320f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
321f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkostd::string Response::GetContentType() const {
322f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  return GetHeader(response_header::kContentType);
323f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
324f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
32520d497f58d7abdec1e011cb1efadb45e53e5af0bAlex VakulenkoStreamPtr Response::ExtractDataStream(ErrorPtr* error) {
32620d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko  return connection_->ExtractDataStream(error);
327f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
328f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
32920d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenkostd::vector<uint8_t> Response::ExtractData() {
33020d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko  std::vector<uint8_t> data;
33120d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko  StreamPtr src_stream = connection_->ExtractDataStream(nullptr);
33220d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko  StreamPtr dest_stream = MemoryStream::CreateRef(&data, nullptr);
33320d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko  if (src_stream && dest_stream) {
33420d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko    char buffer[1024];
33520d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko    size_t read = 0;
33620d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko    while (src_stream->ReadBlocking(buffer, sizeof(buffer), &read, nullptr) &&
33720d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko           read > 0) {
33820d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko      CHECK(dest_stream->WriteAllBlocking(buffer, read, nullptr));
33920d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko    }
34020d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko  }
34120d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko  return data;
34220d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko}
343f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
34420d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenkostd::string Response::ExtractDataAsString() {
34520d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko  std::vector<uint8_t> data = ExtractData();
34620d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko  return std::string{data.begin(), data.end()};
347f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
348f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
3492e1579107504b584d59e4ab036544369321f2a58Alex Vakulenkostd::string Response::GetHeader(const std::string& header_name) const {
350f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  if (connection_)
351f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko    return connection_->GetResponseHeader(header_name);
352f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
353f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko  return std::string();
354f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}
355f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko
356f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko}  // namespace http
3579ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko}  // namespace brillo
358