http_server.hpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /*
  2. * Copyright (c) 2017-2023 zhllxt
  3. *
  4. * author : zhllxt
  5. * email : 37792738@qq.com
  6. *
  7. * Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. */
  10. #ifndef __ASIO2_HTTP_SERVER_HPP__
  11. #define __ASIO2_HTTP_SERVER_HPP__
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. #pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <asio2/base/detail/push_options.hpp>
  16. #include <asio2/tcp/tcp_server.hpp>
  17. #include <asio2/http/http_session.hpp>
  18. namespace asio2::detail
  19. {
  20. ASIO2_CLASS_FORWARD_DECLARE_BASE;
  21. ASIO2_CLASS_FORWARD_DECLARE_TCP_BASE;
  22. ASIO2_CLASS_FORWARD_DECLARE_TCP_SERVER;
  23. template<class derived_t, class session_t>
  24. class http_server_impl_t
  25. : public tcp_server_impl_t<derived_t, session_t>
  26. , public http_router_t <session_t, typename session_t::args_type>
  27. {
  28. ASIO2_CLASS_FRIEND_DECLARE_BASE;
  29. ASIO2_CLASS_FRIEND_DECLARE_TCP_BASE;
  30. ASIO2_CLASS_FRIEND_DECLARE_TCP_SERVER;
  31. public:
  32. using super = tcp_server_impl_t <derived_t, session_t>;
  33. using self = http_server_impl_t<derived_t, session_t>;
  34. using session_type = session_t;
  35. public:
  36. /**
  37. * @brief constructor
  38. */
  39. template<class... Args>
  40. explicit http_server_impl_t(Args&&... args)
  41. : super(std::forward<Args>(args)...)
  42. {
  43. }
  44. /**
  45. * @brief destructor
  46. */
  47. ~http_server_impl_t()
  48. {
  49. this->stop();
  50. }
  51. /**
  52. * @brief start the server
  53. * @param host - A string identifying a location. May be a descriptive name or
  54. * a numeric address string.
  55. * @param service - A string identifying the requested service. This may be a
  56. * descriptive name or a numeric string corresponding to a port number.
  57. */
  58. template<typename String, typename StrOrInt, typename... Args>
  59. inline bool start(String&& host, StrOrInt&& service, Args&&... args)
  60. {
  61. return this->derived()._do_start(std::forward<String>(host), std::forward<StrOrInt>(service),
  62. ecs_helper::make_ecs('0', std::forward<Args>(args)...));
  63. }
  64. public:
  65. /**
  66. * @brief bind recv listener
  67. * @param fun - a user defined callback function
  68. * Function signature : void(std::shared_ptr<asio2::http_session>& session_ptr,
  69. * http::web_request& req, http::web_response& rep)
  70. * or : void(http::web_request& req, http::web_response& rep)
  71. */
  72. template<class F, class ...C>
  73. inline derived_t & bind_recv(F&& fun, C&&... obj)
  74. {
  75. if constexpr (detail::is_template_callable_v<F,
  76. std::shared_ptr<session_t>&, http::web_request&, http::web_response&>)
  77. {
  78. this->is_arg0_session_ = true;
  79. this->listener_.bind(event_type::recv, observer_t<std::shared_ptr<session_t>&,
  80. http::web_request&, http::web_response&>(std::forward<F>(fun), std::forward<C>(obj)...));
  81. }
  82. else
  83. {
  84. this->is_arg0_session_ = false;
  85. this->listener_.bind(event_type::recv, observer_t<
  86. http::web_request&, http::web_response&>(std::forward<F>(fun), std::forward<C>(obj)...));
  87. }
  88. return (this->derived());
  89. }
  90. /**
  91. * @brief bind websocket upgrade listener
  92. * @param fun - a user defined callback function
  93. * Function signature : void(std::shared_ptr<asio2::http_session>& session_ptr)
  94. */
  95. template<class F, class ...C>
  96. inline derived_t & bind_upgrade(F&& fun, C&&... obj)
  97. {
  98. this->listener_.bind(event_type::upgrade, observer_t<std::shared_ptr<session_t>&>
  99. (std::forward<F>(fun), std::forward<C>(obj)...));
  100. return (this->derived());
  101. }
  102. protected:
  103. template<typename... Args>
  104. inline std::shared_ptr<session_t> _make_session(Args&&... args)
  105. {
  106. return super::_make_session(std::forward<Args>(args)..., *this,
  107. this->root_directory_, this->is_arg0_session_, this->support_websocket_);
  108. }
  109. inline void _handle_stop(const error_code& ec, std::shared_ptr<derived_t> this_ptr)
  110. {
  111. // can not use std::move(this_ptr), beacuse after handle stop with std::move(this_ptr),
  112. // this object maybe destroyed, then call "this" will crash.
  113. super::_handle_stop(ec, this_ptr);
  114. this->derived().dispatch([this]() mutable
  115. {
  116. // clear the http cache
  117. this->http_cache_.clear();
  118. });
  119. }
  120. protected:
  121. bool is_arg0_session_ = false;
  122. };
  123. }
  124. namespace asio2
  125. {
  126. template<class derived_t, class session_t>
  127. using http_server_impl_t = detail::http_server_impl_t<derived_t, session_t>;
  128. template<class session_t>
  129. class http_server_t : public detail::http_server_impl_t<http_server_t<session_t>, session_t>
  130. {
  131. public:
  132. using detail::http_server_impl_t<http_server_t<session_t>, session_t>::http_server_impl_t;
  133. };
  134. using http_server = http_server_t<http_session>;
  135. }
  136. #if defined(ASIO2_INCLUDE_RATE_LIMIT)
  137. #include <asio2/tcp/tcp_stream.hpp>
  138. namespace asio2
  139. {
  140. template<class session_t>
  141. class http_rate_server_t : public asio2::http_server_impl_t<http_rate_server_t<session_t>, session_t>
  142. {
  143. public:
  144. using asio2::http_server_impl_t<http_rate_server_t<session_t>, session_t>::http_server_impl_t;
  145. };
  146. using http_rate_server = http_rate_server_t<http_rate_session>;
  147. }
  148. #endif
  149. #include <asio2/base/detail/pop_options.hpp>
  150. #endif // !__ASIO2_HTTP_SERVER_HPP__