/* * Copyright (c) 2017-2023 zhllxt * * author : zhllxt * email : 37792738@qq.com * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ #ifndef __ASIO2_HTTP_SERVER_HPP__ #define __ASIO2_HTTP_SERVER_HPP__ #if defined(_MSC_VER) && (_MSC_VER >= 1200) #pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include #include #include namespace asio2::detail { ASIO2_CLASS_FORWARD_DECLARE_BASE; ASIO2_CLASS_FORWARD_DECLARE_TCP_BASE; ASIO2_CLASS_FORWARD_DECLARE_TCP_SERVER; template class http_server_impl_t : public tcp_server_impl_t , public http_router_t { ASIO2_CLASS_FRIEND_DECLARE_BASE; ASIO2_CLASS_FRIEND_DECLARE_TCP_BASE; ASIO2_CLASS_FRIEND_DECLARE_TCP_SERVER; public: using super = tcp_server_impl_t ; using self = http_server_impl_t; using session_type = session_t; public: /** * @brief constructor */ template explicit http_server_impl_t(Args&&... args) : super(std::forward(args)...) { } /** * @brief destructor */ ~http_server_impl_t() { this->stop(); } /** * @brief start the server * @param host - A string identifying a location. May be a descriptive name or * a numeric address string. * @param service - A string identifying the requested service. This may be a * descriptive name or a numeric string corresponding to a port number. */ template inline bool start(String&& host, StrOrInt&& service, Args&&... args) { return this->derived()._do_start(std::forward(host), std::forward(service), ecs_helper::make_ecs('0', std::forward(args)...)); } public: /** * @brief bind recv listener * @param fun - a user defined callback function * Function signature : void(std::shared_ptr& session_ptr, * http::web_request& req, http::web_response& rep) * or : void(http::web_request& req, http::web_response& rep) */ template inline derived_t & bind_recv(F&& fun, C&&... obj) { if constexpr (detail::is_template_callable_v&, http::web_request&, http::web_response&>) { this->is_arg0_session_ = true; this->listener_.bind(event_type::recv, observer_t&, http::web_request&, http::web_response&>(std::forward(fun), std::forward(obj)...)); } else { this->is_arg0_session_ = false; this->listener_.bind(event_type::recv, observer_t< http::web_request&, http::web_response&>(std::forward(fun), std::forward(obj)...)); } return (this->derived()); } /** * @brief bind websocket upgrade listener * @param fun - a user defined callback function * Function signature : void(std::shared_ptr& session_ptr) */ template inline derived_t & bind_upgrade(F&& fun, C&&... obj) { this->listener_.bind(event_type::upgrade, observer_t&> (std::forward(fun), std::forward(obj)...)); return (this->derived()); } protected: template inline std::shared_ptr _make_session(Args&&... args) { return super::_make_session(std::forward(args)..., *this, this->root_directory_, this->is_arg0_session_, this->support_websocket_); } inline void _handle_stop(const error_code& ec, std::shared_ptr this_ptr) { // can not use std::move(this_ptr), beacuse after handle stop with std::move(this_ptr), // this object maybe destroyed, then call "this" will crash. super::_handle_stop(ec, this_ptr); this->derived().dispatch([this]() mutable { // clear the http cache this->http_cache_.clear(); }); } protected: bool is_arg0_session_ = false; }; } namespace asio2 { template using http_server_impl_t = detail::http_server_impl_t; template class http_server_t : public detail::http_server_impl_t, session_t> { public: using detail::http_server_impl_t, session_t>::http_server_impl_t; }; using http_server = http_server_t; } #if defined(ASIO2_INCLUDE_RATE_LIMIT) #include namespace asio2 { template class http_rate_server_t : public asio2::http_server_impl_t, session_t> { public: using asio2::http_server_impl_t, session_t>::http_server_impl_t; }; using http_rate_server = http_rate_server_t; } #endif #include #endif // !__ASIO2_HTTP_SERVER_HPP__