aboutsummaryrefslogtreecommitdiffstats
path: root/chromeos/http/http_request.h
blob: 5c0f086472f8020a7da6a8263451b98838ceaabc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
// Copyright 2014 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef LIBCHROMEOS_CHROMEOS_HTTP_HTTP_REQUEST_H_
#define LIBCHROMEOS_CHROMEOS_HTTP_HTTP_REQUEST_H_

#include <limits>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include <base/macros.h>
#include <chromeos/chromeos_export.h>
#include <chromeos/errors/error.h>
#include <chromeos/http/http_connection.h>
#include <chromeos/http/http_transport.h>

namespace chromeos {
namespace http {

// HTTP request verbs
namespace request_type {
CHROMEOS_EXPORT extern const char kOptions[];
CHROMEOS_EXPORT extern const char kGet[];
CHROMEOS_EXPORT extern const char kHead[];
CHROMEOS_EXPORT extern const char kPost[];
CHROMEOS_EXPORT extern const char kPut[];
CHROMEOS_EXPORT extern const char kPatch[];  // Non-standard HTTP/1.1 verb
CHROMEOS_EXPORT extern const char kDelete[];
CHROMEOS_EXPORT extern const char kTrace[];
CHROMEOS_EXPORT extern const char kConnect[];
CHROMEOS_EXPORT extern const char kCopy[];   // Non-standard HTTP/1.1 verb
CHROMEOS_EXPORT extern const char kMove[];   // Non-standard HTTP/1.1 verb
}  // namespace request_type

// HTTP request header names
namespace request_header {
CHROMEOS_EXPORT extern const char kAccept[];
CHROMEOS_EXPORT extern const char kAcceptCharset[];
CHROMEOS_EXPORT extern const char kAcceptEncoding[];
CHROMEOS_EXPORT extern const char kAcceptLanguage[];
CHROMEOS_EXPORT extern const char kAllow[];
CHROMEOS_EXPORT extern const char kAuthorization[];
CHROMEOS_EXPORT extern const char kCacheControl[];
CHROMEOS_EXPORT extern const char kConnection[];
CHROMEOS_EXPORT extern const char kContentEncoding[];
CHROMEOS_EXPORT extern const char kContentLanguage[];
CHROMEOS_EXPORT extern const char kContentLength[];
CHROMEOS_EXPORT extern const char kContentLocation[];
CHROMEOS_EXPORT extern const char kContentMd5[];
CHROMEOS_EXPORT extern const char kContentRange[];
CHROMEOS_EXPORT extern const char kContentType[];
CHROMEOS_EXPORT extern const char kCookie[];
CHROMEOS_EXPORT extern const char kDate[];
CHROMEOS_EXPORT extern const char kExpect[];
CHROMEOS_EXPORT extern const char kExpires[];
CHROMEOS_EXPORT extern const char kFrom[];
CHROMEOS_EXPORT extern const char kHost[];
CHROMEOS_EXPORT extern const char kIfMatch[];
CHROMEOS_EXPORT extern const char kIfModifiedSince[];
CHROMEOS_EXPORT extern const char kIfNoneMatch[];
CHROMEOS_EXPORT extern const char kIfRange[];
CHROMEOS_EXPORT extern const char kIfUnmodifiedSince[];
CHROMEOS_EXPORT extern const char kLastModified[];
CHROMEOS_EXPORT extern const char kMaxForwards[];
CHROMEOS_EXPORT extern const char kPragma[];
CHROMEOS_EXPORT extern const char kProxyAuthorization[];
CHROMEOS_EXPORT extern const char kRange[];
CHROMEOS_EXPORT extern const char kReferer[];
CHROMEOS_EXPORT extern const char kTE[];
CHROMEOS_EXPORT extern const char kTrailer[];
CHROMEOS_EXPORT extern const char kTransferEncoding[];
CHROMEOS_EXPORT extern const char kUpgrade[];
CHROMEOS_EXPORT extern const char kUserAgent[];
CHROMEOS_EXPORT extern const char kVia[];
CHROMEOS_EXPORT extern const char kWarning[];
}  // namespace request_header

// HTTP response header names
namespace response_header {
CHROMEOS_EXPORT extern const char kAcceptRanges[];
CHROMEOS_EXPORT extern const char kAge[];
CHROMEOS_EXPORT extern const char kAllow[];
CHROMEOS_EXPORT extern const char kCacheControl[];
CHROMEOS_EXPORT extern const char kConnection[];
CHROMEOS_EXPORT extern const char kContentEncoding[];
CHROMEOS_EXPORT extern const char kContentLanguage[];
CHROMEOS_EXPORT extern const char kContentLength[];
CHROMEOS_EXPORT extern const char kContentLocation[];
CHROMEOS_EXPORT extern const char kContentMd5[];
CHROMEOS_EXPORT extern const char kContentRange[];
CHROMEOS_EXPORT extern const char kContentType[];
CHROMEOS_EXPORT extern const char kDate[];
CHROMEOS_EXPORT extern const char kETag[];
CHROMEOS_EXPORT extern const char kExpires[];
CHROMEOS_EXPORT extern const char kLastModified[];
CHROMEOS_EXPORT extern const char kLocation[];
CHROMEOS_EXPORT extern const char kPragma[];
CHROMEOS_EXPORT extern const char kProxyAuthenticate[];
CHROMEOS_EXPORT extern const char kRetryAfter[];
CHROMEOS_EXPORT extern const char kServer[];
CHROMEOS_EXPORT extern const char kSetCookie[];
CHROMEOS_EXPORT extern const char kTrailer[];
CHROMEOS_EXPORT extern const char kTransferEncoding[];
CHROMEOS_EXPORT extern const char kUpgrade[];
CHROMEOS_EXPORT extern const char kVary[];
CHROMEOS_EXPORT extern const char kVia[];
CHROMEOS_EXPORT extern const char kWarning[];
CHROMEOS_EXPORT extern const char kWwwAuthenticate[];
}  // namespace response_header

// HTTP request status (error) codes
namespace status_code {
// OK to continue with request
static const int Continue = 100;
// Server has switched protocols in upgrade header
static const int SwitchProtocols = 101;

// Request completed
static const int Ok = 200;
// Object created, reason = new URI
static const int Created = 201;
// Async completion (TBS)
static const int Accepted = 202;
// Partial completion
static const int Partial = 203;
// No info to return
static const int NoContent = 204;
// Request completed, but clear form
static const int ResetContent = 205;
// Partial GET fulfilled
static const int PartialContent = 206;

// Server couldn't decide what to return
static const int Ambiguous = 300;
// Object permanently moved
static const int Moved = 301;
// Object temporarily moved
static const int Redirect = 302;
// Redirection w/ new access method
static const int RedirectMethod = 303;
// If-Modified-Since was not modified
static const int NotModified = 304;
// Redirection to proxy, location header specifies proxy to use
static const int UseProxy = 305;
// HTTP/1.1: keep same verb
static const int RedirectKeepVerb = 307;

// Invalid syntax
static const int BadRequest = 400;
// Access denied
static const int Denied = 401;
// Payment required
static const int PaymentRequired = 402;
// Request forbidden
static const int Forbidden = 403;
// Object not found
static const int NotFound = 404;
// Method is not allowed
static const int BadMethod = 405;
// No response acceptable to client found
static const int NoneAcceptable = 406;
// Proxy authentication required
static const int ProxyAuthRequired = 407;
// Server timed out waiting for request
static const int RequestTimeout = 408;
// User should resubmit with more info
static const int Conflict = 409;
// The resource is no longer available
static const int Gone = 410;
// The server refused to accept request w/o a length
static const int LengthRequired = 411;
// Precondition given in request failed
static const int PrecondionFailed = 412;
// Request entity was too large
static const int RequestTooLarge = 413;
// Request URI too long
static const int UriTooLong = 414;
// Unsupported media type
static const int UnsupportedMedia = 415;
// Retry after doing the appropriate action.
static const int RetryWith = 449;

// Internal server error
static const int InternalServerError = 500;
// Request not supported
static const int NotSupported = 501;
// Error response received from gateway
static const int BadGateway = 502;
// Temporarily overloaded
static const int ServiceUnavailable = 503;
// Timed out waiting for gateway
static const int GatewayTimeout = 504;
// HTTP version not supported
static const int VersionNotSupported = 505;
}  // namespace status_code

class Response;  // Just a forward declaration.
class FormData;

///////////////////////////////////////////////////////////////////////////////
// Request class is the main object used to set up and initiate an HTTP
// communication session. It is used to specify the HTTP request method,
// request URL and many optional parameters (such as HTTP headers, user agent,
// referer URL and so on.
//
// Once everything is setup, GetResponse() method is used to send the request
// and obtain the server response. The returned Response object can be
// used to inspect the response code, HTTP headers and/or response body.
///////////////////////////////////////////////////////////////////////////////
class CHROMEOS_EXPORT Request final {
 public:
  // The main constructor. |url| specifies the remote host address/path
  // to send the request to. |method| is the HTTP request verb and
  // |transport| is the HTTP transport implementation for server communications.
  Request(const std::string& url,
          const std::string& method,
          std::shared_ptr<Transport> transport);
  ~Request();

