Apache Mesos
http.hpp
Go to the documentation of this file.
1 // Licensed under the Apache License, Version 2.0 (the "License");
2 // you may not use this file except in compliance with the License.
3 // You may obtain a copy of the License at
4 //
5 // http://www.apache.org/licenses/LICENSE-2.0
6 //
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License
12 
13 #ifndef __PROCESS_HTTP_HPP__
14 #define __PROCESS_HTTP_HPP__
15 
16 #include <ctype.h>
17 #include <stdint.h>
18 
19 #include <atomic>
20 #include <initializer_list>
21 #include <iosfwd>
22 #include <memory>
23 #include <queue>
24 #include <string>
25 #include <vector>
26 
27 #include <boost/functional/hash.hpp>
28 
29 #include <process/address.hpp>
30 #include <process/future.hpp>
31 #include <process/owned.hpp>
32 #include <process/pid.hpp>
33 #include <process/socket.hpp>
34 
35 #include <stout/error.hpp>
36 #include <stout/hashmap.hpp>
37 #include <stout/ip.hpp>
38 #include <stout/json.hpp>
39 #include <stout/jsonify.hpp>
40 #include <stout/none.hpp>
41 #include <stout/nothing.hpp>
42 #include <stout/option.hpp>
43 #include <stout/stringify.hpp>
44 #include <stout/strings.hpp>
45 #include <stout/try.hpp>
46 
47 namespace process {
48 
49 // Forward declaration to break cyclic dependency.
50 template <typename T>
51 class Future;
52 
53 namespace http {
54 
55 enum class Scheme {
56  HTTP,
57 #ifdef USE_SSL_SOCKET
58  HTTPS
59 #endif
60 };
61 
62 
63 namespace authentication {
64 
65 class Authenticator;
66 
67 struct Principal;
68 
77  const std::string& realm,
78  Owned<Authenticator> authenticator);
79 
80 
87 Future<Nothing> unsetAuthenticator(const std::string& realm);
88 
89 } // namespace authentication {
90 
91 // Forward declaration.
92 struct Request;
93 
94 namespace authorization {
95 
96 // The `AuthorizationCallbacks` type is used for a set of authorization
97 // callbacks used by libprocess to authorize HTTP endpoints. The key of the map
98 // contains the endpoint's path, while the value contains the callback.
99 typedef hashmap<std::string,
100  lambda::function<process::Future<bool>(
101  const Request,
104 
105 
106 // Set authorization callbacks for HTTP endpoints. These can be used to call out
107 // to an external, application-level authorizer. The callbacks should accept an
108 // HTTP request and an optional principal, and they should return a
109 // `Future<bool>` representing whether or not authorization was successful.
111 
112 
113 // Remove any authorization callbacks which were previously installed in
114 // libprocess.
115 void unsetCallbacks();
116 
117 } // namespace authorization {
118 
119 // Checks if the given status code is defined by RFC 2616.
120 bool isValidStatus(uint16_t code);
121 
122 // Represents a Uniform Resource Locator:
123 // scheme://domain|ip:port/path?query#fragment
124 //
125 // This is actually a URI-reference (see 4.1 of RFC 3986).
126 //
127 // TODO(bmahler): The default port should depend on the scheme!
128 struct URL
129 {
130  URL() = default;
131 
132  URL(const std::string& _scheme,
133  const std::string& _domain,
134  const uint16_t _port = 80,
135  const std::string& _path = "/",
136  const hashmap<std::string, std::string>& _query =
138  const Option<std::string>& _fragment = None())
139  : scheme(_scheme),
140  domain(_domain),
141  port(_port),
142  path(_path),
143  query(_query),
144  fragment(_fragment) {}
145 
146  URL(const std::string& _scheme,
147  const net::IP& _ip,
148  const uint16_t _port = 80,
149  const std::string& _path = "/",
150  const hashmap<std::string, std::string>& _query =
152  const Option<std::string>& _fragment = None())
153  : scheme(_scheme),
154  ip(_ip),
155  port(_port),
156  path(_path),
157  query(_query),
158  fragment(_fragment) {}
159 
160  static Try<URL> parse(const std::string& urlString);
161 
166  bool isAbsolute() const;
167 
169 
170  // TODO(benh): Consider using unrestricted union for 'domain' and 'ip'.
174  std::string path;
177 };
178 
179 
180 std::ostream& operator<<(std::ostream& stream, const URL& url);
181 
182 
184 {
185  size_t operator()(const std::string& key) const
186  {
187  size_t seed = 0;
188  foreach (char c, key) {
189  boost::hash_combine(seed, ::tolower(c));
190  }
191  return seed;
192  }
193 };
194 
195 
197 {
198  bool operator()(const std::string& left, const std::string& right) const
199  {
200  if (left.size() != right.size()) {
201  return false;
202  }
203  for (size_t i = 0; i < left.size(); ++i) {
204  if (::tolower(left[i]) != ::tolower(right[i])) {
205  return false;
206  }
207  }
208  return true;
209  }
210 };
211 
212 
213 struct Status
214 {
215  static const uint16_t CONTINUE;
216  static const uint16_t SWITCHING_PROTOCOLS;
217  static const uint16_t OK;
218  static const uint16_t CREATED;
219  static const uint16_t ACCEPTED;
220  static const uint16_t NON_AUTHORITATIVE_INFORMATION;
221  static const uint16_t NO_CONTENT;
222  static const uint16_t RESET_CONTENT;
223  static const uint16_t PARTIAL_CONTENT;
224  static const uint16_t MULTIPLE_CHOICES;
225  static const uint16_t MOVED_PERMANENTLY;
226  static const uint16_t FOUND;
227  static const uint16_t SEE_OTHER;
228  static const uint16_t NOT_MODIFIED;
229  static const uint16_t USE_PROXY;
230  static const uint16_t TEMPORARY_REDIRECT;
231  static const uint16_t BAD_REQUEST;
232  static const uint16_t UNAUTHORIZED;
233  static const uint16_t PAYMENT_REQUIRED;
234  static const uint16_t FORBIDDEN;
235  static const uint16_t NOT_FOUND;
236  static const uint16_t METHOD_NOT_ALLOWED;
237  static const uint16_t NOT_ACCEPTABLE;
238  static const uint16_t PROXY_AUTHENTICATION_REQUIRED;
239  static const uint16_t REQUEST_TIMEOUT;
240  static const uint16_t CONFLICT;
241  static const uint16_t GONE;
242  static const uint16_t LENGTH_REQUIRED;
243  static const uint16_t PRECONDITION_FAILED;
244  static const uint16_t REQUEST_ENTITY_TOO_LARGE;
245  static const uint16_t REQUEST_URI_TOO_LARGE;
246  static const uint16_t UNSUPPORTED_MEDIA_TYPE;
247  static const uint16_t REQUESTED_RANGE_NOT_SATISFIABLE;
248  static const uint16_t EXPECTATION_FAILED;
249  static const uint16_t INTERNAL_SERVER_ERROR;
250  static const uint16_t NOT_IMPLEMENTED;
251  static const uint16_t BAD_GATEWAY;
252  static const uint16_t SERVICE_UNAVAILABLE;
253  static const uint16_t GATEWAY_TIMEOUT;
254  static const uint16_t HTTP_VERSION_NOT_SUPPORTED;
255 
256  static std::string string(uint16_t code);
257 };
258 
259 
260 // Represents an asynchronous in-memory unbuffered Pipe, currently
261 // used for streaming HTTP responses via chunked encoding. Note that
262 // being an in-memory pipe means that this cannot be used across OS
263 // processes.
264 //
265 // Much like unix pipes, data is read until end-of-file is
266 // encountered; this occurs when the write-end of the pipe is
267 // closed and there is no outstanding data left to read.
268 //
269 // Unlike unix pipes, if the read-end of the pipe is closed before
270 // the write-end is closed, rather than receiving SIGPIPE or EPIPE
271 // during a write, the writer is notified via a future. This future
272 // is discarded if the write-end is closed first.
273 //
274 // No buffering means that each non-empty write to the pipe will
275 // correspond to to an equivalent read from the pipe, and the
276 // reader must "keep up" with the writer in order to avoid
277 // unbounded memory growth.
278 //
279 // The writer can induce a failure on the reader in order to signal
280 // that an error has occurred. For example, if we are receiving a
281 // response but a disconnection occurs before the response is
282 // completed, we want the reader to detect that a disconnection
283 // occurred!
284 //
285 // TODO(bmahler): Consider aggregating writes into larger reads to
286 // help the reader keep up (a process::Stream abstraction with
287 // backpressure would obviate the need for this).
288 //
289 // TODO(bmahler): Add a more general process::Stream<T> abstraction
290 // to represent asynchronous finite/infinite streams (possibly
291 // with "backpressure" on the writer). This is broadly useful
292 // (e.g. allocator can expose Stream<Allocation>, http::Pipe
293 // becomes Stream<string>, process::Queue<T> is just an infinite
294 // Stream<T> (i.e. completion and error semantics hidden)).
295 class Pipe
296 {
297 private:
298  struct Data; // Forward declaration.
299 
300 public:
301  class Reader
302  {
303  public:
304  // Returns data written to the pipe.
305  // Returns an empty read when end-of-file is reached.
306  // Returns Failure if the writer failed, or the read-end
307  // is closed.
309 
310  // Performs a series of asynchronous reads, until EOF is reached.
311  // Returns the concatenated result of the reads.
312  // Returns Failure if the writer failed, or the read-end
313  // is closed.
314  Future<std::string> readAll();
315 
316  // Closing the read-end of the pipe before the write-end closes
317  // or fails will notify the writer that the reader is no longer
318  // interested. Returns false if the read-end was already closed.
319  bool close();
320 
321  // Comparison operators useful for checking connection equality.
322  bool operator==(const Reader& other) const { return data == other.data; }
323  bool operator!=(const Reader& other) const { return !(*this == other); }
324 
325  private:
326  friend class Pipe;
327 
328  enum State
329  {
330  OPEN,
331  CLOSED,
332  };
333 
334  explicit Reader(const std::shared_ptr<Data>& _data) : data(_data) {}
335 
336  std::shared_ptr<Data> data;
337  };
338 
339  class Writer
340  {
341  public:
342  // Returns false if the data could not be written because
343  // either end of the pipe was already closed. Note that an
344  // empty write has no effect.
345  bool write(std::string s);
346 
347  // Closing the write-end of the pipe will send end-of-file
348  // to the reader. Returns false if the write-end of the pipe
349  // was already closed or failed.
350  bool close();
351 
352  // Closes the write-end of the pipe but sends a failure
353  // to the reader rather than end-of-file. Returns false
354  // if the write-end of the pipe was already closed or failed.
355  bool fail(const std::string& message);
356 
357  // Returns Nothing when the read-end of the pipe is closed
358  // before the write-end is closed, which means the reader
359  // was unable to continue reading!
360  Future<Nothing> readerClosed() const;
361 
362  // Comparison operators useful for checking connection equality.
363  bool operator==(const Writer& other) const { return data == other.data; }
364  bool operator!=(const Writer& other) const { return !(*this == other); }
365  private:
366  friend class Pipe;
367 
368  enum State
369  {
370  OPEN,
371  CLOSED,
372  FAILED,
373  };
374 
375  explicit Writer(const std::shared_ptr<Data>& _data) : data(_data) {}
376 
377  std::shared_ptr<Data> data;
378  };
379 
380  Pipe() : data(new Data()) {}
381 
382  Reader reader() const;
383  Writer writer() const;
384 
385  // Comparison operators useful for checking connection equality.
386  bool operator==(const Pipe& other) const { return data == other.data; }
387  bool operator!=(const Pipe& other) const { return !(*this == other); }
388 private:
389  struct Data
390  {
391  Data()
392  : readEnd(Reader::OPEN),
393  writeEnd(Writer::OPEN) {}
394 
395  // Rather than use a process to serialize access to the pipe's
396  // internal data we use a 'std::atomic_flag'.
397  std::atomic_flag lock = ATOMIC_FLAG_INIT;
398 
399  Reader::State readEnd;
400  Writer::State writeEnd;
401 
402  // Represents readers waiting for data from the pipe.
403  std::queue<Owned<Promise<std::string>>> reads;
404 
405  // Represents unread writes in the pipe. Note that we omit
406  // empty strings as they serve as a signal for end-of-file.
407  std::queue<std::string> writes;
408 
409  // Signals when the read-end is closed before the write-end.
410  Promise<Nothing> readerClosure;
411 
412  // Failure reason when the 'writeEnd' is FAILED.
413  Option<Failure> failure;
414  };
415 
416  std::shared_ptr<Data> data;
417 };
418 
419 
420 namespace header {
421 
422 // https://tools.ietf.org/html/rfc2617.
424 {
425 public:
426  static constexpr const char* NAME = "WWW-Authenticate";
427 
429  const std::string& authScheme,
430  const hashmap<std::string, std::string>& authParam)
431  : authScheme_(authScheme),
432  authParam_(authParam) {}
433 
434  static Try<WWWAuthenticate> create(const std::string& value);
435 
436  std::string authScheme();
438 
439 private:
440  // According to RFC, HTTP/1.1 server may return multiple challenges
441  // with a 401 (Authenticate) response. Each challenage is in the
442  // format of 'auth-scheme 1*SP 1#auth-param' and each challenage may
443  // use a different auth-scheme.
444  // https://tools.ietf.org/html/rfc2617#section-4.6
445  //
446  // TODO(gilbert): We assume there is only one authenticate challenge.
447  // Multiple challenges should be supported as well.
448  std::string authScheme_;
450 };
451 
452 } // namespace header {
453 
454 
455 class Headers : public hashmap<
456  std::string,
457  std::string,
458  CaseInsensitiveHash,
459  CaseInsensitiveEqual>
460 {
461 public:
462  Headers() {}
463 
464  Headers(const std::map<std::string, std::string>& map)
465  : hashmap<
466  std::string,
467  std::string,
469  CaseInsensitiveEqual>(map) {}
470 
471  Headers(std::map<std::string, std::string>&& map)
472  : hashmap<
473  std::string,
474  std::string,
477 
478  Headers(std::initializer_list<std::pair<std::string, std::string>> list)
479  : hashmap<
480  std::string,
481  std::string,
484 
485  template <typename T>
486  Result<T> get() const
487  {
488  Option<std::string> value = get(T::NAME);
489  if (value.isNone()) {
490  return None();
491  }
492  Try<T> header = T::create(value.get());
493  if (header.isError()) {
494  return Error(header.error());
495  }
496  return header.get();
497  }
498 
499  Option<std::string> get(const std::string& key) const
500  {
501  return hashmap<
502  std::string,
503  std::string,
506  }
507 
508  Headers operator+(const Headers& that) const
509  {
510  Headers result = *this;
511  result.insert(that.begin(), that.end());
512  return result;
513  }
514 };
515 
516 
517 struct Request
518 {
520  : keepAlive(false), type(BODY) {}
521 
522  std::string method;
523 
524  // TODO(benh): Add major/minor version.
525 
526  // For client requests, the URL should be a URI.
527  // For server requests, the URL may be a URI or a relative reference.
529 
531 
532  // TODO(bmahler): Ensure this is consistent with the 'Connection'
533  // header; perhaps make this a function that checks the header.
534  //
535  // TODO(anand): Ideally, this could default to 'true' since
536  // persistent connections are the default since HTTP 1.1.
537  // Perhaps, we need to go from `keepAlive` to `closeConnection`
538  // to reflect the header more accurately, and to have an
539  // intuitive default of false.
540  //
541  // Default: false.
542  bool keepAlive;
543 
544  // For server requests, this contains the address of the client.
545  // Note that this may correspond to a proxy or load balancer address.
547 
548  // Clients can choose to provide the entire body at once
549  // via BODY or can choose to stream the body over to the
550  // server via PIPE.
551  //
552  // Default: BODY.
553  enum
554  {
556  PIPE
557  } type;
558 
559  // TODO(bmahler): Add a 'query' field which contains both
560  // the URL query and the parsed form data from the body.
561 
562  std::string body;
564 
569  bool acceptsEncoding(const std::string& encoding) const;
570 
575  bool acceptsMediaType(const std::string& mediaType) const;
576 
583  bool acceptsMediaType(
584  const std::string& name,
585  const std::string& mediaType) const;
586 
587 private:
588  bool _acceptsMediaType(
590  const std::string& mediaType) const;
591 };
592 
593 
594 struct Response
595 {
597  : type(NONE)
598  {}
599 
600  Response(uint16_t _code)
601  : type(NONE), code(_code)
602  {
603  status = Status::string(code);
604  }
605 
606  explicit Response(
607  const std::string& _body,
608  uint16_t _code,
609  const std::string& contentType = "text/plain; charset=utf-8")
610  : type(BODY),
611  body(_body),
612  code(_code)
613  {
614  headers["Content-Length"] = stringify(body.size());
615  headers["Content-Type"] = contentType;
616  status = Status::string(code);
617  }
618 
619  // TODO(benh): Add major/minor version.
620  std::string status;
621 
623 
624  // Either provide a 'body', an absolute 'path' to a file, or a
625  // 'pipe' for streaming a response. Distinguish between the cases
626  // using 'type' below.
627  //
628  // BODY: Uses 'body' as the body of the response. These may be
629  // encoded using gzip for efficiency, if 'Content-Encoding' is not
630  // already specified.
631  //
632  // PATH: Attempts to perform a 'sendfile' operation on the file
633  // found at 'path'.
634  //
635  // PIPE: Splices data from the Pipe 'reader' using a "chunked"
636  // 'Transfer-Encoding'. The writer uses a Pipe::Writer to
637  // perform writes and to detect a closed read-end of the Pipe
638  // (i.e. nobody is listening any longer). Once the writer is
639  // finished, it will close its end of the pipe to signal end
640  // of file to the Reader.
641  //
642  // In all cases (BODY, PATH, PIPE), you are expected to properly
643  // specify the 'Content-Type' header, but the 'Content-Length' and
644  // or 'Transfer-Encoding' headers will be filled in for you.
645  enum
646  {
650  PIPE
651  } type;
652 
653  std::string body;
654  std::string path;
656 
657  uint16_t code;
658 };
659 
660 
661 struct OK : Response
662 {
663  OK() : Response(Status::OK) {}
664 
665  explicit OK(const char* body)
666  : Response(std::string(body), Status::OK) {}
667 
668  explicit OK(const std::string& body) : Response(body, Status::OK) {}
669 
670  explicit OK(const std::string& body, const std::string& contentType)
671  : Response(body, Status::OK, contentType) {}
672 
673  OK(const JSON::Value& value, const Option<std::string>& jsonp = None());
674 
675  OK(JSON::Proxy&& value, const Option<std::string>& jsonp = None());
676 };
677 
678 
680 {
681  Accepted() : Response(Status::ACCEPTED) {}
682 
683  explicit Accepted(const std::string& body)
684  : Response(body, Status::ACCEPTED) {}
685 };
686 
687 
689 {
690  explicit TemporaryRedirect(const std::string& url)
691  : Response(Status::TEMPORARY_REDIRECT)
692  {
693  headers["Location"] = url;
694  }
695 };
696 
697 
699 {
700  BadRequest() : Response(Status::BAD_REQUEST) {}
701 
702  explicit BadRequest(const std::string& body)
703  : Response(body, Status::BAD_REQUEST) {}
704 };
705 
706 
708 {
709  explicit Unauthorized(const std::vector<std::string>& challenges)
710  : Response(Status::UNAUTHORIZED)
711  {
712  // TODO(arojas): Many HTTP client implementations do not support
713  // multiple challenges within a single 'WWW-Authenticate' header.
714  // Once MESOS-3306 is fixed, we can use multiple entries for the
715  // same header.
716  headers["WWW-Authenticate"] = strings::join(", ", challenges);
717  }
718 
720  const std::vector<std::string>& challenges,
721  const std::string& body)
722  : Response(body, Status::UNAUTHORIZED)
723  {
724  // TODO(arojas): Many HTTP client implementations do not support
725  // multiple challenges within a single 'WWW-Authenticate' header.
726  // Once MESOS-3306 is fixed, we can use multiple entries for the
727  // same header.
728  headers["WWW-Authenticate"] = strings::join(", ", challenges);
729  }
730 };
731 
732 
734 {
735  Forbidden() : Response(Status::FORBIDDEN) {}
736 
737  explicit Forbidden(const std::string& body)
738  : Response(body, Status::FORBIDDEN) {}
739 };
740 
741 
743 {
744  NotFound() : Response(Status::NOT_FOUND) {}
745 
746  explicit NotFound(const std::string& body)
747  : Response(body, Status::NOT_FOUND) {}
748 };
749 
750 
752 {
753  // According to RFC 2616, "An Allow header field MUST be present in a
754  // 405 (Method Not Allowed) response".
755 
757  const std::initializer_list<std::string>& allowedMethods)
758  : Response(Status::METHOD_NOT_ALLOWED)
759  {
760  headers["Allow"] = strings::join(", ", allowedMethods);
761  }
762 
764  const std::initializer_list<std::string>& allowedMethods,
765  const std::string& requestMethod)
766  : Response(
767  constructBody(allowedMethods, requestMethod),
768  Status::METHOD_NOT_ALLOWED)
769  {
770  headers["Allow"] = strings::join(", ", allowedMethods);
771  }
772 
773 private:
774  static std::string constructBody(
775  const std::initializer_list<std::string>& allowedMethods,
776  const std::string& requestMethod)
777  {
778  return "Expecting one of { '" + strings::join("', '", allowedMethods) +
779  "' }, but received '" + requestMethod + "'";
780  }
781 };
782 
783 
785 {
786  NotAcceptable() : Response(Status::NOT_ACCEPTABLE) {}
787 
788  explicit NotAcceptable(const std::string& body)
789  : Response(body, Status::NOT_ACCEPTABLE) {}
790 };
791 
792 
794 {
795  Conflict() : Response(Status::CONFLICT) {}
796 
797  explicit Conflict(const std::string& body)
798  : Response(body, Status::CONFLICT) {}
799 };
800 
801 
803 {
804  PreconditionFailed() : Response(Status::PRECONDITION_FAILED) {}
805 
806  explicit PreconditionFailed(const std::string& body)
807  : Response(body, Status::PRECONDITION_FAILED) {}
808 };
809 
810 
812 {
813  UnsupportedMediaType() : Response(Status::UNSUPPORTED_MEDIA_TYPE) {}
814 
815  explicit UnsupportedMediaType(const std::string& body)
816  : Response(body, Status::UNSUPPORTED_MEDIA_TYPE) {}
817 };
818 
819 
821 {
822  InternalServerError() : Response(Status::INTERNAL_SERVER_ERROR) {}
823 
824  explicit InternalServerError(const std::string& body)
825  : Response(body, Status::INTERNAL_SERVER_ERROR) {}
826 };
827 
828 
830 {
831  NotImplemented() : Response(Status::NOT_IMPLEMENTED) {}
832 
833  explicit NotImplemented(const std::string& body)
834  : Response(body, Status::NOT_IMPLEMENTED) {}
835 };
836 
837 
839 {
840  ServiceUnavailable() : Response(Status::SERVICE_UNAVAILABLE) {}
841 
842  explicit ServiceUnavailable(const std::string& body)
843  : Response(body, Status::SERVICE_UNAVAILABLE) {}
844 };
845 
846 
847 namespace path {
848 
849 // Parses an HTTP path into a map given a pattern (TODO(benh): Make
850 // the patterns be regular expressions). This returns an error if
851 // 'pattern' doesn't match 'path'. For example:
852 //
853 // parse("/books/{isbn}/chapters/{chapter}",
854 // "/books/0304827484/chapters/3")
855 //
856 // Would return a map with the following:
857 // books: "books"
858 // isbn: "0304827484"
859 // chapters: "chapters"
860 // chapter: "3"
861 //
862 // Another example:
863 //
864 // parse("/books/{isbn}/chapters/{chapter}",
865 // "/books/0304827484")
866 //
867 // Would return a map with the following:
868 // books: "books"
869 // isbn: "0304827484"
870 //
871 // And another:
872 //
873 // parse("/books/{isbn}/chapters/{chapter}",
874 // "/books/0304827484/chapters")
875 //
876 // Would return a map with the following:
877 // books: "books"
878 // isbn: "0304827484"
879 // chapters: "chapters"
881  const std::string& pattern,
882  const std::string& path);
883 
884 } // namespace path {
885 
886 
896 std::string encode(
897  const std::string& s,
898  const std::string& additional_chars = "");
899 
900 
901 // Decodes a percent-encoded string according to RFC 3986.
902 // The input string must not already be decoded.
903 // Returns error on the occurrence of a malformed % escape in s.
904 Try<std::string> decode(const std::string& s);
905 
906 
912 Try<std::vector<Response>> decodeResponses(const std::string& s);
913 
914 
915 namespace query {
916 
917 // Decodes an HTTP query string into a map. For example:
918 //
919 // decode("foo=1&bar=%20&baz&foo=3")
920 //
921 // Would return a map with the following:
922 // bar: " "
923 // baz: ""
924 // foo: "3"
925 //
926 // We use the last value for a key for simplicity, since the RFC does not
927 // specify how to handle duplicate keys:
928 // http://en.wikipedia.org/wiki/Query_string
929 // TODO(bmahler): If needed, investigate populating the query map inline
930 // for better performance.
931 Try<hashmap<std::string, std::string>> decode(const std::string& query);
932 
933 std::string encode(const hashmap<std::string, std::string>& query);
934 
935 } // namespace query {
936 
937 
945 {
946 public:
947  Connection() = delete;
948 
956  Future<Response> send(const Request& request, bool streamedResponse = false);
957 
961  Future<Nothing> disconnect();
962 
966  Future<Nothing> disconnected();
967 
968  bool operator==(const Connection& c) const { return data == c.data; }
969  bool operator!=(const Connection& c) const { return !(*this == c); }
970 
973 
974 private:
975  Connection(
976  const network::Socket& s,
977  const network::Address& _localAddress,
978  const network::Address& _peerAddress);
979 
981  const network::Address& address, Scheme scheme);
982  friend Future<Connection> connect(const URL&);
983 
984  // Forward declaration.
985  struct Data;
986 
987  std::shared_ptr<Data> data;
988 };
989 
990 
992 
993 
994 Future<Connection> connect(const URL& url);
995 
996 
997 namespace internal {
998 
1000  network::Socket s,
1001  std::function<Future<Response>(const Request&)>&& f);
1002 
1003 } // namespace internal {
1004 
1005 
1006 // Serves HTTP requests on the specified socket using the specified
1007 // handler.
1008 //
1009 // Returns `Nothing` after serving has completed, either because (1) a
1010 // failure occurred receiving requests or sending responses or (2) the
1011 // HTTP connection was not persistent (i.e., a 'Connection: close'
1012 // header existed either on the request or the response) or (3)
1013 // serving was discarded.
1014 //
1015 // Doing a `discard()` on the Future returned from `serve` will
1016 // discard any current socket receiving and any current socket
1017 // sending and shutdown the socket in both directions.
1018 //
1019 // NOTE: HTTP pipelining is automatically performed. If you don't want
1020 // pipelining you must explicitly sequence/serialize the requests to
1021 // wait for previous responses yourself.
1022 //
1023 // NOTE: The `Request` passed to the handler is of type `PIPE` and should
1024 // always be read using `Request.reader`.
1025 template <typename F>
1027 {
1028  return internal::serve(
1029  s,
1030  std::function<Future<Response>(const Request&)>(std::forward<F>(f)));
1031 }
1032 
1033 
1034 // Forward declaration.
1035 class ServerProcess;
1036 
1037 
1038 class Server
1039 {
1040 public:
1041  // Options for creating a server.
1042  //
1043  // NOTE: until GCC 5.0 default member initializers prevented the
1044  // class from being an aggregate which prevented you from being able
1045  // to use aggregate initialization, thus we introduce and use
1046  // `DEFAULT_CREATE_OPTIONS` for the default parameter of `create`.
1048  {
1050  size_t backlog;
1051  };
1052 
1054  {
1055  return {
1056  /* .scheme = */ Scheme::HTTP,
1057  /* .backlog = */ 16384,
1058  };
1059  };
1060 
1061  // Options for stopping a server.
1062  //
1063  // NOTE: see note above as to why we have `DEFAULT_STOP_OPTIONS`.
1065  {
1066  // During the grace period:
1067  // * No new sockets will be accepted (but on OS X they'll still queue).
1068  // * Existing sockets will be shut down for reads to prevent new
1069  // requests from arriving.
1070  // * Existing sockets will be shut down after already received
1071  // requests have their responses sent.
1072  // After the grace period connections will be forcibly shut down.
1074  };
1075 
1077  {
1078  return {
1079  /* .grace_period = */ Seconds(0),
1080  };
1081  };
1082 
1083  static Try<Server> create(
1085  std::function<Future<Response>(
1086  const network::Socket& socket,
1087  const Request&)>&& f,
1088  const CreateOptions& options = DEFAULT_CREATE_OPTIONS());
1089 
1090  template <typename F>
1092  network::Socket socket,
1093  F&& f,
1094  const CreateOptions& options = DEFAULT_CREATE_OPTIONS())
1095  {
1096  return create(
1097  std::move(socket),
1098  std::function<Future<Response>(
1099  const network::Socket&,
1100  const Request&)>(std::forward<F>(f)),
1101  options);
1102  }
1103 
1104  static Try<Server> create(
1105  const network::Address& address,
1106  std::function<Future<Response>(
1107  const network::Socket&,
1108  const Request&)>&& f,
1109  const CreateOptions& options = DEFAULT_CREATE_OPTIONS());
1110 
1111  template <typename F>
1113  const network::Address& address,
1114  F&& f,
1115  const CreateOptions& options = DEFAULT_CREATE_OPTIONS())
1116  {
1117  return create(
1118  address,
1119  std::function<Future<Response>(
1120  const network::Socket&,
1121  const Request&)>(std::forward<F>(f)),
1122  options);
1123  }
1124 
1125  // Movable but not copyable, not assignable.
1126  Server(Server&& that) = default;
1127  Server(const Server&) = delete;
1128  Server& operator=(const Server&) = delete;
1129 
1130  ~Server();
1131 
1132  // Runs the server, returns nothing after the server has been
1133  // stopped or a failure if one occured.
1134  Future<Nothing> run();
1135 
1136  // Returns after the server has been stopped and all existing
1137  // connections have been closed.
1138  Future<Nothing> stop(const StopOptions& options = DEFAULT_STOP_OPTIONS());
1139 
1140  // Returns the bound address of the server.
1142 
1143 private:
1144  Server(
1145  network::Socket&& socket,
1146  std::function<Future<Response>(
1147  const network::Socket&,
1148  const Request&)>&& f);
1149 
1152 };
1153 
1154 
1155 // Create a http Request from the specified parameters.
1157  const UPID& upid,
1158  const std::string& method,
1159  bool enableSSL = false,
1160  const Option<std::string>& path = None(),
1161  const Option<Headers>& headers = None(),
1162  const Option<std::string>& body = None(),
1163  const Option<std::string>& contentType = None());
1164 
1165 
1167  const URL& url,
1168  const std::string& method,
1169  const Option<Headers>& headers = None(),
1170  const Option<std::string>& body = None(),
1171  const Option<std::string>& contentType = None());
1172 
1182  const Request& request,
1183  bool streamedResponse = false);
1184 
1185 
1186 // TODO(Yongqiao Wang): Refactor other functions
1187 // (such as post/get/requestDelete) to use the 'request' function.
1188 
1189 // TODO(bmahler): Support discarding the future responses;
1190 // discarding should disconnect from the server.
1191 
1192 // TODO(joerg84): Make names consistent (see Mesos-3256).
1193 
1194 // Asynchronously sends an HTTP GET request to the specified URL
1195 // and returns the HTTP response of type 'BODY' once the entire
1196 // response is received.
1197 Future<Response> get(
1198  const URL& url,
1199  const Option<Headers>& headers = None());
1200 
1201 
1202 // Asynchronously sends an HTTP GET request to the process with the
1203 // given UPID and returns the HTTP response of type 'BODY' once the
1204 // entire response is received.
1205 Future<Response> get(
1206  const UPID& upid,
1207  const Option<std::string>& path = None(),
1208  const Option<std::string>& query = None(),
1209  const Option<Headers>& headers = None(),
1210  const Option<std::string>& scheme = None());
1211 
1212 
1213 // Asynchronously sends an HTTP POST request to the specified URL
1214 // and returns the HTTP response of type 'BODY' once the entire
1215 // response is received.
1217  const URL& url,
1218  const Option<Headers>& headers = None(),
1219  const Option<std::string>& body = None(),
1220  const Option<std::string>& contentType = None());
1221 
1222 
1223 // Asynchronously sends an HTTP POST request to the process with the
1224 // given UPID and returns the HTTP response of type 'BODY' once the
1225 // entire response is received.
1227  const UPID& upid,
1228  const Option<std::string>& path = None(),
1229  const Option<Headers>& headers = None(),
1230  const Option<std::string>& body = None(),
1231  const Option<std::string>& contentType = None(),
1232  const Option<std::string>& scheme = None());
1233 
1234 
1244  const URL& url,
1245  const Option<Headers>& headers = None());
1246 
1247 
1260  const UPID& upid,
1261  const Option<std::string>& path = None(),
1262  const Option<Headers>& headers = None(),
1263  const Option<std::string>& scheme = None());
1264 
1265 
1266 namespace streaming {
1267 
1268 // Asynchronously sends an HTTP GET request to the specified URL
1269 // and returns the HTTP response of type 'PIPE' once the response
1270 // headers are received. The caller must read the response body
1271 // from the Pipe::Reader.
1272 Future<Response> get(
1273  const URL& url,
1274  const Option<Headers>& headers = None());
1275 
1276 // Asynchronously sends an HTTP GET request to the process with the
1277 // given UPID and returns the HTTP response of type 'PIPE' once the
1278 // response headers are received. The caller must read the response
1279 // body from the Pipe::Reader.
1280 Future<Response> get(
1281  const UPID& upid,
1282  const Option<std::string>& path = None(),
1283  const Option<std::string>& query = None(),
1284  const Option<Headers>& headers = None(),
1285  const Option<std::string>& scheme = None());
1286 
1287 // Asynchronously sends an HTTP POST request to the specified URL
1288 // and returns the HTTP response of type 'PIPE' once the response
1289 // headers are received. The caller must read the response body
1290 // from the Pipe::Reader.
1292  const URL& url,
1293  const Option<Headers>& headers = None(),
1294  const Option<std::string>& body = None(),
1295  const Option<std::string>& contentType = None());
1296 
1297 // Asynchronously sends an HTTP POST request to the process with the
1298 // given UPID and returns the HTTP response of type 'PIPE' once the
1299 // response headers are received. The caller must read the response
1300 // body from the Pipe::Reader.
1302  const UPID& upid,
1303  const Option<std::string>& path = None(),
1304  const Option<Headers>& headers = None(),
1305  const Option<std::string>& body = None(),
1306  const Option<std::string>& contentType = None(),
1307  const Option<std::string>& scheme = None());
1308 
1309 } // namespace streaming {
1310 
1311 } // namespace http {
1312 } // namespace process {
1313 
1314 #endif // __PROCESS_HTTP_HPP__
static StopOptions DEFAULT_STOP_OPTIONS()
Definition: http.hpp:1076
Definition: path.hpp:26
Try< hashmap< std::string, std::string > > parse(const std::string &pattern, const std::string &path)
NotImplemented(const std::string &body)
Definition: http.hpp:833
bool operator!=(const Writer &other) const
Definition: http.hpp:364
WWWAuthenticate(const std::string &authScheme, const hashmap< std::string, std::string > &authParam)
Definition: http.hpp:428
size_t operator()(const std::string &key) const
Definition: http.hpp:185
Future< Nothing > serve(network::Socket s, std::function< Future< Response >(const Request &)> &&f)
Forbidden()
Definition: http.hpp:735
NotFound(const std::string &body)
Definition: http.hpp:746
bool operator!=(const Connection &c) const
Definition: http.hpp:969
static const uint16_t GATEWAY_TIMEOUT
Definition: http.hpp:253
static const uint16_t MOVED_PERMANENTLY
Definition: http.hpp:225
static const uint16_t GONE
Definition: http.hpp:241
static const uint16_t UNSUPPORTED_MEDIA_TYPE
Definition: http.hpp:246
Definition: errorbase.hpp:36
Definition: http.hpp:1047
Definition: option.hpp:28
Definition: http.hpp:295
static const uint16_t METHOD_NOT_ALLOWED
Definition: http.hpp:236
Future< Response > request(const Request &request, bool streamedResponse=false)
Asynchronously sends an HTTP request to the process and returns the HTTP response once the entire res...
F && f
Definition: defer.hpp:270
static const uint16_t BAD_REQUEST
Definition: http.hpp:231
static const uint16_t NO_CONTENT
Definition: http.hpp:221
T & get()&
Definition: try.hpp:73
URL url
Definition: http.hpp:528
static const uint16_t REQUEST_TIMEOUT
Definition: http.hpp:239
static const uint16_t LENGTH_REQUIRED
Definition: http.hpp:242
NotAcceptable(const std::string &body)
Definition: http.hpp:788
std::stringstream & join(std::stringstream &stream, const std::string &separator, T &&...args)
Definition: strings.hpp:307
static CreateOptions DEFAULT_CREATE_OPTIONS()
Definition: http.hpp:1053
Definition: check.hpp:33
std::string status
Definition: http.hpp:620
NotAcceptable()
Definition: http.hpp:786
static const uint16_t PARTIAL_CONTENT
Definition: http.hpp:223
static const uint16_t EXPECTATION_FAILED
Definition: http.hpp:248
static const uint16_t CONFLICT
Definition: http.hpp:240
Option< Pipe::Reader > reader
Definition: http.hpp:563
Unauthorized(const std::vector< std::string > &challenges)
Definition: http.hpp:709
uint16_t code
Definition: http.hpp:657
Definition: http.hpp:183
UnsupportedMediaType(const std::string &body)
Definition: http.hpp:815
Definition: http.hpp:213
OK()
Definition: http.hpp:663
Future< Nothing > serve(const network::Socket &s, F &&f)
Definition: http.hpp:1026
Definition: http.hpp:829
static const uint16_t NON_AUTHORITATIVE_INFORMATION
Definition: http.hpp:220
Result< ProcessStatus > status(pid_t pid)
Definition: proc.hpp:166
Definition: http.hpp:196
Option< std::string > domain
Definition: http.hpp:171
InternalServerError()
Definition: http.hpp:822
Definition: http.hpp:1038
static const uint16_t FOUND
Definition: http.hpp:226
bool operator==(const Writer &other) const
Definition: http.hpp:363
Definition: type_utils.hpp:510
Definition: address.hpp:276
Forbidden(const std::string &body)
Definition: http.hpp:737
Future< Response > get(const URL &url, const Option< Headers > &headers=None())
Definition: http.hpp:555
Option< network::Address > client
Definition: http.hpp:546
const std::string NAME
Definition: logrotate.hpp:38
static const uint16_t MULTIPLE_CHOICES
Definition: http.hpp:224
static const uint16_t REQUEST_ENTITY_TOO_LARGE
Definition: http.hpp:244
Definition: http.hpp:647
Future< Response > requestDelete(const URL &url, const Option< Headers > &headers=None())
Asynchronously sends an HTTP DELETE request to the process with the given UPID and returns the HTTP r...
std::string encode(const std::string &s, const std::string &additional_chars="")
Returns a percent-encoded string according to RFC 3986.
Definition: http.hpp:688
Option< net::IP > ip
Definition: http.hpp:172
Definition: duration.hpp:32
Try< std::string > decode(const std::string &s)
Decode a string that is Base64-encoded with the standard Base64 alphabet.
Definition: base64.hpp:183
Definition: check.hpp:30
BadRequest()
Definition: http.hpp:700
static const uint16_t RESET_CONTENT
Definition: http.hpp:222
Definition: http.hpp:517
PreconditionFailed()
Definition: http.hpp:804
Scheme
Definition: http.hpp:55
bool operator==(const Connection &c) const
Definition: http.hpp:968
ServiceUnavailable()
Definition: http.hpp:840
hashmap< std::string, std::string > query
Definition: http.hpp:175
Definition: http.hpp:648
Definition: ip.hpp:73
Definition: hashmap.hpp:38
InternalServerError(const std::string &body)
Definition: http.hpp:824
Duration grace_period
Definition: http.hpp:1073
Accepted()
Definition: http.hpp:681
Option< Pipe::Reader > reader
Definition: http.hpp:655
std::string path
Definition: http.hpp:174
Definition: http.hpp:793
Definition: http.hpp:751
static const uint16_t PRECONDITION_FAILED
Definition: http.hpp:243
std::string body
Definition: http.hpp:653
An "untyped" PID, used to encapsulate the process ID for lower-layer abstractions (eg...
Definition: pid.hpp:39
Definition: http.hpp:128
static const uint16_t NOT_ACCEPTABLE
Definition: http.hpp:237
Option< std::string > scheme
Definition: http.hpp:168
Definition: http.hpp:679
Future< Nothing > setAuthenticator(const std::string &realm, Owned< Authenticator > authenticator)
Sets (or overwrites) the authenticator for the realm.
NotImplemented()
Definition: http.hpp:831
OK(const char *body)
Definition: http.hpp:665
static const uint16_t SERVICE_UNAVAILABLE
Definition: http.hpp:252
Definition: http.hpp:339
Try<::mesos::Value::Ranges > fragment(const ::mesos::Value::Range &bounds, size_t numRanges)
Definition: jsonify.hpp:85
Definition: duration.hpp:207
static const uint16_t PAYMENT_REQUIRED
Definition: http.hpp:233
URL(const std::string &_scheme, const net::IP &_ip, const uint16_t _port=80, const std::string &_path="/", const hashmap< std::string, std::string > &_query=(hashmap< std::string, std::string >()), const Option< std::string > &_fragment=None())
Definition: http.hpp:146
Definition: http.hpp:455
static const uint16_t USE_PROXY
Definition: http.hpp:229
Option< uint16_t > port
Definition: http.hpp:173
Headers(std::map< std::string, std::string > &&map)
Definition: http.hpp:471
static const uint16_t ACCEPTED
Definition: http.hpp:219
NotFound()
Definition: http.hpp:744
const T & get() const &
Definition: option.hpp:118
MethodNotAllowed(const std::initializer_list< std::string > &allowedMethods)
Definition: http.hpp:756
ServiceUnavailable(const std::string &body)
Definition: http.hpp:842
Definition: http.hpp:784
Future< Response > post(const URL &url, const Option< Headers > &headers=None(), const Option< std::string > &body=None(), const Option< std::string > &contentType=None())
Request createRequest(const UPID &upid, const std::string &method, bool enableSSL=false, const Option< std::string > &path=None(), const Option< Headers > &headers=None(), const Option< std::string > &body=None(), const Option< std::string > &contentType=None())
Future< Connection > connect(const network::Address &address, Scheme scheme)
Definition: http.hpp:820
bool keepAlive
Definition: http.hpp:542
Accepted(const std::string &body)
Definition: http.hpp:683
bool operator==(const Pipe &other) const
Definition: http.hpp:386
static const uint16_t SEE_OTHER
Definition: http.hpp:227
bool operator!=(const Reader &other) const
Definition: http.hpp:323
static const uint16_t OK
Definition: http.hpp:217
Definition: http.hpp:838
URL(const std::string &_scheme, const std::string &_domain, const uint16_t _port=80, const std::string &_path="/", const hashmap< std::string, std::string > &_query=(hashmap< std::string, std::string >()), const Option< std::string > &_fragment=None())
Definition: http.hpp:132
OK(const std::string &body, const std::string &contentType)
Definition: http.hpp:670
static Try error(const E &e)
Definition: try.hpp:42
Scheme scheme
Definition: http.hpp:1049
Future< R > run(R(*method)())
Definition: run.hpp:55
Conflict()
Definition: http.hpp:795
MethodNotAllowed(const std::initializer_list< std::string > &allowedMethods, const std::string &requestMethod)
Definition: http.hpp:763
Option< std::string > fragment
Definition: http.hpp:176
static const uint16_t CONTINUE
Definition: http.hpp:215
Try< std::vector< Entry > > list(const std::string &hierarchy, const std::string &cgroup)
static const uint16_t PROXY_AUTHENTICATION_REQUIRED
Definition: http.hpp:238
Definition: json.hpp:247
Iterable< V > map(F &&f, const Iterable< U, Us... > &input)
Definition: lambda.hpp:46
BadRequest(const std::string &body)
Definition: http.hpp:702
Result< Process > process(pid_t pid)
Definition: freebsd.hpp:30
Definition: http.hpp:802
bool operator!=(const Pipe &other) const
Definition: http.hpp:387
Definition: none.hpp:27
Definition: attributes.hpp:24
bool isError() const
Definition: try.hpp:71
Result< Credentials > read(const Path &path)
Definition: credentials.hpp:35
std::string path
Definition: http.hpp:654
TemporaryRedirect(const std::string &url)
Definition: http.hpp:690
OK(const std::string &body)
Definition: http.hpp:668
std::string method
Definition: http.hpp:522
Definition: executor.hpp:48
Definition: http.hpp:594
std::ostream & operator<<(std::ostream &stream, const URL &url)
Pipe()
Definition: http.hpp:380
Definition: http.hpp:811
Headers operator+(const Headers &that) const
Definition: http.hpp:508
std::string body
Definition: http.hpp:562
static const uint16_t SWITCHING_PROTOCOLS
Definition: http.hpp:216
static const uint16_t BAD_GATEWAY
Definition: http.hpp:251
Try< std::vector< Response > > decodeResponses(const std::string &s)
Decode HTTP responses from the given string.
static const uint16_t INTERNAL_SERVER_ERROR
Definition: http.hpp:249
Definition: http.hpp:698
UnsupportedMediaType()
Definition: http.hpp:813
Protocol< WriteRequest, WriteResponse > write
Definition: http.hpp:661
Headers(const std::map< std::string, std::string > &map)
Definition: http.hpp:464
Try< uint32_t > type(const std::string &path)
network::inet::Address address()
Returns the socket address associated with this instance of the library.
static const uint16_t NOT_MODIFIED
Definition: http.hpp:228
Definition: http.hpp:707
static Try< Server > create(network::Socket socket, F &&f, const CreateOptions &options=DEFAULT_CREATE_OPTIONS())
Definition: http.hpp:1091
bool isNone() const
Definition: option.hpp:116
const network::Address peerAddress
Definition: http.hpp:972
static const uint16_t REQUESTED_RANGE_NOT_SATISFIABLE
Definition: http.hpp:247
void setCallbacks(const AuthorizationCallbacks &)
static const uint16_t CREATED
Definition: http.hpp:218
Try< Nothing > create(const std::string &hierarchy, const std::string &cgroup, bool recursive=false)
Definition: http.hpp:649
Response()
Definition: http.hpp:596
static const uint16_t UNAUTHORIZED
Definition: http.hpp:232
static const uint16_t NOT_FOUND
Definition: http.hpp:235
URI http(const std::string &host, const std::string &path="/", const Option< int > &port=None(), const Option< std::string > &query=None(), const Option< std::string > &fragment=None(), const Option< std::string > &user=None(), const Option< std::string > &password=None())
Creates an http URI with the given parameters.
Definition: http.hpp:35
bool operator==(const Reader &other) const
Definition: http.hpp:322
Try< Netlink< struct nl_sock > > socket(int protocol=NETLINK_ROUTE)
Definition: internal.hpp:91
std::string stringify(int flags)
static const uint16_t NOT_IMPLEMENTED
Definition: http.hpp:250
Definition: owned.hpp:36
static std::string string(uint16_t code)
Headers()
Definition: http.hpp:462
Headers(std::initializer_list< std::pair< std::string, std::string >> list)
Definition: http.hpp:478
Headers headers
Definition: http.hpp:622
Response(uint16_t _code)
Definition: http.hpp:600
Conflict(const std::string &body)
Definition: http.hpp:797
const network::Address localAddress
Definition: http.hpp:971
size_t backlog
Definition: http.hpp:1050
static const uint16_t REQUEST_URI_TOO_LARGE
Definition: http.hpp:245
Definition: http.hpp:1064
bool isValidStatus(uint16_t code)
Represents a connection to an HTTP server.
Definition: http.hpp:944
Future< Nothing > unsetAuthenticator(const std::string &realm)
Unsets the authenticator for the realm.
bool operator()(const std::string &left, const std::string &right) const
Definition: http.hpp:198
Definition: http.hpp:301
constexpr const char * name
Definition: shell.hpp:43
static const uint16_t HTTP_VERSION_NOT_SUPPORTED
Definition: http.hpp:254
Unauthorized(const std::vector< std::string > &challenges, const std::string &body)
Definition: http.hpp:719
static Try< Server > create(const network::Address &address, F &&f, const CreateOptions &options=DEFAULT_CREATE_OPTIONS())
Definition: http.hpp:1112
static const uint16_t TEMPORARY_REDIRECT
Definition: http.hpp:230
static const uint16_t FORBIDDEN
Definition: http.hpp:234
Headers headers
Definition: http.hpp:530
Definition: http.hpp:733
Definition: http.hpp:742
PreconditionFailed(const std::string &body)
Definition: http.hpp:806
Response(const std::string &_body, uint16_t _code, const std::string &contentType="text/plain; charset=utf-8")
Definition: http.hpp:606
Future< size_t > send(const int_fd &fd, const void *buf, size_t size)
Request()
Definition: http.hpp:519