C++ Rest SDK
The C++ REST SDK is a Microsoft project for cloud-based client-server communication in native code using a modern asynchronous C++ API design. This project aims to help C++ developers connect to and interact with services.
http_msg.h
1 /***
2 * ==++==
3 *
4 * Copyright (c) Microsoft Corporation. All rights reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * ==--==
17 * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
18 *
19 * HTTP Library: Request and reply message definitions.
20 *
21 * For the latest on this and related APIs, please see http://casablanca.codeplex.com.
22 *
23 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
24 ****/
25 #pragma once
26 
27 #include <map>
28 #include <memory>
29 #include <string>
30 #include <vector>
31 #include <system_error>
32 
33 #include "pplx/pplxtasks.h"
34 #include "cpprest/json.h"
35 #include "cpprest/uri.h"
36 #include "cpprest/http_headers.h"
37 #include "cpprest/details/cpprest_compat.h"
38 #include "cpprest/asyncrt_utils.h"
39 #include "cpprest/streams.h"
40 #include "cpprest/containerstream.h"
41 
42 namespace web
43 {
44 namespace http
45 {
46 
47 // URI class has been moved from web::http namespace to web namespace.
48 // The below using declarations ensure we don't break existing code.
49 // Please use the web::uri class going forward.
50 using web::uri;
51 using web::uri_builder;
52 
53 namespace client
54 {
55  class http_client;
56 }
57 
62 typedef utility::string_t method;
63 
67 class methods
68 {
69 public:
70 #define _METHODS
71 #define DAT(a,b) _ASYNCRTIMP const static method a;
72 #include "cpprest/details/http_constants.dat"
73 #undef _METHODS
74 #undef DAT
75 };
76 
77 typedef unsigned short status_code;
78 
83 {
84 public:
85 #define _PHRASES
86 #define DAT(a,b,c) const static status_code a=b;
87 #include "cpprest/details/http_constants.dat"
88 #undef _PHRASES
89 #undef DAT
90 };
91 
93 namespace message_direction
94 {
99  enum direction {
100  upload,
101  download
102  };
103 }
104 
105 typedef utility::string_t reason_phrase;
106 typedef std::function<void(message_direction::direction, utility::size64_t)> progress_handler;
107 
109 {
110  unsigned short id;
111  reason_phrase phrase;
112 };
113 
118 {
119 public:
120 #define _HEADER_NAMES
121 #define DAT(a,b) _ASYNCRTIMP const static utility::string_t a;
122 #include "cpprest/details/http_constants.dat"
123 #undef _HEADER_NAMES
124 #undef DAT
125 };
126 
130 class http_exception : public std::exception
131 {
132 public:
133 
138  http_exception(const utility::string_t &whatArg)
139  : m_msg(utility::conversions::to_utf8string(whatArg)) {}
140 
141 #ifdef _WIN32
142  http_exception(std::string whatArg) : m_msg(std::move(whatArg)) {}
147 #endif
148 
154  http_exception(int errorCode)
155  : m_errorCode(utility::details::create_error_code(errorCode))
156  {
157  m_msg = m_errorCode.message();
158  }
159 
165  http_exception(int errorCode, const utility::string_t &whatArg)
166  : m_errorCode(utility::details::create_error_code(errorCode)),
167  m_msg(utility::conversions::to_utf8string(whatArg))
168  {}
169 
170 #ifdef _WIN32
171  http_exception(int errorCode, std::string whatArg) :
177  m_errorCode(utility::details::create_error_code(errorCode)),
178  m_msg(std::move(whatArg))
179  {}
180 #endif
181 
188  http_exception(int errorCode, const std::error_category &cat) : m_errorCode(std::error_code(errorCode, cat))
189  {
190  m_msg = m_errorCode.message();
191  }
192 
197  const char* what() const CPPREST_NOEXCEPT
198  {
199  return m_msg.c_str();
200  }
201 
206  const std::error_code & error_code() const
207  {
208  return m_errorCode;
209  }
210 
211 private:
212  std::error_code m_errorCode;
213  std::string m_msg;
214 };
215 
216 namespace details
217 {
218 
225 {
226 public:
227 
228  friend class http::client::http_client;
229 
230  _ASYNCRTIMP http_msg_base();
231 
232  virtual ~http_msg_base() {}
233 
234  http_headers &headers() { return m_headers; }
235 
236  _ASYNCRTIMP void set_body(const concurrency::streams::istream &instream, const utf8string &contentType);
237  _ASYNCRTIMP void set_body(const concurrency::streams::istream &instream, const utf16string &contentType);
238  _ASYNCRTIMP void set_body(const concurrency::streams::istream &instream, utility::size64_t contentLength, const utf8string &contentType);
239  _ASYNCRTIMP void set_body(const concurrency::streams::istream &instream, utility::size64_t contentLength, const utf16string &contentType);
240 
248  utility::string_t parse_and_check_content_type(bool ignore_content_type, const std::function<bool(const utility::string_t&)> &check_content_type);
249 
250  _ASYNCRTIMP utf8string extract_utf8string(bool ignore_content_type = false);
251  _ASYNCRTIMP utf16string extract_utf16string(bool ignore_content_type = false);
252  _ASYNCRTIMP utility::string_t extract_string(bool ignore_content_type = false);
253 
254  _ASYNCRTIMP json::value _extract_json(bool ignore_content_type = false);
255  _ASYNCRTIMP std::vector<unsigned char> _extract_vector();
256 
257  virtual _ASYNCRTIMP utility::string_t to_string() const;
258 
262  virtual _ASYNCRTIMP void _complete(utility::size64_t bodySize, const std::exception_ptr &exceptionPtr = std::exception_ptr());
263 
267  void set_instream(const concurrency::streams::istream &instream) { m_inStream = instream; }
268 
272  const concurrency::streams::istream & instream() const { return m_inStream; }
273 
277  void set_outstream(const concurrency::streams::ostream &outstream, bool is_default) { m_outStream = outstream; m_default_outstream = is_default; }
278 
282  const concurrency::streams::ostream & outstream() const { return m_outStream; }
283 
284  const pplx::task_completion_event<utility::size64_t> & _get_data_available() const { return m_data_available; }
285 
289  _ASYNCRTIMP void _prepare_to_receive_data();
290 
303  _ASYNCRTIMP size_t _get_content_length();
304 
305 protected:
306 
317  concurrency::streams::istream m_inStream;
318 
325  concurrency::streams::ostream m_outStream;
326 
327  http_headers m_headers;
328  bool m_default_outstream;
329 
332 };
333 
339 {
340 public:
342  virtual ~_http_server_context() {}
343 private:
344 };
345 
350 {
351 public:
352  _http_response() : m_status_code((std::numeric_limits<uint16_t>::max)()) { }
353 
354  _http_response(http::status_code code) : m_status_code(code) {}
355 
356  http::status_code status_code() const { return m_status_code; }
357 
358  void set_status_code(http::status_code code) { m_status_code = code; }
359 
360  const http::reason_phrase & reason_phrase() const { return m_reason_phrase; }
361 
362  void set_reason_phrase(const http::reason_phrase &reason) { m_reason_phrase = reason; }
363 
364  _ASYNCRTIMP utility::string_t to_string() const;
365 
366  _http_server_context * _get_server_context() const { return m_server_context.get(); }
367 
368  void _set_server_context(std::unique_ptr<details::_http_server_context> server_context) { m_server_context = std::move(server_context); }
369 
370 private:
371  std::unique_ptr<_http_server_context> m_server_context;
372 
373  http::status_code m_status_code;
374  http::reason_phrase m_reason_phrase;
375 };
376 
377 } // namespace details
378 
379 
384 {
385 public:
386 
391  http_response() : _m_impl(std::make_shared<details::_http_response>()) { }
392 
398  http_response(http::status_code code)
399  : _m_impl(std::make_shared<details::_http_response>(code)) { }
400 
405  http::status_code status_code() const { return _m_impl->status_code(); }
406 
414  void set_status_code(http::status_code code) const { _m_impl->set_status_code(code); }
415 
421  const http::reason_phrase & reason_phrase() const { return _m_impl->reason_phrase(); }
422 
428  void set_reason_phrase(const http::reason_phrase &reason) const { _m_impl->set_reason_phrase(reason); }
429 
437  http_headers &headers() { return _m_impl->headers(); }
438 
443  const http_headers &headers() const { return _m_impl->headers(); }
444 
455  utility::string_t to_string() const { return _m_impl->to_string(); }
456 
463  pplx::task<utility::string_t> extract_string(bool ignore_content_type = false) const
464  {
465  auto impl = _m_impl;
466  return pplx::create_task(_m_impl->_get_data_available()).then([impl, ignore_content_type](utility::size64_t) { return impl->extract_string(ignore_content_type); });
467  }
468 
475  pplx::task<utf8string> extract_utf8string(bool ignore_content_type = false) const
476  {
477  auto impl = _m_impl;
478  return pplx::create_task(_m_impl->_get_data_available()).then([impl, ignore_content_type](utility::size64_t) { return impl->extract_utf8string(ignore_content_type); });
479  }
480 
487  pplx::task<utf16string> extract_utf16string(bool ignore_content_type = false) const
488  {
489  auto impl = _m_impl;
490  return pplx::create_task(_m_impl->_get_data_available()).then([impl, ignore_content_type](utility::size64_t) { return impl->extract_utf16string(ignore_content_type); });
491  }
492 
499  pplx::task<json::value> extract_json(bool ignore_content_type = false) const
500  {
501  auto impl = _m_impl;
502  return pplx::create_task(_m_impl->_get_data_available()).then([impl, ignore_content_type](utility::size64_t) { return impl->_extract_json(ignore_content_type); });
503  }
504 
510  {
511  auto impl = _m_impl;
512  return pplx::create_task(_m_impl->_get_data_available()).then([impl](utility::size64_t) { return impl->_extract_vector(); });
513  }
514 
524  void set_body(utf8string &&body_text, const utf8string &content_type = utf8string("text/plain; charset=utf-8"))
525  {
526  const auto length = body_text.size();
527  _m_impl->set_body(concurrency::streams::bytestream::open_istream<std::string>(std::move(body_text)), length, content_type);
528  }
529 
539  void set_body(const utf8string &body_text, const utf8string &content_type = utf8string("text/plain; charset=utf-8"))
540  {
541  _m_impl->set_body(concurrency::streams::bytestream::open_istream<std::string>(body_text), body_text.size(), content_type);
542  }
543 
553  void set_body(const utf16string &body_text, utf16string content_type = ::utility::conversions::to_utf16string("text/plain"))
554  {
555  if (content_type.find(::utility::conversions::to_utf16string("charset=")) != content_type.npos)
556  {
557  throw std::invalid_argument("content_type can't contain a 'charset'.");
558  }
559 
560  auto utf8body = utility::conversions::utf16_to_utf8(body_text);
561  auto length = utf8body.size();
562  _m_impl->set_body(concurrency::streams::bytestream::open_istream<std::string>(
563  std::move(utf8body)),
564  length,
565  std::move(content_type.append(::utility::conversions::to_utf16string("; charset=utf-8"))));
566  }
567 
576  void set_body(const json::value &body_data)
577  {
578  auto body_text = utility::conversions::to_utf8string(body_data.serialize());
579  auto length = body_text.size();
580  set_body(concurrency::streams::bytestream::open_istream(std::move(body_text)), length, _XPLATSTR("application/json"));
581  }
582 
591  void set_body(std::vector<unsigned char> &&body_data)
592  {
593  auto length = body_data.size();
594  set_body(concurrency::streams::bytestream::open_istream(std::move(body_data)), length);
595  }
596 
605  void set_body(const std::vector<unsigned char> &body_data)
606  {
607  set_body(concurrency::streams::bytestream::open_istream(body_data), body_data.size());
608  }
609 
620  void set_body(const concurrency::streams::istream &stream, const utility::string_t &content_type = _XPLATSTR("application/octet-stream"))
621  {
622  _m_impl->set_body(stream, content_type);
623  }
624 
636  void set_body(const concurrency::streams::istream &stream, utility::size64_t content_length, const utility::string_t &content_type = _XPLATSTR("application/octet-stream"))
637  {
638  _m_impl->set_body(stream, content_length, content_type);
639  }
640 
651  concurrency::streams::istream body() const
652  {
653  return _m_impl->instream();
654  }
655 
661  {
662  http_response resp = *this;
663  return pplx::create_task(_m_impl->_get_data_available()).then([resp](utility::size64_t) mutable { return resp; });
664  }
665 
666  std::shared_ptr<http::details::_http_response> _get_impl() const { return _m_impl; }
667 
668  http::details::_http_server_context * _get_server_context() const { return _m_impl->_get_server_context(); }
669  void _set_server_context(std::unique_ptr<http::details::_http_server_context> server_context) { _m_impl->_set_server_context(std::move(server_context)); }
670 
671 private:
672 
673  std::shared_ptr<http::details::_http_response> _m_impl;
674 };
675 
676 namespace details {
680 class _http_request : public http::details::http_msg_base, public std::enable_shared_from_this<_http_request>
681 {
682 public:
683 
684  _ASYNCRTIMP _http_request(http::method mtd);
685 
686  _ASYNCRTIMP _http_request(std::unique_ptr<http::details::_http_server_context> server_context);
687 
688  virtual ~_http_request() {}
689 
690  http::method &method() { return m_method; }
691 
692  uri &request_uri() { return m_uri; }
693 
694  _ASYNCRTIMP uri absolute_uri() const;
695 
696  _ASYNCRTIMP uri relative_uri() const;
697 
698  _ASYNCRTIMP void set_request_uri(const uri&);
699 
700  const pplx::cancellation_token &cancellation_token() const { return m_cancellationToken; }
701 
702  void set_cancellation_token(const pplx::cancellation_token &token)
703  {
704  m_cancellationToken = token;
705  }
706 
707  _ASYNCRTIMP utility::string_t to_string() const;
708 
709  _ASYNCRTIMP pplx::task<void> reply(const http_response &response);
710 
711  pplx::task<http_response> get_response()
712  {
713  return pplx::task<http_response>(m_response);
714  }
715 
716  _ASYNCRTIMP pplx::task<void> _reply_if_not_already(http::status_code status);
717 
718  void set_response_stream(const concurrency::streams::ostream &stream)
719  {
720  m_response_stream = stream;
721  }
722 
723  void set_progress_handler(const progress_handler &handler)
724  {
725  m_progress_handler = std::make_shared<progress_handler>(handler);
726  }
727 
728  const concurrency::streams::ostream & _response_stream() const { return m_response_stream; }
729 
730  const std::shared_ptr<progress_handler> & _progress_handler() const { return m_progress_handler; }
731 
732  http::details::_http_server_context * _get_server_context() const { return m_server_context.get(); }
733 
734  void _set_server_context(std::unique_ptr<http::details::_http_server_context> server_context) { m_server_context = std::move(server_context); }
735 
736  void _set_listener_path(const utility::string_t &path) { m_listener_path = path; }
737 
738  void _set_base_uri(const http::uri &base_uri) { m_base_uri = base_uri; }
739 
740 private:
741 
742  // Actual initiates sending the response, without checking if a response has already been sent.
743  pplx::task<void> _reply_impl(http_response response);
744 
745  http::method m_method;
746 
747  // Tracks whether or not a response has already been started for this message.
748  pplx::details::atomic_long m_initiated_response;
749 
750  std::unique_ptr<http::details::_http_server_context> m_server_context;
751 
752  pplx::cancellation_token m_cancellationToken;
753 
754  http::uri m_base_uri;
755  http::uri m_uri;
756  utility::string_t m_listener_path;
757 
758  concurrency::streams::ostream m_response_stream;
759 
760  std::shared_ptr<progress_handler> m_progress_handler;
761 
763 };
764 
765 
766 } // namespace details
767 
772 {
773 public:
778  : _m_impl(std::make_shared<http::details::_http_request>(methods::GET)) {}
779 
785  : _m_impl(std::make_shared<http::details::_http_request>(std::move(mtd))) {}
786 
791 
796  const http::method &method() const { return _m_impl->method(); }
797 
802  void set_method(const http::method &method) const { _m_impl->method() = method; }
803 
808  const uri & request_uri() const { return _m_impl->request_uri(); }
809 
814  void set_request_uri(const uri& uri) { return _m_impl->set_request_uri(uri); }
815 
825  uri relative_uri() const { return _m_impl->relative_uri(); }
826 
834  uri absolute_uri() const { return _m_impl->absolute_uri(); }
835 
843  http_headers &headers() { return _m_impl->headers(); }
844 
852  const http_headers &headers() const { return _m_impl->headers(); }
853 
860  pplx::task<utility::string_t> extract_string(bool ignore_content_type = false)
861  {
862  auto impl = _m_impl;
863  return pplx::create_task(_m_impl->_get_data_available()).then([impl, ignore_content_type](utility::size64_t) { return impl->extract_string(ignore_content_type); });
864  }
865 
872  pplx::task<utf8string> extract_utf8string(bool ignore_content_type = false)
873  {
874  auto impl = _m_impl;
875  return pplx::create_task(_m_impl->_get_data_available()).then([impl, ignore_content_type](utility::size64_t) { return impl->extract_utf8string(ignore_content_type); });
876  }
877 
884  pplx::task<utf16string> extract_utf16string(bool ignore_content_type = false)
885  {
886  auto impl = _m_impl;
887  return pplx::create_task(_m_impl->_get_data_available()).then([impl, ignore_content_type](utility::size64_t) { return impl->extract_utf16string(ignore_content_type); });
888  }
889 
896  pplx::task<json::value> extract_json(bool ignore_content_type = false) const
897  {
898  auto impl = _m_impl;
899  return pplx::create_task(_m_impl->_get_data_available()).then([impl, ignore_content_type](utility::size64_t) { return impl->_extract_json(ignore_content_type); });
900  }
901 
907  {
908  auto impl = _m_impl;
909  return pplx::create_task(_m_impl->_get_data_available()).then([impl](utility::size64_t) { return impl->_extract_vector(); });
910  }
911 
921  void set_body(utf8string &&body_text, const utf8string &content_type = utf8string("text/plain; charset=utf-8"))
922  {
923  const auto length = body_text.size();
924  _m_impl->set_body(concurrency::streams::bytestream::open_istream<std::string>(std::move(body_text)), length, content_type);
925  }
926 
936  void set_body(const utf8string &body_text, const utf8string &content_type = utf8string("text/plain; charset=utf-8"))
937  {
938  _m_impl->set_body(concurrency::streams::bytestream::open_istream<std::string>(body_text), body_text.size(), content_type);
939  }
940 
951  void set_body(const utf16string &body_text, utf16string content_type = ::utility::conversions::to_utf16string("text/plain"))
952  {
953  if(content_type.find(::utility::conversions::to_utf16string("charset=")) != content_type.npos)
954  {
955  throw std::invalid_argument("content_type can't contain a 'charset'.");
956  }
957 
958  auto utf8body = utility::conversions::utf16_to_utf8(body_text);
959  auto length = utf8body.size();
960  _m_impl->set_body(concurrency::streams::bytestream::open_istream(
961  std::move(utf8body)),
962  length,
963  std::move(content_type.append(::utility::conversions::to_utf16string("; charset=utf-8"))));
964  }
965 
974  void set_body(const json::value &body_data)
975  {
976  auto body_text = utility::conversions::to_utf8string(body_data.serialize());
977  auto length = body_text.size();
978  _m_impl->set_body(concurrency::streams::bytestream::open_istream(std::move(body_text)), length, _XPLATSTR("application/json"));
979  }
980 
989  void set_body(std::vector<unsigned char> &&body_data)
990  {
991  auto length = body_data.size();
992  _m_impl->set_body(concurrency::streams::bytestream::open_istream(std::move(body_data)), length, _XPLATSTR("application/octet-stream"));
993  }
994 
1003  void set_body(const std::vector<unsigned char> &body_data)
1004  {
1005  set_body(concurrency::streams::bytestream::open_istream(body_data), body_data.size());
1006  }
1007 
1018  void set_body(const concurrency::streams::istream &stream, const utility::string_t &content_type = _XPLATSTR("application/octet-stream"))
1019  {
1020  _m_impl->set_body(stream, content_type);
1021  }
1022 
1034  void set_body(const concurrency::streams::istream &stream, utility::size64_t content_length, const utility::string_t &content_type = _XPLATSTR("application/octet-stream"))
1035  {
1036  _m_impl->set_body(stream, content_length, content_type);
1037  }
1038 
1049  concurrency::streams::istream body() const
1050  {
1051  return _m_impl->instream();
1052  }
1053 
1063  void set_response_stream(const concurrency::streams::ostream &stream)
1064  {
1065  return _m_impl->set_response_stream(stream);
1066  }
1067 
1096  void set_progress_handler(const progress_handler &handler)
1097  {
1098  return _m_impl->set_progress_handler(handler);
1099  }
1100 
1106  pplx::task<void> reply(const http_response &response) const { return _m_impl->reply(response); }
1107 
1113  pplx::task<void> reply(http::status_code status) const
1114  {
1115  return reply(http_response(status));
1116  }
1117 
1124  pplx::task<void> reply(http::status_code status, const json::value &body_data) const
1125  {
1126  http_response response(status);
1127  response.set_body(body_data);
1128  return reply(response);
1129  }
1130 
1139  // Callers of this function do NOT need to block waiting for the response to be
1142  pplx::task<void> reply(http::status_code status, utf8string &&body_data, const utf8string &content_type = "text/plain; charset=utf-8") const
1143  {
1144  http_response response(status);
1145  response.set_body(std::move(body_data), content_type);
1146  return reply(response);
1147  }
1148 
1158  // Callers of this function do NOT need to block waiting for the response to be
1161  pplx::task<void> reply(http::status_code status, const utf8string &body_data, const utf8string &content_type = "text/plain; charset=utf-8") const
1162  {
1163  http_response response(status);
1164  response.set_body(body_data, content_type);
1165  return reply(response);
1166  }
1167 
1177  // Callers of this function do NOT need to block waiting for the response to be
1180  pplx::task<void> reply(http::status_code status, const utf16string &body_data, const utf16string &content_type = ::utility::conversions::to_utf16string("text/plain")) const
1181  {
1182  http_response response(status);
1183  response.set_body(body_data, content_type);
1184  return reply(response);
1185  }
1186 
1194  pplx::task<void> reply(status_code status, const concurrency::streams::istream &body, const utility::string_t &content_type = _XPLATSTR("application/octet-stream")) const
1195  {
1196  http_response response(status);
1197  response.set_body(body, content_type);
1198  return reply(response);
1199  }
1200 
1209  pplx::task<void> reply(status_code status, const concurrency::streams::istream &body, utility::size64_t content_length, const utility::string_t &content_type = _XPLATSTR("application/octet-stream")) const
1210  {
1211  http_response response(status);
1212  response.set_body(body, content_length, content_type);
1213  return reply(response);
1214  }
1215 
1221  {
1222  http_request req = *this;
1223  return pplx::create_task(_m_impl->_get_data_available()).then([req](utility::size64_t) mutable { return req; });
1224  }
1225 
1231  {
1232  return _m_impl->get_response();
1233  }
1234 
1245  utility::string_t to_string() const { return _m_impl->to_string(); }
1246 
1250  pplx::task<void> _reply_if_not_already(status_code status) { return _m_impl->_reply_if_not_already(status); }
1251 
1255  http::details::_http_server_context * _get_server_context() const { return _m_impl->_get_server_context(); }
1256 
1260  static http_request _create_request(std::unique_ptr<http::details::_http_server_context> server_context) { return http_request(std::move(server_context)); }
1261  void _set_server_context(std::unique_ptr<http::details::_http_server_context> server_context) { _m_impl->_set_server_context(std::move(server_context)); }
1262 
1263  void _set_listener_path(const utility::string_t &path) { _m_impl->_set_listener_path(path); }
1264 
1265  const std::shared_ptr<http::details::_http_request> & _get_impl() const { return _m_impl; }
1266 
1267  void _set_cancellation_token(const pplx::cancellation_token &token)
1268  {
1269  _m_impl->set_cancellation_token(token);
1270  }
1271 
1272  const pplx::cancellation_token & _cancellation_token() const
1273  {
1274  return _m_impl->cancellation_token();
1275  }
1276 
1277  void _set_base_uri(const http::uri &base_uri)
1278  {
1279  _m_impl->_set_base_uri(base_uri);
1280  }
1281 
1282 private:
1283  friend class http::details::_http_request;
1284  friend class http::client::http_client;
1285 
1286  http_request(std::unique_ptr<http::details::_http_server_context> server_context) : _m_impl(std::make_shared<details::_http_request>(std::move(server_context))) {}
1287 
1288  std::shared_ptr<http::details::_http_request> _m_impl;
1289 };
1290 
1302 class http_pipeline_stage : public std::enable_shared_from_this<http_pipeline_stage>
1303 {
1304 public:
1305 
1306  virtual ~http_pipeline_stage()
1307  {
1308  }
1309 
1315  virtual pplx::task<http_response> propagate(http_request request) = 0;
1316 
1317 protected:
1318 
1320  {
1321  }
1322 
1327  const std::shared_ptr<http_pipeline_stage> & next_stage() const
1328  {
1329  return m_next_stage;
1330  }
1331 
1336  std::shared_ptr<http_pipeline_stage> current_stage()
1337  {
1338  return this->shared_from_this();
1339  }
1340 
1341 private:
1342  friend class http_pipeline;
1343 
1344  void set_next_stage(const std::shared_ptr<http_pipeline_stage> &next)
1345  {
1346  m_next_stage = next;
1347  }
1348 
1349  std::shared_ptr<http_pipeline_stage> m_next_stage;
1350 
1351  // No copy or assignment.
1352  http_pipeline_stage & operator=(const http_pipeline_stage &);
1353  http_pipeline_stage(const http_pipeline_stage &);
1354 };
1355 
1356 namespace details {
1357 
1359 {
1360 public:
1361  function_pipeline_wrapper(std::function<pplx::task<http_response>(http_request, std::shared_ptr<http::http_pipeline_stage>)> handler) : m_handler(handler)
1362  {
1363  }
1364 
1366  {
1367  return m_handler(request, next_stage());
1368  }
1369 private:
1370 
1371  std::function<pplx::task<http_response>(http_request, std::shared_ptr<http::http_pipeline_stage>)> m_handler;
1372 };
1373 
1374 } // namespace details
1375 
1380 {
1381 public:
1382 
1387  static std::shared_ptr<http_pipeline> create_pipeline(const std::shared_ptr<http_pipeline_stage> &last)
1388  {
1389  return std::shared_ptr<http_pipeline>(new http_pipeline(last));
1390  }
1391 
1397  {
1398  std::shared_ptr<http_pipeline_stage> first;
1399  {
1401  first = (m_stages.size() > 0) ? m_stages[0] : m_last_stage;
1402  }
1403  return first->propagate(request);
1404  }
1405 
1410  void append(const std::shared_ptr<http_pipeline_stage> &stage)
1411  {
1413 
1414  if (m_stages.size() > 0)
1415  {
1416  std::shared_ptr<http_pipeline_stage> penultimate = m_stages[m_stages.size()-1];
1417  penultimate->set_next_stage(stage);
1418  }
1419  stage->set_next_stage(m_last_stage);
1420 
1421  m_stages.push_back(stage);
1422  }
1423 
1428  void set_last_stage(const std::shared_ptr<http_pipeline_stage> &last)
1429  {
1430  m_last_stage = last;
1431  }
1432 
1437  const std::shared_ptr<http_pipeline_stage>& last_stage() const
1438  {
1439  return m_last_stage;
1440  }
1441 
1442 private:
1443 
1444  http_pipeline(const std::shared_ptr<http_pipeline_stage> &last) : m_last_stage(last)
1445  {
1446  }
1447 
1448  // The vector of pipeline stages.
1449  std::vector<std::shared_ptr<http_pipeline_stage>> m_stages;
1450 
1451  // The last stage is always set up by the client or listener and cannot
1452  // be changed. All application-defined stages are executed before the
1453  // last stage, which is typically a send or dispatch.
1454  std::shared_ptr<http_pipeline_stage> m_last_stage;
1455 
1457 
1458  // No copy or assignment.
1459  http_pipeline & operator=(const http_pipeline &);
1460  http_pipeline(const http_pipeline &);
1461 };
1462 
1463 }}
Predefined values for all of the standard HTTP 1.1 response status codes.
Definition: http_msg.h:82
const std::shared_ptr< http_pipeline_stage > & last_stage() const
Retrieves the last stage in this pipeline.
Definition: http_msg.h:1437
pplx::task< std::vector< unsigned char > > extract_vector() const
Extracts the body of the response message into a vector of bytes.
Definition: http_msg.h:509
A generic RAII wrapper for locks that implements the critical_section interface cpprest_synchronizati...
Definition: pplxlinux.h:264
Represents an HTTP error. This class holds an error message and an optional error code...
Definition: http_msg.h:130
const http::method & method() const
Get the method (GET/PUT/POST/DELETE) of the request message.
Definition: http_msg.h:796
pplx::task< http::http_response > content_ready() const
Signals the user (client) when all the data for this response message has been received.
Definition: http_msg.h:660
void set_request_uri(const uri &uri)
Set the underling URI of the request message.
Definition: http_msg.h:814
Represents HTTP headers, acts like a map.
Definition: http_headers.h:75
http_response()
Constructs a response with an empty status code, no headers, and no body.
Definition: http_msg.h:391
concurrency::streams::istream body() const
Produces a stream which the caller may use to retrieve data from an incoming request.
Definition: http_msg.h:1049
_ASYNCRTIMP std::string __cdecl utf16_to_utf8(const utf16string &w)
Converts a UTF-16 string to a UTF-8 string.
http::details::_http_server_context * _get_server_context() const
Gets the server context associated with this HTTP message.
Definition: http_msg.h:1255
const http_headers & headers() const
Gets a const reference to the headers of the response message.
Definition: http_msg.h:852
virtual _ASYNCRTIMP void _complete(utility::size64_t bodySize, const std::exception_ptr &exceptionPtr=std::exception_ptr())
Completes this message
pplx::task< utf8string > extract_utf8string(bool ignore_content_type=false) const
Extracts the body of the response message as a UTF-8 string value, checking that the content type is ...
Definition: http_msg.h:475
Represents an HTTP response.
Definition: http_msg.h:383
void set_progress_handler(const progress_handler &handler)
Defines a callback function that will be invoked for every chunk of data uploaded or downloaded as pa...
Definition: http_msg.h:1096
Common HTTP methods.
Definition: http_msg.h:67
_ASYNCRTIMP size_t _get_content_length()
Determine the content length
pplx::task< void > reply(http::status_code status, const utf16string &body_data, const utf16string &content_type=::utility::conversions::to_utf16string("text/plain")) const
Responds to this HTTP request with a string. Assumes the character encoding of the string is UTF-16 w...
Definition: http_msg.h:1180
HTTP client handler class, used to represent an HTTP pipeline stage.
Definition: http_msg.h:1302
A flexible, protocol independent URI implementation.
Definition: base_uri.h:151
pplx::task< json::value > extract_json(bool ignore_content_type=false) const
Extracts the body of the request message into a json value, checking that the content type is applica...
Definition: http_msg.h:896
http_exception(int errorCode, const utility::string_t &whatArg)
Creates an http_exception with from a error code using the current platform error category...
Definition: http_msg.h:165
~http_request()
Destructor frees any held resources.
Definition: http_msg.h:790
http_headers & headers()
Gets a reference to the headers of the response message.
Definition: http_msg.h:843
const concurrency::streams::ostream & outstream() const
Get the stream through which the message body could be written
Definition: http_msg.h:282
const std::error_code & error_code() const
Retrieves the underlying error code causing this exception.
Definition: http_msg.h:206
http_exception(const utility::string_t &whatArg)
Creates an http_exception with just a string message and no error code.
Definition: http_msg.h:138
void set_reason_phrase(const http::reason_phrase &reason) const
Sets the reason phrase of the response message. If no reason phrase is set it will default to the sta...
Definition: http_msg.h:428
pplx::task< utility::string_t > extract_string(bool ignore_content_type=false) const
Extracts the body of the response message as a string value, checking that the content type is a MIME...
Definition: http_msg.h:463
pplx::task< std::vector< unsigned char > > extract_vector() const
Extract the body of the response message into a vector of bytes. Extracting a vector can be done on ...
Definition: http_msg.h:906
void set_status_code(http::status_code code) const
Sets the status code of the response message.
Definition: http_msg.h:414
The web namespace contains functionality common to multiple protocols like HTTP and WebSockets...
Definition: base_uri.h:37
pplx::task< void > reply(status_code status, const concurrency::streams::istream &body, const utility::string_t &content_type=_XPLATSTR("application/octet-stream")) const
Responds to this HTTP request.
Definition: http_msg.h:1194
pplx::task_completion_event< utility::size64_t > m_data_available
The TCE is used to signal the availability of the message body.
Definition: http_msg.h:331
void set_body(utf8string &&body_text, const utf8string &content_type=utf8string("text/plain; charset=utf-8"))
Sets the body of the message to a textual string and set the "Content-Type" header. Assumes the character encoding of the string is UTF-8.
Definition: http_msg.h:524
virtual pplx::task< http_response > propagate(http_request request)=0
Runs this stage against the given request and passes onto the next stage.
const http_headers & headers() const
Gets a const reference to the headers of the response message.
Definition: http_msg.h:443
HTTP client class, used to maintain a connection to an HTTP service for an extended session...
Definition: http_client.h:383
pplx::task< void > reply(status_code status, const concurrency::streams::istream &body, utility::size64_t content_length, const utility::string_t &content_type=_XPLATSTR("application/octet-stream")) const
Responds to this HTTP request.
Definition: http_msg.h:1209
std::shared_ptr< http_pipeline_stage > current_stage()
Gets a shared pointer to this pipeline stage.
Definition: http_msg.h:1336
const http::reason_phrase & reason_phrase() const
Gets the reason phrase of the response message. If no reason phrase is set it will default to the sta...
Definition: http_msg.h:421
static std::shared_ptr< http_pipeline > create_pipeline(const std::shared_ptr< http_pipeline_stage > &last)
Create an http pipeline that consists of a linear chain of stages
Definition: http_msg.h:1387
void set_body(const std::vector< unsigned char > &body_data)
Sets the body of the message to the contents of a byte vector. If the 'Content-Type' header hasn't al...
Definition: http_msg.h:1003
utility::string_t to_string() const
Generates a string representation of the message, including the body when possible. Mainly this should be used for debugging purposes as it has to copy the message body and doesn't have excellent performance.
Definition: http_msg.h:1245
void set_body(const utf16string &body_text, utf16string content_type=::utility::conversions::to_utf16string("text/plain"))
Sets the body of the message to a textual string and set the "Content-Type" header. Assumes the character encoding of the string is UTF-16 will perform conversion to UTF-8.
Definition: http_msg.h:553
Base class for HTTP messages. This class is to store common functionality so it isn't duplicated on b...
Definition: http_msg.h:224
void set_body(const utf8string &body_text, const utf8string &content_type=utf8string("text/plain; charset=utf-8"))
Sets the body of the message to a textual string and set the "Content-Type" header. Assumes the character encoding of the string is UTF-8.
Definition: http_msg.h:936
pplx::task< void > reply(http::status_code status, utf8string &&body_data, const utf8string &content_type="text/plain; charset=utf-8") const
Definition: http_msg.h:1142
uri absolute_uri() const
Get an absolute URI with scheme, host, port, path, query, and fragment part of the request message...
Definition: http_msg.h:834
void set_body(const json::value &body_data)
Sets the body of the message to contain json value. If the 'Content-Type' header hasn't already been ...
Definition: http_msg.h:576
_ASYNCRTIMP utility::string_t serialize() const
Serializes the current JSON value to a C++ string.
void set_body(utf8string &&body_text, const utf8string &content_type=utf8string("text/plain; charset=utf-8"))
Sets the body of the message to a textual string and set the "Content-Type" header. Assumes the character encoding of the string is UTF-8.
Definition: http_msg.h:921
void set_method(const http::method &method) const
Get the method (GET/PUT/POST/DELETE) of the request message.
Definition: http_msg.h:802
void set_body(const utf8string &body_text, const utf8string &content_type=utf8string("text/plain; charset=utf-8"))
Sets the body of the message to a textual string and set the "Content-Type" header. Assumes the character encoding of the string is UTF-8.
Definition: http_msg.h:539
pplx::task< utf8string > extract_utf8string(bool ignore_content_type=false)
Extract the body of the request message as a UTF-8 string value, checking that the content type is a ...
Definition: http_msg.h:872
utility::string_t method
Predefined method strings for the standard HTTP methods mentioned in the HTTP 1.1 specification...
Definition: http_msg.h:62
Definition: http_msg.h:1379
pplx::task< utf16string > extract_utf16string(bool ignore_content_type=false)
Extract the body of the request message as a UTF-16 string value, checking that the content type is a...
Definition: http_msg.h:884
static http_request _create_request(std::unique_ptr< http::details::_http_server_context > server_context)
These are used for the initial creation of the HTTP request.
Definition: http_msg.h:1260
void append(const std::shared_ptr< http_pipeline_stage > &stage)
Adds an HTTP pipeline stage to the pipeline.
Definition: http_msg.h:1410
const std::shared_ptr< http_pipeline_stage > & next_stage() const
Gets the next stage in the pipeline.
Definition: http_msg.h:1327
const uri & request_uri() const
Get the underling URI of the request message.
Definition: http_msg.h:808
concurrency::streams::istream m_inStream
Stream to read the message body. By default this is an invalid stream. The user could set the instrea...
Definition: http_msg.h:317
_ASYNCRTIMP utf16string __cdecl to_utf16string(const std::string &value)
Converts to a UTF-16 from string.
void set_body(const concurrency::streams::istream &stream, utility::size64_t content_length, const utility::string_t &content_type=_XPLATSTR("application/octet-stream"))
Defines a stream that will be relied on to provide the body of the HTTP message when it is sent...
Definition: http_msg.h:636
void set_body(const concurrency::streams::istream &stream, const utility::string_t &content_type=_XPLATSTR("application/octet-stream"))
Defines a stream that will be relied on to provide the body of the HTTP message when it is sent...
Definition: http_msg.h:1018
utility::string_t parse_and_check_content_type(bool ignore_content_type, const std::function< bool(const utility::string_t &)> &check_content_type)
Helper function for extract functions. Parses the Content-Type header and check to make sure it match...
const char * what() const CPPREST_NOEXCEPT
Gets a string identifying the cause of the exception.
Definition: http_msg.h:197
Internal representation of an HTTP response.
Definition: http_msg.h:349
The Parallel Patterns Library (PPL) task class. A task object represents work that can be executed as...
Definition: pplxtasks.h:176
pplx::task< json::value > extract_json(bool ignore_content_type=false) const
Extracts the body of the response message into a json value, checking that the content type is applic...
Definition: http_msg.h:499
http_exception(int errorCode, const std::error_category &cat)
Creates an http_exception with from a error code and category. The message of the error code will be ...
Definition: http_msg.h:188
Definition: http_msg.h:108
The cancellation_token class represents the ability to determine whether some operation has been requ...
Definition: pplxcancellation_token.h:712
Recursive mutex
Definition: pplxlinux.h:196
concurrency::streams::istream body() const
Produces a stream which the caller may use to retrieve data from an incoming request.
Definition: http_msg.h:651
void set_body(const concurrency::streams::istream &stream, utility::size64_t content_length, const utility::string_t &content_type=_XPLATSTR("application/octet-stream"))
Defines a stream that will be relied on to provide the body of the HTTP message when it is sent...
Definition: http_msg.h:1034
pplx::task< http_response > propagate(http_request request)
Initiate an http request into the pipeline
Definition: http_msg.h:1396
void set_body(const concurrency::streams::istream &stream, const utility::string_t &content_type=_XPLATSTR("application/octet-stream"))
Defines a stream that will be relied on to provide the body of the HTTP message when it is sent...
Definition: http_msg.h:620
A JSON value represented as a C++ class.
Definition: json.h:83
void set_outstream(const concurrency::streams::ostream &outstream, bool is_default)
Set the stream through which the message body could be written
Definition: http_msg.h:277
void set_body(const utf16string &body_text, utf16string content_type=::utility::conversions::to_utf16string("text/plain"))
Sets the body of the message to a textual string and set the "Content-Type" header. Assumes the character encoding of the string is UTF-16 will perform conversion to UTF-8.
Definition: http_msg.h:951
pplx::task< http_request > content_ready() const
Signals the user (listener) when all the data for this request message has been received.
Definition: http_msg.h:1220
The Parallel Patterns Library (PPL) task class. A task object represents work that can be executed as...
Definition: pplxtasks.h:4173
http_request(http::method mtd)
Constructs a new HTTP request with the given request method.
Definition: http_msg.h:784
http::status_code status_code() const
Gets the status code of the response message.
Definition: http_msg.h:405
http_response(http::status_code code)
Constructs a response with given status code, no headers, and no body.
Definition: http_msg.h:398
http_exception(int errorCode)
Creates an http_exception with from a error code using the current platform error category...
Definition: http_msg.h:154
void set_body(const json::value &body_data)
Sets the body of the message to contain json value. If the 'Content-Type' header hasn't already been ...
Definition: http_msg.h:974
pplx::task< void > reply(http::status_code status, const utf8string &body_data, const utf8string &content_type="text/plain; charset=utf-8") const
Responds to this HTTP request with a string. Assumes the character encoding of the string is UTF-8...
Definition: http_msg.h:1161
void set_body(std::vector< unsigned char > &&body_data)
Sets the body of the message to the contents of a byte vector. If the 'Content-Type' header hasn't al...
Definition: http_msg.h:989
void set_body(std::vector< unsigned char > &&body_data)
Sets the body of the message to the contents of a byte vector. If the 'Content-Type' header hasn't al...
Definition: http_msg.h:591
Internal representation of an HTTP request message.
Definition: http_msg.h:680
http_request()
Constructs a new HTTP request with the 'GET' method.
Definition: http_msg.h:777
Represents an HTTP request.
Definition: http_msg.h:771
uri relative_uri() const
Gets a reference the URI path, query, and fragment part of this request message. This will be appende...
Definition: http_msg.h:825
virtual pplx::task< http_response > propagate(http_request request) override
Runs this stage against the given request and passes onto the next stage.
Definition: http_msg.h:1365
pplx::task< http_response > get_response() const
Gets a task representing the response that will eventually be sent.
Definition: http_msg.h:1230
utility::string_t to_string() const
Generates a string representation of the message, including the body when possible. Mainly this should be used for debugging purposes as it has to copy the message body and doesn't have excellent performance.
Definition: http_msg.h:455
pplx::task< void > reply(http::status_code status) const
Asynchronously responses to this HTTP request.
Definition: http_msg.h:1113
_ASYNCRTIMP void _prepare_to_receive_data()
Prepare the message with an output stream to receive network data
concurrency::streams::ostream m_outStream
stream to write the msg body By default this is an invalid stream. The user could set this on the res...
Definition: http_msg.h:325
Builder for constructing URIs incrementally.
Definition: uri_builder.h:40
const concurrency::streams::istream & instream() const
Get the stream through which the message body could be read
Definition: http_msg.h:272
void set_body(const std::vector< unsigned char > &body_data)
Sets the body of the message to the contents of a byte vector. If the 'Content-Type' header hasn't al...
Definition: http_msg.h:605
pplx::task< void > reply(http::status_code status, const json::value &body_data) const
Responds to this HTTP request.
Definition: http_msg.h:1124
void set_last_stage(const std::shared_ptr< http_pipeline_stage > &last)
Sets the last stage of the pipeline.
Definition: http_msg.h:1428
http_headers & headers()
Gets the headers of the response message.
Definition: http_msg.h:437
pplx::task< utility::string_t > extract_string(bool ignore_content_type=false)
Extract the body of the request message as a string value, checking that the content type is a MIME t...
Definition: http_msg.h:860
Base structure for associating internal server information with an HTTP request/response.
Definition: http_msg.h:338
_ASYNCRTIMP std::string __cdecl to_utf8string(std::string value)
Converts to a UTF-8 string.
Various utilities for string conversions and date and time manipulation.
Definition: asyncrt_utils.h:50
void set_response_stream(const concurrency::streams::ostream &stream)
Defines a stream that will be relied on to hold the body of the HTTP response message that results fr...
Definition: http_msg.h:1063
pplx::task< void > _reply_if_not_already(status_code status)
Sends a response if one has not already been sent.
Definition: http_msg.h:1250
pplx::task< utf16string > extract_utf16string(bool ignore_content_type=false) const
Extracts the body of the response message as a UTF-16 string value, checking that the content type is...
Definition: http_msg.h:487
pplx::task< void > reply(const http_response &response) const
Asynchronously responses to this HTTP request.
Definition: http_msg.h:1106
direction
Enumeration used to denote the direction of a message: a request with a body is an upload...
Definition: http_msg.h:99
Constants for the HTTP headers mentioned in RFC 2616.
Definition: http_msg.h:117
void set_instream(const concurrency::streams::istream &instream)
Set the stream through which the message body could be read
Definition: http_msg.h:267