  // Gets/Sets "Accept:" header value. The default value is "*/*" if not set.
  void SetAccept(const std::string& accept_mime_types);
  const std::string& GetAccept() const;

  // Gets/Sets "Content-Type:" header value
  void SetContentType(const std::string& content_type);
  const std::string& GetContentType() const;

  // Adds additional HTTP request header
  void AddHeader(const std::string& header, const std::string& value);
  void AddHeaders(const HeaderList& headers);

  // Removes HTTP request header
  void RemoveHeader(const std::string& header);

  // Adds a request body. This is not to be used with GET method
  bool AddRequestBody(const void* data, size_t size, chromeos::ErrorPtr* error);
  bool AddRequestBody(StreamPtr stream, chromeos::ErrorPtr* error);

  // Adds a request body. This is not to be used with GET method.
  // This method also sets the correct content-type of the request, including
  // the multipart data boundary.
  bool AddRequestBodyAsFormData(std::unique_ptr<FormData> form_data,
                                chromeos::ErrorPtr* error);

  // Adds a stream for the response. Otherwise a MemoryStream will be used.
  bool AddResponseStream(StreamPtr stream, chromeos::ErrorPtr* error);

  // Makes a request for a subrange of data. Specifies a partial range with
  // either from beginning of the data to the specified offset (if |bytes| is
  // negative) or from the specified offset to the end of data (if |bytes| is
  // positive).
  // All individual ranges will be sent as part of "Range:" HTTP request header.
  void AddRange(int64_t bytes);

