RESTinio
http_server.hpp
Go to the documentation of this file.
1 /*
2  restinio
3 */
4 
5 /*!
6  HTTP-Server.
7 */
8 
9 #pragma once
10 
11 #include <restinio/exception.hpp>
12 #include <restinio/settings.hpp>
13 #include <restinio/request_handler.hpp>
14 #include <restinio/impl/acceptor.hpp>
15 #include <restinio/traits.hpp>
16 
17 #include <memory>
18 
19 namespace restinio
20 {
21 
22 //
23 // io_context_shared_ptr_t
24 //
26 
27 //
28 // io_context_holder_t
29 //
30 /*!
31  * \brief Helper class for holding shared pointer to io_context.
32  *
33  * It intended to be used as argument to http_server_t's constructor.
34  */
36 {
38 public :
39  io_context_holder_t( io_context_shared_ptr_t context )
40  : m_context( std::move(context) )
41  {}
42 
45  {
46  return std::move(m_context);
47  }
48 };
49 
50 //
51 // own_io_context
52 //
53 /*!
54  * \brief Function which tells that http_server should create and use
55  * its own instance of io_context.
56  *
57  * Usage example:
58  * \code
59  * restinio::http_server_t<> server(
60  * restinio::own_io_context(),
61  * restinio::server_settings_t<>()... );
62  * \endcode
63  */
66 {
67  return { std::make_shared< asio_ns::io_context >() };
68 }
69 
70 //
71 // external_io_context
72 //
73 /*!
74  * \brief Function which tells that http_server should use external
75  * instance of io_context and should not controll its lifetime.
76  *
77  * Usage example:
78  * \code
79  * asio::io_context ctx;
80  * ...
81  * restinio::http_server_t<> server(
82  * restinio::external_io_context(ctx),
83  * restinio::server_settings_t<>()...);
84  * \endcode
85  */
87 external_io_context( asio_ns::io_context & ctx )
88 {
89  return { std::shared_ptr< asio_ns::io_context >(
90  std::addressof(ctx),
91  // Empty deleter.
92  []( asio_ns::io_context * ){} )
93  };
94 }
95 
96 //
97 // http_server_t
98 //
99 
100 //! Class for http-server.
101 /*!
102  With the help of this class one can run a server.
103  Server can be started and stopped in sync or async way.
104 
105  Please note that it is responsibility of user to provide a working
106  context for http_server. It means that user must call
107  asio::io_context::run() on some work thread (or on several working
108  threads).
109 
110  Sync way for starting and stopping a http_server can be used only if
111  http_server_t::open_sync() and http_server_t::close_sync() methods
112  are called somewhere inside asio::io_context::run(). For example:
113  \code
114  // Create and initialize object.
115  restinio::http_server_t< my_traits_t > server{
116  restinio::own_io_context(),
117  [&]( auto & settings ){
118  //
119  settings
120  .port( args.port() )
121  // .set_more_params( ... )
122  .request_handler(
123  []( restinio::request_handle_t req ){
124  // Handle request.
125  } );
126  } };
127 
128  // Post initial action to asio event loop.
129  asio::post( server.io_context(),
130  [&] {
131  // Starting the server in a sync way.
132  server.open_sync();
133  } );
134 
135  // Running server.
136  server.io_context().run();
137  \endcode
138 
139  Async way for starting and stopping a http_server can be used if
140  http_server_t::open_async() and http_server_t::open_async() can be
141  called from any other thread. For example:
142  \code
143  asio::io_context io_ctx;
144  restinio::http_server_t< my_traits_t > server{
145  restinio::external_io_context(io_ctx),
146  [&]( auto & settings ) { ... } };
147 
148  // Launch thread on which server will work.
149  std::thread server_thread{ [&] {
150  io_ctx.run();
151  } };
152 
153  // Start server in async way. Actual start will be performed
154  // on the context of server_thread.
155  server.open_async(
156  // Ok callback. Nothing to do.
157  []{},
158  // Error callback. Rethrow an exception.
159  []( auto ex_ptr ) {
160  std::rethrow_exception( ex_ptr );
161  } );
162  ...
163  // Wait while server_thread finishes its work.
164  server_thread.join();
165  \endcode
166 */
167 template < typename Traits = default_traits_t >
169 {
173  using timer_manager_t = typename Traits::timer_manager_t;
175 
176  public:
177  /*!
178  * @brief An alias for Traits type.
179  *
180  * @since v.0.5.0
181  */
182  using traits_t = Traits;
183 
184  // This is not Copyable nor Moveable type.
185  http_server_t( const http_server_t & ) = delete;
186  http_server_t( http_server_t && ) = delete;
187 
188  template<typename D>
190  io_context_holder_t io_context,
191  basic_server_settings_t< D, Traits > && settings )
194  {
195  // Since v.0.5.1 the presence of custom connection state
196  // listener should be checked before the start of HTTP server.
198  // The presence of IP-blocker should also be checked.
200 
201  // Now we can continue preparation of HTTP server.
202 
204 
207 
208  auto conn_settings =
212  m_timer_manager );
213 
214  m_acceptor =
216  settings,
217  this->io_context(),
221  *( conn_settings->m_logger ) );
222  }
223 
224  template<
225  typename Configurator,
226  // Use SFINAE.
227  // This constructor must be called only if Configurator
228  // allows to call operator() with server_settings_t& arg.
229  typename = decltype(
231  *(static_cast<server_settings_t<Traits>*>(nullptr)))) >
233  io_context_holder_t io_context,
234  Configurator && configurator )
235  : http_server_t{
236  io_context,
239  {}
240 
241  //! It is allowed to inherit from http_server_t
242  virtual ~http_server_t()
243  {
244  // Ensure server is closed after destruction of http_server instance.
245  close_sync();
246  }
247 
248  //! Get io_context on which server runs.
249  asio_ns::io_context & io_context() noexcept { return *m_io_context; }
250 
251  //! Starts server in async way.
252  /*!
253  \note It is necessary to be sure that ioservice is running.
254  */
255  template <
256  typename Server_Open_Ok_CB,
257  typename Server_Open_Error_CB >
258  void
260  Server_Open_Ok_CB open_ok_cb,
261  Server_Open_Error_CB open_err_cb )
262  {
263  asio_ns::post(
265  [ this,
266  ok_cb = std::move( open_ok_cb ),
267  err_cb = std::move( open_err_cb ) ]{
268  try
269  {
270  open_sync();
272  }
273  catch( const std::exception & )
274  {
276  }
277  } );
278  }
279 
280  //! Start server.
281  /*!
282  If server was started successfully then function returns,
283  otherwise it throws.
284  */
285  void
287  {
289  {
291  m_acceptor->open();
293  }
294  }
295 
296  //! Closes server in async way.
297  /*!
298  \note It doesn't call io_context to stop
299  (\see stop_io_context()).
300  */
301  template <
302  typename Server_Close_Ok_CB,
303  typename Server_Close_Error_CB >
304  void
306  Server_Close_Ok_CB close_ok_cb,
307  Server_Close_Error_CB close_err_cb )
308  {
309  asio_ns::post(
311  [ this,
312  ok_cb = std::move( close_ok_cb ),
313  err_cb = std::move( close_err_cb ) ]{
314  try
315  {
316  close_sync();
318  }
319  catch( const std::exception & )
320  {
322  }
323  } );
324  }
325 
326  //! Stop server.
327  /*!
328  If server was stopped successfully then function returns,
329  otherwise it throws.
330  */
331  void
333  {
335  {
337  m_acceptor->close();
340  }
341  }
342 
343  private:
344  //! A wrapper for asio io_context where server is running.
346 
347  //! An optional user's cleanup functor.
349 
350  //! Acceptor for new connections.
352 
353  //! Timer manager object.
355 
356  //! State of server.
357  enum class running_state_t
358  {
359  not_running,
360  running,
361  };
362 
363  //! Server state.
365 
366  //! Call a cleanup functor if it is defined.
367  /*!
368  * \note
369  * Cleanup functor can be called only once. Next call to
370  * call_cleanup_functor() will do nothing.
371  *
372  * \attention
373  * Cleanup functor can't throw.
374  */
375  void
377  {
378  if( m_cleanup_functor )
379  {
381  fn();
382  }
383  }
384 
385  //! Call callback and terminate the application if callback throws.
386  template< typename Callback >
387  static void call_nothrow_cb( Callback && cb ) noexcept
388  {
389  cb();
390  }
391 };
392 
393 } /* namespace restinio */
Helper class for holding shared pointer to io_context.
Definition: http_server.hpp:35
http_server_t(io_context_holder_t io_context, Configurator &&configurator)
std::shared_ptr< acceptor_t > m_acceptor
Acceptor for new connections.
running_state_t m_running_state
Server state.
cleanup_functor_t m_cleanup_functor
An optional user&#39;s cleanup functor.
timer_manager_handle_t m_timer_manager
Timer manager object.
void open_async(Server_Open_Ok_CB open_ok_cb, Server_Open_Error_CB open_err_cb)
Starts server in async way.
io_context_shared_ptr_t m_context
Definition: http_server.hpp:37
io_context_holder_t own_io_context()
Function which tells that http_server should create and use its own instance of io_context.
Definition: http_server.hpp:65
http_server_t(const http_server_t &)=delete
void close_async(Server_Close_Ok_CB close_ok_cb, Server_Close_Error_CB close_err_cb)
Closes server in async way.
asio_ns::io_context & io_context() noexcept
Get io_context on which server runs.
io_context_shared_ptr_t m_io_context
A wrapper for asio io_context where server is running.
void open_sync()
Start server.
io_context_holder_t external_io_context(asio_ns::io_context &ctx)
Function which tells that http_server should use external instance of io_context and should not contr...
Definition: http_server.hpp:87
running_state_t
State of server.
void close_sync()
Stop server.
io_context_holder_t(io_context_shared_ptr_t context)
Definition: http_server.hpp:39
void call_cleanup_functor() noexcept
Call a cleanup functor if it is defined.
http_server_t(http_server_t &&)=delete
http_server_t(io_context_holder_t io_context, basic_server_settings_t< D, Traits > &&settings)
virtual ~http_server_t()
It is allowed to inherit from http_server_t.
static void call_nothrow_cb(Callback &&cb) noexcept
Call callback and terminate the application if callback throws.
io_context_shared_ptr_t giveaway_context()
Definition: http_server.hpp:44
std::enable_if< std::is_same< Parameter_Container, query_string_params_t >::value||std::is_same< Parameter_Container, router::route_params_t >::value, optional_t< Value_Type > >::type opt_value(const Parameter_Container &params, string_view_t key)
Gets the value of a parameter specified by key wrapped in optional_t<Value_Type> if parameter exists ...
Definition: value_or.hpp:64
Class for http-server.