Home | History | Annotate | Download | only in http
      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