  // Makes a request for a subrange of data. Specifies a full range with
  // start and end bytes from the beginning of the requested data.
  // All individual ranges will be sent as part of "Range:" HTTP request header.
  void AddRange(uint64_t from_byte, uint64_t to_byte);

  // Returns the request URL
  const std::string& GetRequestURL() const;

  // Returns the request verb.
  const std::string& GetRequestMethod() const;

  // Gets/Sets a request referer URL (sent as "Referer:" request header).
  void SetReferer(const std::string& referer);
  const std::string& GetReferer() const;

  // Gets/Sets a user agent string (sent as "User-Agent:" request header).
  void SetUserAgent(const std::string& user_agent);
  const std::string& GetUserAgent() const;

  // Sends the request to the server and blocks until the response is received,
  // which is returned as the response object.
  // In case the server couldn't be reached for whatever reason, returns
  // empty unique_ptr (null). In such a case, the additional error information
  // can be returned through the optional supplied |error| parameter.
  std::unique_ptr<Response> GetResponseAndBlock(chromeos::ErrorPtr* error);

  // Sends out the request and invokes the |success_callback| when the response
  // is received. In case of an error, the |error_callback| is invoked.
  // Returns the ID of the asynchronous request created.
  RequestID GetResponse(const SuccessCallback& success_callback,
                        const ErrorCallback& error_callback);

 private:
  friend class HttpRequestTest;

  // Helper function to create an http::Connection and send off request headers.
  CHROMEOS_PRIVATE bool SendRequestIfNeeded(chromeos::ErrorPtr* error);

  // Implementation that provides particular HTTP transport.
  std::shared_ptr<Transport> transport_;

  // An established connection for adding request body. This connection
  // is maintained by the request object after the headers have been
  // sent and before the response is requested.
  std::shared_ptr<Connection> connection_;

  // Full request URL, such as "http://www.host.com/path/to/object"
  const std::string request_url_;
  // HTTP request verb, such as "GET", "POST", "PUT", ...
  const std::string method_;

  // Referrer URL, if any. Sent to the server via "Referer: " header.
  std::string referer_;
  // User agent string, if any. Sent to the server via "User-Agent: " header.
  std::string user_agent_;
  // Content type of the request body data.
  // Sent to the server via "Content-Type: " header.
  std::string content_type_;
  // List of acceptable response data types.
  // Sent to the server via "Accept: " header.
  std::string accept_ = "*/*";

  // List of optional request headers provided by the caller.
  std::multimap<std::string, std::string> headers_;
  // List of optional data ranges to request partial content from the server.
  // Sent to the server as "Range: " header.
  std::vector<std::pair<uint64_t, uint64_t>> ranges_;

  // range_value_omitted is used in |ranges_| list to indicate omitted value.
  // E.g. range (10,range_value_omitted) represents bytes from 10 to the end
  // of the data stream.
  const uint64_t range_value_omitted = std::numeric_limits<uint64_t>::max();

  DISALLOW_COPY_AND_ASSIGN(Request);
};

///////////////////////////////////////////////////////////////////////////////
// Response class is returned from Request::GetResponse() and is a way
// to get to response status, error codes, response HTTP headers and response
// data (body) if available.
///////////////////////////////////////////////////////////////////////////////
class CHROMEOS_EXPORT Response final {
 public:
  explicit Response(const std::shared_ptr<Connection>& connection);
  ~Response();

  // Returns true if server returned a success code (status code below 400).
  bool IsSuccessful() const;

  // Returns the HTTP status code (e.g. 200 for success)
  int GetStatusCode() const;

  // Returns the status text (e.g. for error 403 it could be "NOT AUTHORIZED").
  std::string GetStatusText() const;

  // Returns the content type of the response data.
  std::string GetContentType() const;

  // Returns response data stream by transferring ownership of the data stream
  // from Response class to the caller.
  StreamPtr ExtractDataStream(ErrorPtr* error);

  // Extracts the data from the underlying response data stream as a byte array.
  std::vector<uint8_t> ExtractData();

  // Extracts the data from the underlying response data stream as a string.
  std::string ExtractDataAsString();

  // Returns a value of a given response HTTP header.
  std::string GetHeader(const std::string& header_name) const;

 private:
  friend class HttpRequestTest;

  std::shared_ptr<Connection> connection_;

  DISALLOW_COPY_AND_ASSIGN(Response);
};

}  // namespace http
}  // namespace chromeos

#endif  // LIBCHROMEOS_CHROMEOS_HTTP_HTTP_REQUEST_H_