#include <iostream>
#include <random>
#include <fstream>
#include <fmt/format.h>
#include <restinio-helpers/cmd_line_args_helpers.hpp>
struct app_args_t
{
bool m_help{ false };
std::string m_dest_folder{ "." };
std::string m_address{ "localhost" };
std::uint16_t m_port{ 8080 };
std::size_t m_pool_size{ 1 };
bool m_trace_server{ false };
static app_args_t
parse( int argc, const char * argv[] )
{
using namespace restinio_helpers;
app_args_t result;
process_cmd_line_args( argc, argv, result,
cmd_line_arg_t{
result.m_dest_folder,
"-d", "--dest-folder",
"destination folder for uploaded files (default: {})"
},
cmd_line_arg_t{
result.m_address,
"-a", "--address",
"address to listen (default: {})"
},
cmd_line_arg_t{
result.m_port,
"-p", "--port",
"port to listen (default: {})"
},
cmd_line_arg_t{
result.m_pool_size,
"-n", "--thread-pool-size",
"size of a thread pool to run server (default: {})"
},
cmd_line_arg_t{
result.m_trace_server,
"-t", "--trace",
"enable trace server"
} );
return result;
}
};
void store_file_to_disk(
const app_args_t & args,
{
std::ofstream dest_file;
dest_file.exceptions( std::ofstream::failbit );
dest_file.open(
std::ios_base::out | std::ios_base::trunc | std::ios_base::binary );
dest_file.write( raw_content.data(), raw_content.size() );
}
void save_file(
const app_args_t & args,
{
*req,
if(
"file" == part.
name )
{
{
return handling_result_t::stop_enumeration;
}
}
return handling_result_t::terminate_enumeration;
} );
if( !enumeration_result || 1u != *enumeration_result )
throw std::runtime_error( "file content not found!" );
}
auto make_router( const app_args_t & args )
{
auto router = std::make_unique< router_t >();
"/",
const auto action_url = fmt::format(
args.m_address, args.m_port );
auto resp = req->create_response();
resp.append_header( "Server", "RESTinio" );
resp.append_header_date_field();
resp.append_header(
restinio::http_field::content_type,
"text/html; charset=utf-8" );
resp.set_body(
R"---(
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>File Upload!</title>
</head>
<body>
<p>Please select file to be uploaded to server.</p>
<form method="post" action=")---" + action_url + R"---(" enctype="multipart/form-data">
<p><input type="text" name="comment" id="comment-id" value=""></p>
<p><input type="file" name="file" id="file-id"></p>
<p><button type="submit">Submit</button></p>
</form>
</body>
</html>
)---" );
return resp.done();
} );
[&]( const auto & req, const auto & )
{
save_file( args, req );
auto resp = req->create_response();
resp.append_header( "Server", "RESTinio" );
resp.append_header_date_field();
resp.append_header(
restinio::http_field::content_type,
"text/plain; charset=utf-8" );
resp.set_body( "Ok. Uploaded" );
return resp.done();
} );
}
template < typename Server_Traits >
void run_server( const app_args_t & args )
{
.port( args.m_port )
.address( args.m_address )
.concurrent_accepts_count( args.m_pool_size )
.request_handler( make_router( args ) ) );
}
int main( int argc, const char * argv[] )
{
try
{
const auto args = app_args_t::parse( argc, argv );
if( !args.m_help )
{
if( args.m_trace_server )
{
router_t >;
run_server< traits_t >( args );
}
else
{
router_t >;
run_server< traits_t >( args );
}
}
}
catch( const std::exception & ex )
{
std::cerr << "Error: " << ex.what() << std::endl;
return 1;
}
return 0;
}
Timer factory implementation using asio timers.
Include all core header files in one.
Various tools for simplification of file uploading.
#define RESTINIO_FMT_FORMAT_STRING(s)
expected_t< std::size_t, enumeration_error_t > enumerate_parts_with_files(const generic_request_t< Extra_Data > &req, Handler &&handler, string_view_t expected_media_type=string_view_t{"multipart"}, string_view_t expected_media_subtype=string_view_t{"form-data"})
A helper function for enumeration of parts of a multipart body those contain uploaded files.
generic_express_router_t< Regex_Engine, no_extra_data_factory_t > express_router_t
A type of express-like router for the case when the default extra-data-factory is specified in the se...
run_on_thread_pool_settings_t< Traits > on_thread_pool(std::size_t pool_size)
A special marker for the case when http_server must be run on an thread pool.
std::shared_ptr< request_t > request_handle_t
An alias for handle for incoming request without additional extra-data.
std::string_view string_view_t
void run(asio_ns::io_context &ioctx, run_on_this_thread_settings_t< Traits > &&settings)
Helper function for running http server until ctrl+c is hit.
ostream_logger_t< std::mutex > shared_ostream_logger_t
A description of one part with an uploaded file.
std::optional< std::string > filename
The value of Content-Disposition's 'filename' parameter.
std::string name
The value of Content-Disposition's 'name' parameter.
string_view_t body
The body of that part.