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 #ifndef LIBBRILLO_BRILLO_HTTP_HTTP_REQUEST_H_ 6 #define LIBBRILLO_BRILLO_HTTP_HTTP_REQUEST_H_ 7 8 #include <limits> 9 #include <map> 10 #include <memory> 11 #include <string> 12 #include <utility> 13 #include <vector> 14 15 #include <base/macros.h> 16 #include <brillo/brillo_export.h> 17 #include <brillo/errors/error.h> 18 #include <brillo/http/http_connection.h> 19 #include <brillo/http/http_transport.h> 20 21 namespace brillo { 22 namespace http { 23 24 // HTTP request verbs 25 namespace request_type { 26 BRILLO_EXPORT extern const char kOptions[]; 27 BRILLO_EXPORT extern const char kGet[]; 28 BRILLO_EXPORT extern const char kHead[]; 29 BRILLO_EXPORT extern const char kPost[]; 30 BRILLO_EXPORT extern const char kPut[]; 31 BRILLO_EXPORT extern const char kPatch[]; // Non-standard HTTP/1.1 verb 32 BRILLO_EXPORT extern const char kDelete[]; 33 BRILLO_EXPORT extern const char kTrace[]; 34 BRILLO_EXPORT extern const char kConnect[]; 35 BRILLO_EXPORT extern const char kCopy[]; // Non-standard HTTP/1.1 verb 36 BRILLO_EXPORT extern const char kMove[]; // Non-standard HTTP/1.1 verb 37 } // namespace request_type 38 39 // HTTP request header names 40 namespace request_header { 41 BRILLO_EXPORT extern const char kAccept[]; 42 BRILLO_EXPORT extern const char kAcceptCharset[]; 43 BRILLO_EXPORT extern const char kAcceptEncoding[]; 44 BRILLO_EXPORT extern const char kAcceptLanguage[]; 45 BRILLO_EXPORT extern const char kAllow[]; 46 BRILLO_EXPORT extern const char kAuthorization[]; 47 BRILLO_EXPORT extern const char kCacheControl[]; 48 BRILLO_EXPORT extern const char kConnection[]; 49 BRILLO_EXPORT extern const char kContentEncoding[]; 50 BRILLO_EXPORT extern const char kContentLanguage[]; 51 BRILLO_EXPORT extern const char kContentLength[]; 52 BRILLO_EXPORT extern const char kContentLocation[]; 53 BRILLO_EXPORT extern const char kContentMd5[]; 54 BRILLO_EXPORT extern const char kContentRange[]; 55 BRILLO_EXPORT extern const char kContentType[]; 56 BRILLO_EXPORT extern const char kCookie[]; 57 BRILLO_EXPORT extern const char kDate[]; 58 BRILLO_EXPORT extern const char kExpect[]; 59 BRILLO_EXPORT extern const char kExpires[]; 60 BRILLO_EXPORT extern const char kFrom[]; 61 BRILLO_EXPORT extern const char kHost[]; 62 BRILLO_EXPORT extern const char kIfMatch[]; 63 BRILLO_EXPORT extern const char kIfModifiedSince[]; 64 BRILLO_EXPORT extern const char kIfNoneMatch[]; 65 BRILLO_EXPORT extern const char kIfRange[]; 66 BRILLO_EXPORT extern const char kIfUnmodifiedSince[]; 67 BRILLO_EXPORT extern const char kLastModified[]; 68 BRILLO_EXPORT extern const char kMaxForwards[]; 69 BRILLO_EXPORT extern const char kPragma[]; 70 BRILLO_EXPORT extern const char kProxyAuthorization[]; 71 BRILLO_EXPORT extern const char kRange[]; 72 BRILLO_EXPORT extern const char kReferer[]; 73 BRILLO_EXPORT extern const char kTE[]; 74 BRILLO_EXPORT extern const char kTrailer[]; 75 BRILLO_EXPORT extern const char kTransferEncoding[]; 76 BRILLO_EXPORT extern const char kUpgrade[]; 77 BRILLO_EXPORT extern const char kUserAgent[]; 78 BRILLO_EXPORT extern const char kVia[]; 79 BRILLO_EXPORT extern const char kWarning[]; 80 } // namespace request_header 81 82 // HTTP response header names 83 namespace response_header { 84 BRILLO_EXPORT extern const char kAcceptRanges[]; 85 BRILLO_EXPORT extern const char kAge[]; 86 BRILLO_EXPORT extern const char kAllow[]; 87 BRILLO_EXPORT extern const char kCacheControl[]; 88 BRILLO_EXPORT extern const char kConnection[]; 89 BRILLO_EXPORT extern const char kContentEncoding[]; 90 BRILLO_EXPORT extern const char kContentLanguage[]; 91 BRILLO_EXPORT extern const char kContentLength[]; 92 BRILLO_EXPORT extern const char kContentLocation[]; 93 BRILLO_EXPORT extern const char kContentMd5[]; 94 BRILLO_EXPORT extern const char kContentRange[]; 95 BRILLO_EXPORT extern const char kContentType[]; 96 BRILLO_EXPORT extern const char kDate[]; 97 BRILLO_EXPORT extern const char kETag[]; 98 BRILLO_EXPORT extern const char kExpires[]; 99 BRILLO_EXPORT extern const char kLastModified[]; 100 BRILLO_EXPORT extern const char kLocation[]; 101 BRILLO_EXPORT extern const char kPragma[]; 102 BRILLO_EXPORT extern const char kProxyAuthenticate[]; 103 BRILLO_EXPORT extern const char kRetryAfter[]; 104 BRILLO_EXPORT extern const char kServer[]; 105 BRILLO_EXPORT extern const char kSetCookie[]; 106 BRILLO_EXPORT extern const char kTrailer[]; 107 BRILLO_EXPORT extern const char kTransferEncoding[]; 108 BRILLO_EXPORT extern const char kUpgrade[]; 109 BRILLO_EXPORT extern const char kVary[]; 110 BRILLO_EXPORT extern const char kVia[]; 111 BRILLO_EXPORT extern const char kWarning[]; 112 BRILLO_EXPORT extern const char kWwwAuthenticate[]; 113 } // namespace response_header 114 115 // HTTP request status (error) codes 116 namespace status_code { 117 // OK to continue with request 118 static const int Continue = 100; 119 // Server has switched protocols in upgrade header 120 static const int SwitchProtocols = 101; 121 122 // Request completed 123 static const int Ok = 200; 124 // Object created, reason = new URI 125 static const int Created = 201; 126 // Async completion (TBS) 127 static const int Accepted = 202; 128 // Partial completion 129 static const int Partial = 203; 130 // No info to return 131 static const int NoContent = 204; 132 // Request completed, but clear form 133 static const int ResetContent = 205; 134 // Partial GET fulfilled 135 static const int PartialContent = 206; 136 137 // Server couldn't decide what to return 138 static const int Ambiguous = 300; 139 // Object permanently moved 140 static const int Moved = 301; 141 // Object temporarily moved 142 static const int Redirect = 302; 143 // Redirection w/ new access method 144 static const int RedirectMethod = 303; 145 // If-Modified-Since was not modified 146 static const int NotModified = 304; 147 // Redirection to proxy, location header specifies proxy to use 148 static const int UseProxy = 305; 149 // HTTP/1.1: keep same verb 150 static const int RedirectKeepVerb = 307; 151 152 // Invalid syntax 153 static const int BadRequest = 400; 154 // Access denied 155 static const int Denied = 401; 156 // Payment required 157 static const int PaymentRequired = 402; 158 // Request forbidden 159 static const int Forbidden = 403; 160 // Object not found 161 static const int NotFound = 404; 162 // Method is not allowed 163 static const int BadMethod = 405; 164 // No response acceptable to client found 165 static const int NoneAcceptable = 406; 166 // Proxy authentication required 167 static const int ProxyAuthRequired = 407; 168 // Server timed out waiting for request 169 static const int RequestTimeout = 408; 170 // User should resubmit with more info 171 static const int Conflict = 409; 172 // The resource is no longer available 173 static const int Gone = 410; 174 // The server refused to accept request w/o a length 175 static const int LengthRequired = 411; 176 // Precondition given in request failed 177 static const int PrecondionFailed = 412; 178 // Request entity was too large 179 static const int RequestTooLarge = 413; 180 // Request URI too long 181 static const int UriTooLong = 414; 182 // Unsupported media type 183 static const int UnsupportedMedia = 415; 184 // Retry after doing the appropriate action. 185 static const int RetryWith = 449; 186 187 // Internal server error 188 static const int InternalServerError = 500; 189 // Request not supported 190 static const int NotSupported = 501; 191 // Error response received from gateway 192 static const int BadGateway = 502; 193 // Temporarily overloaded 194 static const int ServiceUnavailable = 503; 195 // Timed out waiting for gateway 196 static const int GatewayTimeout = 504; 197 // HTTP version not supported 198 static const int VersionNotSupported = 505; 199 } // namespace status_code 200 201 class Response; // Just a forward declaration. 202 class FormData; 203 204 /////////////////////////////////////////////////////////////////////////////// 205 // Request class is the main object used to set up and initiate an HTTP 206 // communication session. It is used to specify the HTTP request method, 207 // request URL and many optional parameters (such as HTTP headers, user agent, 208 // referer URL and so on. 209 // 210 // Once everything is setup, GetResponse() method is used to send the request 211 // and obtain the server response. The returned Response object can be 212 // used to inspect the response code, HTTP headers and/or response body. 213 /////////////////////////////////////////////////////////////////////////////// 214 class BRILLO_EXPORT Request final { 215 public: 216 // The main constructor. |url| specifies the remote host address/path 217 // to send the request to. |method| is the HTTP request verb and 218 // |transport| is the HTTP transport implementation for server communications. 219 Request(const std::string& url, 220 const std::string& method, 221 std::shared_ptr<Transport> transport); 222 ~Request(); 223 224 // Gets/Sets "Accept:" header value. The default value is "*/*" if not set. 225 void SetAccept(const std::string& accept_mime_types); 226 const std::string& GetAccept() const; 227 228 // Gets/Sets "Content-Type:" header value 229 void SetContentType(const std::string& content_type); 230 const std::string& GetContentType() const; 231 232 // Adds additional HTTP request header 233 void AddHeader(const std::string& header, const std::string& value); 234 void AddHeaders(const HeaderList& headers); 235 236 // Removes HTTP request header 237 void RemoveHeader(const std::string& header); 238 239 // Adds a request body. This is not to be used with GET method 240 bool AddRequestBody(const void* data, size_t size, brillo::ErrorPtr* error); 241 bool AddRequestBody(StreamPtr stream, brillo::ErrorPtr* error); 242 243 // Adds a request body. This is not to be used with GET method. 244 // This method also sets the correct content-type of the request, including 245 // the multipart data boundary. 246 bool AddRequestBodyAsFormData(std::unique_ptr<FormData> form_data, 247 brillo::ErrorPtr* error); 248 249 // Adds a stream for the response. Otherwise a MemoryStream will be used. 250 bool AddResponseStream(StreamPtr stream, brillo::ErrorPtr* error); 251 252 // Makes a request for a subrange of data. Specifies a partial range with 253 // either from beginning of the data to the specified offset (if |bytes| is 254 // negative) or from the specified offset to the end of data (if |bytes| is 255 // positive). 256 // All individual ranges will be sent as part of "Range:" HTTP request header. 257 void AddRange(int64_t bytes); 258 259 // Makes a request for a subrange of data. Specifies a full range with 260 // start and end bytes from the beginning of the requested data. 261 // All individual ranges will be sent as part of "Range:" HTTP request header. 262 void AddRange(uint64_t from_byte, uint64_t to_byte); 263 264 // Returns the request URL 265 const std::string& GetRequestURL() const; 266 267 // Returns the request verb. 268 const std::string& GetRequestMethod() const; 269 270 // Gets/Sets a request referer URL (sent as "Referer:" request header). 271 void SetReferer(const std::string& referer); 272 const std::string& GetReferer() const; 273 274 // Gets/Sets a user agent string (sent as "User-Agent:" request header). 275 void SetUserAgent(const std::string& user_agent); 276 const std::string& GetUserAgent() const; 277 278 // Sends the request to the server and blocks until the response is received, 279 // which is returned as the response object. 280 // In case the server couldn't be reached for whatever reason, returns 281 // empty unique_ptr (null). In such a case, the additional error information 282 // can be returned through the optional supplied |error| parameter. 283 std::unique_ptr<Response> GetResponseAndBlock(brillo::ErrorPtr* error); 284 285 // Sends out the request and invokes the |success_callback| when the response 286 // is received. In case of an error, the |error_callback| is invoked. 287 // Returns the ID of the asynchronous request created. 288 RequestID GetResponse(const SuccessCallback& success_callback, 289 const ErrorCallback& error_callback); 290 291 private: 292 friend class HttpRequestTest; 293 294 // Helper function to create an http::Connection and send off request headers. 295 BRILLO_PRIVATE bool SendRequestIfNeeded(brillo::ErrorPtr* error); 296 297 // Implementation that provides particular HTTP transport. 298 std::shared_ptr<Transport> transport_; 299 300 // An established connection for adding request body. This connection 301 // is maintained by the request object after the headers have been 302 // sent and before the response is requested. 303 std::shared_ptr<Connection> connection_; 304 305 // Full request URL, such as "http://www.host.com/path/to/object" 306 const std::string request_url_; 307 // HTTP request verb, such as "GET", "POST", "PUT", ... 308 const std::string method_; 309 310 // Referrer URL, if any. Sent to the server via "Referer: " header. 311 std::string referer_; 312 // User agent string, if any. Sent to the server via "User-Agent: " header. 313 std::string user_agent_; 314 // Content type of the request body data. 315 // Sent to the server via "Content-Type: " header. 316 std::string content_type_; 317 // List of acceptable response data types. 318 // Sent to the server via "Accept: " header. 319 std::string accept_ = "*/*"; 320 321 // List of optional request headers provided by the caller. 322 std::multimap<std::string, std::string> headers_; 323 // List of optional data ranges to request partial content from the server. 324 // Sent to the server as "Range: " header. 325 std::vector<std::pair<uint64_t, uint64_t>> ranges_; 326 327 // range_value_omitted is used in |ranges_| list to indicate omitted value. 328 // E.g. range (10,range_value_omitted) represents bytes from 10 to the end 329 // of the data stream. 330 const uint64_t range_value_omitted = std::numeric_limits<uint64_t>::max(); 331 332 DISALLOW_COPY_AND_ASSIGN(Request); 333 }; 334 335 /////////////////////////////////////////////////////////////////////////////// 336 // Response class is returned from Request::GetResponse() and is a way 337 // to get to response status, error codes, response HTTP headers and response 338 // data (body) if available. 339 /////////////////////////////////////////////////////////////////////////////// 340 class BRILLO_EXPORT Response final { 341 public: 342 explicit Response(const std::shared_ptr<Connection>& connection); 343 ~Response(); 344 345 // Returns true if server returned a success code (status code below 400). 346 bool IsSuccessful() const; 347 348 // Returns the HTTP status code (e.g. 200 for success) 349 int GetStatusCode() const; 350 351 // Returns the status text (e.g. for error 403 it could be "NOT AUTHORIZED"). 352 std::string GetStatusText() const; 353 354 // Returns the content type of the response data. 355 std::string GetContentType() const; 356 357 // Returns response data stream by transferring ownership of the data stream 358 // from Response class to the caller. 359 StreamPtr ExtractDataStream(ErrorPtr* error); 360 361 // Extracts the data from the underlying response data stream as a byte array. 362 std::vector<uint8_t> ExtractData(); 363 364 // Extracts the data from the underlying response data stream as a string. 365 std::string ExtractDataAsString(); 366 367 // Returns a value of a given response HTTP header. 368 std::string GetHeader(const std::string& header_name) const; 369 370 private: 371 friend class HttpRequestTest; 372 373 std::shared_ptr<Connection> connection_; 374 375 DISALLOW_COPY_AND_ASSIGN(Response); 376 }; 377 378 } // namespace http 379 } // namespace brillo 380 381 #endif // LIBBRILLO_BRILLO_HTTP_HTTP_REQUEST_H_ 382