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_server_httpsys.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: implementation of HTTP server API built on Windows HTTP Server APIs.
20 *
21 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
22 ****/
23 
24 #pragma once
25 
26 #if _WIN32_WINNT < _WIN32_WINNT_VISTA
27 #error "Error: http server APIs are not supported in XP"
28 #endif //_WIN32_WINNT < _WIN32_WINNT_VISTA
29 
30 // Windows Sockets are not code analysis clean.
31 #pragma warning(push)
32 #pragma warning(disable : 6386)
33 #include <http.h>
34 #pragma warning(pop)
35 
36 #include <atomic>
37 #include <mutex>
38 
39 #include "cpprest/details/http_server.h"
40 
41 namespace web
42 {
43 namespace http
44 {
45 namespace experimental
46 {
47 namespace details
48 {
49 
50 class http_windows_server;
51 struct windows_request_context;
52 
56 class http_overlapped : public OVERLAPPED
57 {
58 public:
59  void set_http_io_completion(std::function<void(DWORD, DWORD)> http_io_completion)
60  {
61  ZeroMemory(this, sizeof(OVERLAPPED));
62  m_http_io_completion = http_io_completion;
63  }
64 
68  static void CALLBACK io_completion_callback(
69  PTP_CALLBACK_INSTANCE instance,
70  PVOID context,
71  PVOID pOverlapped,
72  ULONG result,
73  ULONG_PTR numberOfBytesTransferred,
74  PTP_IO io)
75  {
76  CASABLANCA_UNREFERENCED_PARAMETER(io);
77  CASABLANCA_UNREFERENCED_PARAMETER(context);
78  CASABLANCA_UNREFERENCED_PARAMETER(instance);
79 
80  http_overlapped *p_http_overlapped = (http_overlapped *)pOverlapped;
81  p_http_overlapped->m_http_io_completion(result, (DWORD) numberOfBytesTransferred);
82  }
83 
84 private:
85  std::function<void(DWORD, DWORD)> m_http_io_completion;
86 };
87 
92 {
94  virtual ~windows_request_context();
95 
96  // Asynchronously starts processing the current request.
97  void async_process_request(HTTP_REQUEST_ID request_id, http::http_request msg, const unsigned long headers_size);
98 
99  // Dispatch request to the provided http_listener.
100  void dispatch_request_to_listener(_In_ web::http::experimental::listener::details::http_listener_impl *pListener);
101 
102  // Read in a portion of the request body.
103  void read_request_body_chunk();
104 
105  // Start processing the response.
106  void async_process_response();
107 
108  void transmit_body();
109 
110  // Read request headers io completion callback function .
111  void read_headers_io_completion(DWORD error_code, DWORD bytes_read);
112 
113  // Read request body io completion callback function.
114  void read_body_io_completion(DWORD error_code, DWORD bytes_read);
115 
116  // Send response io completion callback function .
117  void send_response_io_completion(DWORD error_code, DWORD bytes_read);
118 
119  // Send response body io completion callback function.
120  void send_response_body_io_completion(DWORD error_code, DWORD bytes_read);
121 
122  // Cancel request io completion callback function.
123  void cancel_request_io_completion(DWORD error_code, DWORD bytes_read);
124 
125  // TCE that indicates the completion of response
126  // Workaround for ppl task_completion_event bug.
127  std::mutex m_responseCompletedLock;
128  pplx::task_completion_event<void> m_response_completed;
129 
130  // Id of the currently processed request on this connection.
131  HTTP_REQUEST_ID m_request_id;
132 
133  bool m_sending_in_chunks;
134  bool m_transfer_encoding;
135 
136  size_t m_remaining_to_write;
137 
138  HTTP_REQUEST *m_request;
139  std::unique_ptr<unsigned char[]> m_request_buffer;
140 
141  std::unique_ptr<HTTP_UNKNOWN_HEADER []> m_headers;
142  std::vector<std::string> m_headers_buffer;
143 
144  http_overlapped m_overlapped;
145 
146  http_request m_msg;
147  http_response m_response;
148 
149  std::exception_ptr m_except_ptr;
150 private:
153 
154  // Sends entity body chunk.
155  void send_entity_body(_In_reads_(data_length) unsigned char * data, _In_ size_t data_length);
156 
157  // Cancels this request.
158  void cancel_request(std::exception_ptr except_ptr);
159 
160  std::vector<unsigned char> m_body_data;
161 };
162 
167 {
168 public:
169 
174 
179 
183  virtual pplx::task<void> start();
184 
189 
194 
198  virtual pplx::task<void> stop();
199 
205  virtual pplx::task<void> respond(http::http_response response);
206 
207 private:
208  friend struct details::windows_request_context;
209 
210  // Structure to hold each registered listener.
211  class listener_registration
212  {
213  public:
214  listener_registration(HTTP_URL_GROUP_ID urlGroupId)
215  : m_urlGroupId(urlGroupId)
216  {}
217 
218  // URL group id for this listener. Each listener needs it own URL group
219  // because configuration like timeouts, authentication, etc...
220  HTTP_URL_GROUP_ID m_urlGroupId;
221 
222  // Request handler lock to guard against removing a listener while in user code.
223  pplx::extensibility::reader_writer_lock_t m_requestHandlerLock;
224  };
225 
226  // Registered listeners
228  std::unordered_map<web::http::experimental::listener::details::http_listener_impl *, std::unique_ptr<listener_registration>> _M_registeredListeners;
229 
230  // HTTP Server API server session id.
231  HTTP_SERVER_SESSION_ID m_serverSessionId;
232 
233  // Tracks the number of outstanding requests being processed.
234  std::atomic<int> m_numOutstandingRequests;
235  pplx::extensibility::event_t m_zeroOutstandingRequests;
236 
237  // Handle to HTTP Server API request queue.
238  HANDLE m_hRequestQueue;
239 
240  // Threadpool I/O structure for overlapped I/O.
241  TP_IO * m_threadpool_io;
242 
243  // Task which actually handles receiving requests from HTTP Server API request queue.
244  pplx::task<void> m_receivingTask;
245  void receive_requests();
246 };
247 
248 } // namespace details;
249 } // namespace experimental
250 }} // namespace web::http
The task_completion_event class allows you to delay the execution of a task until a condition is sati...
Definition: pplxtasks.h:2934
Represents an HTTP response.
Definition: http_msg.h:383
The web namespace contains functionality common to multiple protocols like HTTP and WebSockets...
Definition: base_uri.h:37
Class to implement HTTP server API on Windows.
Definition: http_server_httpsys.h:166
static void CALLBACK io_completion_callback(PTP_CALLBACK_INSTANCE instance, PVOID context, PVOID pOverlapped, ULONG result, ULONG_PTR numberOfBytesTransferred, PTP_IO io)
Callback for all I/O completions.
Definition: http_server_httpsys.h:68
virtual pplx::task< void > start()
Start listening for incoming requests.
virtual pplx::task< void > stop()
Stop processing and listening for incoming requests.
virtual pplx::task< void > respond(http::http_response response)
Asynchronously sends the specified http response.
virtual pplx::task< void > register_listener(_In_ web::http::experimental::listener::details::http_listener_impl *pListener)
Registers an http listener.
virtual pplx::task< void > unregister_listener(_In_ web::http::experimental::listener::details::http_listener_impl *pListener)
Unregisters an http listener.
The Parallel Patterns Library (PPL) task class. A task object represents work that can be executed as...
Definition: pplxtasks.h:4173
Manual reset event
Definition: pplxlinux.h:84
http_windows_server()
Constructs a http_windows_server.
Represents an HTTP request.
Definition: http_msg.h:771
Reader writer lock
Definition: pplxlinux.h:140
Internal class for pointer to implementation design pattern.
Definition: http_listener.h:171
Base structure for associating internal server information with an HTTP request/response.
Definition: http_msg.h:338
Interface http listeners interact with for receiving and responding to http requests.
Definition: http_server.h:42
Class used to wrap OVERLAPPED I/O with any HTTP I/O.
Definition: http_server_httpsys.h:56
Context for http request through Windows HTTP Server API.
Definition: http_server_httpsys.h:91