2016-09-21 14:11:06 +00:00
# pragma once
# include <chrono>
# include <string>
# include <functional>
# include <memory>
# include <future>
# include <cstdint>
# include <type_traits>
# include <thread>
2017-12-24 15:40:39 +00:00
# include <condition_variable>
2016-09-21 14:11:06 +00:00
2021-07-03 20:02:32 +00:00
# include "crow/version.h"
2016-09-21 14:11:06 +00:00
# include "crow/settings.h"
# include "crow/logging.h"
# include "crow/utility.h"
# include "crow/routing.h"
# include "crow/middleware_context.h"
# include "crow/http_request.h"
# include "crow/http_server.h"
2021-11-19 17:42:25 +00:00
# include "crow/task_timer.h"
2022-05-20 11:14:55 +00:00
# include "crow/websocket.h"
2021-06-03 14:12:20 +00:00
# ifdef CROW_ENABLE_COMPRESSION
2021-01-02 19:12:04 +00:00
# include "crow/compression.h"
2021-06-03 14:12:20 +00:00
# endif
2016-09-21 14:11:06 +00:00
# ifdef CROW_MSVC_WORKAROUND
# define CROW_ROUTE(app, url) app.route_dynamic(url)
2021-07-28 19:31:08 +00:00
# define CROW_BP_ROUTE(blueprint, url) blueprint.new_rule_dynamic(url)
2016-09-21 14:11:06 +00:00
# else
2022-07-23 21:01:49 +00:00
# define CROW_ROUTE(app, url) app.template route<crow::black_magic::get_parameter_tag(url)>(url)
2021-07-28 19:31:08 +00:00
# define CROW_BP_ROUTE(blueprint, url) blueprint.new_rule_tagged<crow::black_magic::get_parameter_tag(url)>(url)
2022-11-02 21:38:12 +00:00
# define CROW_WEBSOCKET_ROUTE(app, url) app.route<crow::black_magic::get_parameter_tag(url)>(url).websocket<std::remove_reference<decltype(app)>::type>(&app)
2022-07-23 21:01:49 +00:00
# define CROW_MIDDLEWARES(app, ...) template middlewares<typename std::remove_reference<decltype(app)>::type, __VA_ARGS__>()
2016-09-21 14:11:06 +00:00
# endif
2021-04-12 07:41:55 +00:00
# define CROW_CATCHALL_ROUTE(app) app.catchall_route()
2021-07-28 19:31:08 +00:00
# define CROW_BP_CATCHALL_ROUTE(blueprint) blueprint.catchall_rule()
2016-09-21 14:11:06 +00:00
namespace crow
{
# ifdef CROW_ENABLE_SSL
2022-06-06 14:38:46 +00:00
using ssl_context_t = asio : : ssl : : context ;
2016-09-21 14:11:06 +00:00
# endif
2021-11-25 11:45:38 +00:00
/// The main server application
2021-12-03 03:39:23 +00:00
2020-10-22 01:13:57 +00:00
///
/// Use `SimpleApp` or `App<Middleware1, Middleware2, etc...>`
2021-11-25 11:45:38 +00:00
template < typename . . . Middlewares >
2016-09-21 14:11:06 +00:00
class Crow
{
public :
2021-11-25 11:45:38 +00:00
/// This crow application
2016-09-21 14:11:06 +00:00
using self_t = Crow ;
2021-11-25 11:45:38 +00:00
/// The HTTP server
2016-09-21 14:11:06 +00:00
using server_t = Server < Crow , SocketAdaptor , Middlewares . . . > ;
2021-08-29 17:12:46 +00:00
# ifdef CROW_ENABLE_SSL
2021-11-25 11:45:38 +00:00
/// An HTTP server that runs on SSL with an SSLAdaptor
2016-09-21 14:11:06 +00:00
using ssl_server_t = Server < Crow , SSLAdaptor , Middlewares . . . > ;
# endif
Crow ( )
2021-11-27 12:28:50 +00:00
{ }
2020-10-21 13:06:49 +00:00
2022-04-13 17:49:22 +00:00
/// Construct Crow with a subset of middleware
template < typename . . . Ts >
Crow ( Ts & & . . . ts ) :
middlewares_ ( make_middleware_tuple ( std : : forward < Ts > ( ts ) . . . ) )
{ }
2021-11-25 11:45:38 +00:00
/// Process an Upgrade request
2021-12-03 03:39:23 +00:00
2020-10-22 01:13:57 +00:00
///
2022-04-27 02:58:53 +00:00
/// Currently used to upgrade an HTTP connection to a WebSocket connection
2021-11-25 11:45:38 +00:00
template < typename Adaptor >
2016-09-21 14:11:06 +00:00
void handle_upgrade ( const request & req , response & res , Adaptor & & adaptor )
{
router_ . handle_upgrade ( req , res , adaptor ) ;
}
2022-07-18 03:33:56 +00:00
/// Process only the method and URL of a request and provide a route (or an error response)
std : : unique_ptr < routing_handle_result > handle_initial ( request & req , response & res )
2016-09-21 14:11:06 +00:00
{
2022-07-18 03:33:56 +00:00
return router_ . handle_initial ( req , res ) ;
}
/// Process the fully parsed request and generate a response for it
void handle ( request & req , response & res , std : : unique_ptr < routing_handle_result > & found )
{
router_ . handle < self_t > ( req , res , * found ) ;
}
/// Process a fully parsed request from start to finish (primarily used for debugging)
void handle_full ( request & req , response & res )
{
auto found = handle_initial ( req , res ) ;
2022-07-20 20:03:42 +00:00
if ( found - > rule_index )
2022-07-18 03:33:56 +00:00
handle ( req , res , found ) ;
2016-09-21 14:11:06 +00:00
}
2021-11-25 11:45:38 +00:00
/// Create a dynamic route using a rule (**Use CROW_ROUTE instead**)
2016-09-21 14:11:06 +00:00
DynamicRule & route_dynamic ( std : : string & & rule )
{
return router_ . new_rule_dynamic ( std : : move ( rule ) ) ;
}
2020-10-22 01:13:57 +00:00
///Create a route using a rule (**Use CROW_ROUTE instead**)
2021-11-25 11:45:38 +00:00
template < uint64_t Tag >
2021-11-25 14:14:45 +00:00
# ifdef CROW_GCC83_WORKAROUND
2021-11-23 15:00:14 +00:00
auto & route ( std : : string & & rule )
# else
2016-09-21 14:11:06 +00:00
auto route ( std : : string & & rule )
2021-12-04 11:32:32 +00:00
# endif
# if defined CROW_CAN_USE_CPP17 && !defined CROW_GCC83_WORKAROUND
2021-11-25 11:45:38 +00:00
- > typename std : : invoke_result < decltype ( & Router : : new_rule_tagged < Tag > ) , Router , std : : string & & > : : type
2021-12-04 11:32:32 +00:00
# elif !defined CROW_GCC83_WORKAROUND
2021-11-25 11:45:38 +00:00
- > typename std : : result_of < decltype ( & Router : : new_rule_tagged < Tag > ) ( Router , std : : string & & ) > : : type
2021-10-31 18:19:44 +00:00
# endif
2021-07-27 07:52:49 +00:00
{
2016-09-21 14:11:06 +00:00
return router_ . new_rule_tagged < Tag > ( std : : move ( rule ) ) ;
}
2021-11-25 11:45:38 +00:00
/// Create a route for any requests without a proper route (**Use CROW_CATCHALL_ROUTE instead**)
2021-04-12 07:41:55 +00:00
CatchallRule & catchall_route ( )
2021-04-12 05:25:09 +00:00
{
return router_ . catchall_rule ( ) ;
}
2022-05-15 00:51:51 +00:00
/// Set the default max payload size for websockets
self_t & websocket_max_payload ( uint64_t max_payload )
{
max_payload_ = max_payload ;
2022-05-16 16:14:51 +00:00
return * this ;
2022-05-15 00:51:51 +00:00
}
2022-05-15 00:58:53 +00:00
/// Get the default max payload size for websockets
2022-05-15 00:51:51 +00:00
uint64_t websocket_max_payload ( )
{
return max_payload_ ;
}
2020-12-19 07:15:57 +00:00
self_t & signal_clear ( )
{
signals_ . clear ( ) ;
return * this ;
}
self_t & signal_add ( int signal_number )
{
signals_ . push_back ( signal_number ) ;
return * this ;
}
2022-05-14 22:15:39 +00:00
std : : vector < int > signals ( )
{
return signals_ ;
}
2021-11-25 11:45:38 +00:00
/// Set the port that Crow will handle requests on
2016-09-21 14:11:06 +00:00
self_t & port ( std : : uint16_t port )
{
port_ = port ;
return * this ;
}
2022-03-23 22:55:46 +00:00
/// Get the port that Crow will handle requests on
2021-11-14 12:04:19 +00:00
std : : uint16_t port ( )
{
return port_ ;
}
2021-11-25 11:45:38 +00:00
/// Set the connection timeout in seconds (default is 5)
2020-10-21 13:06:49 +00:00
self_t & timeout ( std : : uint8_t timeout )
{
2021-11-19 17:42:25 +00:00
timeout_ = timeout ;
2020-10-21 13:06:49 +00:00
return * this ;
}
2021-11-25 11:45:38 +00:00
/// Set the server name
2020-12-03 01:15:05 +00:00
self_t & server_name ( std : : string server_name )
{
server_name_ = server_name ;
return * this ;
}
2021-11-25 11:45:38 +00:00
/// The IP address that Crow will handle requests on (default is 0.0.0.0)
2016-09-21 14:11:06 +00:00
self_t & bindaddr ( std : : string bindaddr )
{
bindaddr_ = bindaddr ;
return * this ;
}
2023-02-08 15:33:48 +00:00
/// Get the address that Crow will handle requests on
std : : string bindaddr ( )
{
return bindaddr_ ;
}
2016-09-21 14:11:06 +00:00
2021-11-25 11:45:38 +00:00
/// Run the server on multiple threads using all available threads
2016-09-21 14:11:06 +00:00
self_t & multithreaded ( )
{
return concurrency ( std : : thread : : hardware_concurrency ( ) ) ;
}
2021-11-25 11:45:38 +00:00
/// Run the server on multiple threads using a specific number
2016-09-21 14:11:06 +00:00
self_t & concurrency ( std : : uint16_t concurrency )
{
2021-12-23 02:39:39 +00:00
if ( concurrency < 2 ) // Crow can have a minimum of 2 threads running
2021-12-20 08:04:55 +00:00
concurrency = 2 ;
2016-09-21 14:11:06 +00:00
concurrency_ = concurrency ;
return * this ;
}
2023-02-08 15:33:48 +00:00
/// Get the number of threads that server is using
std : : uint16_t concurrency ( )
{
return concurrency_ ;
}
2016-09-21 14:11:06 +00:00
2021-11-25 11:45:38 +00:00
/// Set the server's log level
2021-12-03 03:39:23 +00:00
2020-10-22 01:13:57 +00:00
///
2020-11-04 03:21:52 +00:00
/// Possible values are:<br>
/// crow::LogLevel::Debug (0)<br>
/// crow::LogLevel::Info (1)<br>
/// crow::LogLevel::Warning (2)<br>
/// crow::LogLevel::Error (3)<br>
/// crow::LogLevel::Critical (4)<br>
2021-07-05 09:14:31 +00:00
self_t & loglevel ( LogLevel level )
2020-10-22 01:13:57 +00:00
{
crow : : logger : : setLogLevel ( level ) ;
return * this ;
}
2022-03-23 22:55:46 +00:00
/// Set the response body size (in bytes) beyond which Crow automatically streams responses (Default is 1MiB)
2022-03-18 10:55:27 +00:00
2021-10-12 12:35:08 +00:00
///
/// Any streamed response is unaffected by Crow's timer, and therefore won't timeout before a response is fully sent.
self_t & stream_threshold ( size_t threshold )
{
res_stream_threshold_ = threshold ;
return * this ;
}
2022-03-23 22:55:46 +00:00
/// Get the response body size (in bytes) beyond which Crow automatically streams responses
2021-10-12 12:35:08 +00:00
size_t & stream_threshold ( )
{
return res_stream_threshold_ ;
}
2021-07-05 09:14:31 +00:00
self_t & register_blueprint ( Blueprint & blueprint )
{
2021-07-27 07:52:49 +00:00
router_ . register_blueprint ( blueprint ) ;
2021-07-05 09:14:31 +00:00
return * this ;
}
2021-11-25 11:45:38 +00:00
/// Set a custom duration and function to run on every tick
template < typename Duration , typename Func >
self_t & tick ( Duration d , Func f )
{
2020-10-22 01:13:57 +00:00
tick_interval_ = std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( d ) ;
tick_function_ = f ;
return * this ;
}
2021-06-03 14:12:20 +00:00
# ifdef CROW_ENABLE_COMPRESSION
2021-01-02 19:12:04 +00:00
self_t & use_compression ( compression : : algorithm algorithm )
{
comp_algorithm_ = algorithm ;
2021-08-29 17:54:57 +00:00
compression_used_ = true ;
2021-01-02 19:12:04 +00:00
return * this ;
}
compression : : algorithm compression_algorithm ( )
{
return comp_algorithm_ ;
}
2021-08-29 17:54:57 +00:00
bool compression_used ( ) const
{
return compression_used_ ;
}
2021-06-03 14:12:20 +00:00
# endif
2021-11-25 11:45:38 +00:00
/// A wrapper for `validate()` in the router
2021-12-03 03:39:23 +00:00
2020-10-22 01:13:57 +00:00
///
2021-11-25 11:45:38 +00:00
/// Go through the rules, upgrade them if possible, and add them to the list of rules
2016-09-21 14:11:06 +00:00
void validate ( )
{
2021-07-28 19:31:08 +00:00
if ( ! validated_ )
{
2017-12-24 15:40:39 +00:00
2020-11-10 00:47:30 +00:00
# ifndef CROW_DISABLE_STATIC_DIR
2022-07-23 13:40:01 +00:00
// stat on windows doesn't care whether '/' or '\' is being used. on Linux however, using '\' doesn't work. therefore every instance of '\' gets replaced with '/' then a check is done to make sure the directory ends with '/'.
std : : string static_dir_ ( CROW_STATIC_DIRECTORY ) ;
std : : replace ( static_dir_ . begin ( ) , static_dir_ . end ( ) , ' \\ ' , ' / ' ) ;
if ( static_dir_ [ static_dir_ . length ( ) - 1 ] ! = ' / ' )
2022-07-23 13:51:46 +00:00
static_dir_ + = ' / ' ;
2022-07-23 13:40:01 +00:00
route < crow : : black_magic : : get_parameter_tag ( CROW_STATIC_ENDPOINT ) > ( CROW_STATIC_ENDPOINT ) ( [ static_dir_ ] ( crow : : response & res , std : : string file_path_partial ) {
2022-04-25 20:47:06 +00:00
utility : : sanitize_filename ( file_path_partial ) ;
2022-07-23 13:40:01 +00:00
res . set_static_file_info_unsafe ( static_dir_ + file_path_partial ) ;
2021-11-27 17:44:51 +00:00
res . end ( ) ;
2021-07-28 19:31:08 +00:00
} ) ;
2021-07-05 22:53:32 +00:00
2021-10-22 11:27:10 +00:00
# if defined(__APPLE__) || defined(__MACH__)
if ( ! router_ . blueprints ( ) . empty ( ) )
# endif
{
2021-10-10 11:42:36 +00:00
for ( Blueprint * bp : router_ . blueprints ( ) )
2021-07-05 22:53:32 +00:00
{
2021-10-10 11:42:36 +00:00
if ( ! bp - > static_dir ( ) . empty ( ) )
2021-07-28 19:31:08 +00:00
{
2022-07-23 13:40:01 +00:00
// stat on windows doesn't care whether '/' or '\' is being used. on Linux however, using '\' doesn't work. therefore every instance of '\' gets replaced with '/' then a check is done to make sure the directory ends with '/'.
std : : string static_dir_ ( bp - > static_dir ( ) ) ;
std : : replace ( static_dir_ . begin ( ) , static_dir_ . end ( ) , ' \\ ' , ' / ' ) ;
if ( static_dir_ [ static_dir_ . length ( ) - 1 ] ! = ' / ' )
static_dir_ + = ' / ' ;
2022-11-05 23:20:38 +00:00
bp - > new_rule_tagged < crow : : black_magic : : get_parameter_tag ( CROW_STATIC_ENDPOINT ) > ( CROW_STATIC_ENDPOINT ) ( [ static_dir_ ] ( crow : : response & res , std : : string file_path_partial ) {
2022-04-25 20:47:06 +00:00
utility : : sanitize_filename ( file_path_partial ) ;
2022-07-23 13:40:01 +00:00
res . set_static_file_info_unsafe ( static_dir_ + file_path_partial ) ;
2021-11-27 17:44:51 +00:00
res . end ( ) ;
2021-10-10 11:42:36 +00:00
} ) ;
}
2021-07-28 19:31:08 +00:00
}
2021-07-05 22:53:32 +00:00
}
2020-11-10 00:47:30 +00:00
# endif
2021-07-27 07:52:49 +00:00
2021-07-28 19:31:08 +00:00
router_ . validate ( ) ;
validated_ = true ;
}
2021-07-27 07:52:49 +00:00
}
2021-11-25 11:45:38 +00:00
/// Run the server
2021-07-27 07:52:49 +00:00
void run ( )
{
2021-07-05 09:18:00 +00:00
validate ( ) ;
2020-11-10 00:47:30 +00:00
2016-09-21 14:11:06 +00:00
# ifdef CROW_ENABLE_SSL
2021-11-21 23:29:22 +00:00
if ( ssl_used_ )
2016-09-21 14:11:06 +00:00
{
2021-11-19 17:42:25 +00:00
ssl_server_ = std : : move ( std : : unique_ptr < ssl_server_t > ( new ssl_server_t ( this , bindaddr_ , port_ , server_name_ , & middlewares_ , concurrency_ , timeout_ , & ssl_context_ ) ) ) ;
2016-09-21 14:11:06 +00:00
ssl_server_ - > set_tick_function ( tick_interval_ , tick_function_ ) ;
2021-12-08 16:57:10 +00:00
ssl_server_ - > signal_clear ( ) ;
2021-12-08 02:21:03 +00:00
for ( auto snum : signals_ )
{
2021-12-08 16:57:10 +00:00
ssl_server_ - > signal_add ( snum ) ;
2021-12-08 02:21:03 +00:00
}
2017-12-24 15:40:39 +00:00
notify_server_start ( ) ;
2016-09-21 14:11:06 +00:00
ssl_server_ - > run ( ) ;
}
else
2021-08-29 17:12:46 +00:00
# endif
2016-09-21 14:11:06 +00:00
{
2021-11-19 17:42:25 +00:00
server_ = std : : move ( std : : unique_ptr < server_t > ( new server_t ( this , bindaddr_ , port_ , server_name_ , & middlewares_ , concurrency_ , timeout_ , nullptr ) ) ) ;
2021-08-29 17:12:46 +00:00
server_ - > set_tick_function ( tick_interval_ , tick_function_ ) ;
for ( auto snum : signals_ )
{
server_ - > signal_add ( snum ) ;
}
notify_server_start ( ) ;
server_ - > run ( ) ;
2021-08-21 02:19:51 +00:00
}
2016-09-21 14:11:06 +00:00
}
2022-03-10 12:44:39 +00:00
/// Non-blocking version of \ref run()
2022-07-18 03:33:56 +00:00
///
/// The output from this method needs to be saved into a variable!
/// Otherwise the call will be made on the same thread.
2022-03-10 12:44:39 +00:00
std : : future < void > run_async ( )
{
2022-03-16 18:15:18 +00:00
return std : : async ( std : : launch : : async , [ & ] {
this - > run ( ) ;
} ) ;
2022-03-10 12:44:39 +00:00
}
2021-11-25 11:45:38 +00:00
/// Stop the server
2016-09-21 14:11:06 +00:00
void stop ( )
{
# ifdef CROW_ENABLE_SSL
2021-11-21 23:29:22 +00:00
if ( ssl_used_ )
2016-09-21 14:11:06 +00:00
{
2021-11-25 11:45:38 +00:00
if ( ssl_server_ ) { ssl_server_ - > stop ( ) ; }
2016-09-21 14:11:06 +00:00
}
else
2021-08-29 17:12:46 +00:00
# endif
2016-09-21 14:11:06 +00:00
{
2022-08-21 18:33:04 +00:00
// TODO(EDev): Move these 6 lines to a method in http_server.
2022-05-20 11:14:55 +00:00
std : : vector < crow : : websocket : : connection * > websockets_to_close = websockets_ ;
for ( auto websocket : websockets_to_close )
{
CROW_LOG_INFO < < " Quitting Websocket: " < < websocket ;
websocket - > close ( " Server Application Terminated " ) ;
}
2021-11-25 11:45:38 +00:00
if ( server_ ) { server_ - > stop ( ) ; }
2021-08-29 17:12:46 +00:00
}
2016-09-21 14:11:06 +00:00
}
2021-08-29 17:12:46 +00:00
2022-05-20 11:14:55 +00:00
void add_websocket ( crow : : websocket : : connection * conn )
{
websockets_ . push_back ( conn ) ;
}
void remove_websocket ( crow : : websocket : : connection * conn )
{
2022-06-03 05:44:57 +00:00
websockets_ . erase ( std : : remove ( websockets_ . begin ( ) , websockets_ . end ( ) , conn ) , websockets_ . end ( ) ) ;
2022-05-20 11:14:55 +00:00
}
2022-03-23 22:55:46 +00:00
/// Print the routing paths defined for each HTTP method
2016-09-21 14:11:06 +00:00
void debug_print ( )
{
CROW_LOG_DEBUG < < " Routing: " ;
router_ . debug_print ( ) ;
}
2017-09-17 17:58:53 +00:00
2016-09-21 14:11:06 +00:00
# ifdef CROW_ENABLE_SSL
2020-10-22 01:13:57 +00:00
2022-04-27 02:58:53 +00:00
/// Use certificate and key files for SSL
2016-09-21 14:11:06 +00:00
self_t & ssl_file ( const std : : string & crt_filename , const std : : string & key_filename )
{
2021-11-21 23:29:22 +00:00
ssl_used_ = true ;
2022-06-06 14:38:46 +00:00
ssl_context_ . set_verify_mode ( asio : : ssl : : verify_peer ) ;
ssl_context_ . set_verify_mode ( asio : : ssl : : verify_client_once ) ;
2016-09-21 14:11:06 +00:00
ssl_context_ . use_certificate_file ( crt_filename , ssl_context_t : : pem ) ;
ssl_context_ . use_private_key_file ( key_filename , ssl_context_t : : pem ) ;
ssl_context_ . set_options (
2022-06-06 14:38:46 +00:00
asio : : ssl : : context : : default_workarounds | asio : : ssl : : context : : no_sslv2 | asio : : ssl : : context : : no_sslv3 ) ;
2016-09-21 14:11:06 +00:00
return * this ;
}
2022-04-27 02:58:53 +00:00
/// Use .pem file for SSL
2016-09-21 14:11:06 +00:00
self_t & ssl_file ( const std : : string & pem_filename )
{
2021-11-21 23:29:22 +00:00
ssl_used_ = true ;
2022-06-06 14:38:46 +00:00
ssl_context_ . set_verify_mode ( asio : : ssl : : verify_peer ) ;
ssl_context_ . set_verify_mode ( asio : : ssl : : verify_client_once ) ;
2016-09-21 14:11:06 +00:00
ssl_context_ . load_verify_file ( pem_filename ) ;
ssl_context_ . set_options (
2022-06-06 14:38:46 +00:00
asio : : ssl : : context : : default_workarounds | asio : : ssl : : context : : no_sslv2 | asio : : ssl : : context : : no_sslv3 ) ;
2016-09-21 14:11:06 +00:00
return * this ;
}
2022-04-27 02:54:33 +00:00
/// Use certificate chain and key files for SSL
self_t & ssl_chainfile ( const std : : string & crt_filename , const std : : string & key_filename )
{
ssl_used_ = true ;
2022-06-06 14:38:46 +00:00
ssl_context_ . set_verify_mode ( asio : : ssl : : verify_peer ) ;
ssl_context_ . set_verify_mode ( asio : : ssl : : verify_client_once ) ;
2022-04-27 02:54:33 +00:00
ssl_context_ . use_certificate_chain_file ( crt_filename ) ;
ssl_context_ . use_private_key_file ( key_filename , ssl_context_t : : pem ) ;
ssl_context_ . set_options (
2022-06-06 14:38:46 +00:00
asio : : ssl : : context : : default_workarounds | asio : : ssl : : context : : no_sslv2 | asio : : ssl : : context : : no_sslv3 ) ;
2022-04-27 02:54:33 +00:00
return * this ;
}
2022-06-06 14:38:46 +00:00
self_t & ssl ( asio : : ssl : : context & & ctx )
2016-09-21 14:11:06 +00:00
{
2021-11-21 23:29:22 +00:00
ssl_used_ = true ;
2016-09-21 14:11:06 +00:00
ssl_context_ = std : : move ( ctx ) ;
return * this ;
}
2021-11-21 23:29:22 +00:00
bool ssl_used ( ) const
{
return ssl_used_ ;
}
2016-09-21 14:11:06 +00:00
# else
2021-11-25 11:45:38 +00:00
template < typename T , typename . . . Remain >
2016-09-21 14:11:06 +00:00
self_t & ssl_file ( T & & , Remain & & . . . )
{
// We can't call .ssl() member function unless CROW_ENABLE_SSL is defined.
static_assert (
2021-11-25 11:45:38 +00:00
// make static_assert dependent to T; always false
std : : is_base_of < T , void > : : value ,
" Define CROW_ENABLE_SSL to enable ssl support. " ) ;
2016-09-21 14:11:06 +00:00
return * this ;
}
2022-04-27 02:54:33 +00:00
template < typename T , typename . . . Remain >
self_t & ssl_chainfile ( T & & , Remain & & . . . )
{
// We can't call .ssl() member function unless CROW_ENABLE_SSL is defined.
static_assert (
// make static_assert dependent to T; always false
std : : is_base_of < T , void > : : value ,
" Define CROW_ENABLE_SSL to enable ssl support. " ) ;
return * this ;
}
2021-11-25 11:45:38 +00:00
template < typename T >
2016-09-21 14:11:06 +00:00
self_t & ssl ( T & & )
{
// We can't call .ssl() member function unless CROW_ENABLE_SSL is defined.
static_assert (
2021-11-25 11:45:38 +00:00
// make static_assert dependent to T; always false
std : : is_base_of < T , void > : : value ,
" Define CROW_ENABLE_SSL to enable ssl support. " ) ;
2016-09-21 14:11:06 +00:00
return * this ;
}
2021-11-21 23:29:22 +00:00
bool ssl_used ( ) const
{
return false ;
}
2016-09-21 14:11:06 +00:00
# endif
// middleware
using context_t = detail : : context < Middlewares . . . > ;
2022-02-01 13:31:05 +00:00
using mw_container_t = std : : tuple < Middlewares . . . > ;
2021-11-25 11:45:38 +00:00
template < typename T >
2016-09-21 14:11:06 +00:00
typename T : : context & get_context ( const request & req )
{
static_assert ( black_magic : : contains < T , Middlewares . . . > : : value , " App doesn't have the specified middleware type. " ) ;
auto & ctx = * reinterpret_cast < context_t * > ( req . middleware_context ) ;
return ctx . template get < T > ( ) ;
}
2021-11-25 11:45:38 +00:00
template < typename T >
2016-09-21 14:11:06 +00:00
T & get_middleware ( )
{
return utility : : get_element_by_type < T , Middlewares . . . > ( middlewares_ ) ;
}
2021-11-25 11:45:38 +00:00
/// Wait until the server has properly started
2017-12-24 15:40:39 +00:00
void wait_for_server_start ( )
{
2022-06-13 08:53:27 +00:00
{
std : : unique_lock < std : : mutex > lock ( start_mutex_ ) ;
if ( ! server_started_ )
cv_started_ . wait ( lock ) ;
}
if ( server_ )
server_ - > wait_for_start ( ) ;
# ifdef CROW_ENABLE_SSL
else if ( ssl_server_ )
ssl_server_ - > wait_for_start ( ) ;
# endif
2017-12-24 15:40:39 +00:00
}
2021-04-12 05:25:09 +00:00
2022-04-13 17:49:22 +00:00
private :
template < typename . . . Ts >
std : : tuple < Middlewares . . . > make_middleware_tuple ( Ts & & . . . ts )
{
auto fwd = std : : forward_as_tuple ( ( ts ) . . . ) ;
return std : : make_tuple (
std : : forward < Middlewares > (
black_magic : : tuple_extract < Middlewares , decltype ( fwd ) > ( fwd ) ) . . . ) ;
}
2022-06-13 08:53:27 +00:00
/// Notify anything using `wait_for_server_start()` to proceed
void notify_server_start ( )
{
std : : unique_lock < std : : mutex > lock ( start_mutex_ ) ;
server_started_ = true ;
cv_started_ . notify_all ( ) ;
}
2022-04-13 17:49:22 +00:00
2016-09-21 14:11:06 +00:00
private :
2021-11-19 17:42:25 +00:00
std : : uint8_t timeout_ { 5 } ;
2016-09-21 14:11:06 +00:00
uint16_t port_ = 80 ;
2021-12-23 02:39:39 +00:00
uint16_t concurrency_ = 2 ;
2022-05-15 02:35:45 +00:00
uint64_t max_payload_ { UINT64_MAX } ;
2021-07-28 19:31:08 +00:00
bool validated_ = false ;
2021-07-03 20:02:32 +00:00
std : : string server_name_ = std : : string ( " Crow/ " ) + VERSION ;
2016-09-21 14:11:06 +00:00
std : : string bindaddr_ = " 0.0.0.0 " ;
2021-10-12 12:35:08 +00:00
size_t res_stream_threshold_ = 1048576 ;
2016-09-21 14:11:06 +00:00
Router router_ ;
2021-06-03 14:12:20 +00:00
# ifdef CROW_ENABLE_COMPRESSION
2021-01-02 19:12:04 +00:00
compression : : algorithm comp_algorithm_ ;
2021-08-29 17:54:57 +00:00
bool compression_used_ { false } ;
2021-06-03 14:12:20 +00:00
# endif
2016-09-21 14:11:06 +00:00
std : : chrono : : milliseconds tick_interval_ ;
std : : function < void ( ) > tick_function_ ;
std : : tuple < Middlewares . . . > middlewares_ ;
# ifdef CROW_ENABLE_SSL
std : : unique_ptr < ssl_server_t > ssl_server_ ;
2021-11-21 23:29:22 +00:00
bool ssl_used_ { false } ;
2022-06-06 14:38:46 +00:00
ssl_context_t ssl_context_ { asio : : ssl : : context : : sslv23 } ;
2021-08-21 02:19:51 +00:00
# endif
2021-11-21 23:29:22 +00:00
2021-08-29 17:12:46 +00:00
std : : unique_ptr < server_t > server_ ;
2020-12-19 07:15:57 +00:00
std : : vector < int > signals_ { SIGINT , SIGTERM } ;
2017-12-24 15:40:39 +00:00
bool server_started_ { false } ;
std : : condition_variable cv_started_ ;
std : : mutex start_mutex_ ;
2022-05-20 11:14:55 +00:00
std : : vector < crow : : websocket : : connection * > websockets_ ;
2016-09-21 14:11:06 +00:00
} ;
2021-11-25 11:45:38 +00:00
template < typename . . . Middlewares >
2016-09-21 14:11:06 +00:00
using App = Crow < Middlewares . . . > ;
using SimpleApp = Crow < > ;
2021-11-25 11:45:38 +00:00
} // namespace crow