1 #include <iostream>
2 #include <string>
3
4 #include <restinio/all.hpp>
5
6 using namespace std::string_literals;
7
8 // Type of query-string parser.
9 using query_string_parser_type =
10 restinio::expected_t<
11 restinio::query_string_params_t,
12 restinio::parse_query_failure_t >
13 (*)( restinio::string_view_t );
14
15 // Create an appropriate query-string parser.
create_parser(int argc,char ** argv)16 query_string_parser_type create_parser( int argc, char ** argv )
17 {
18 if( argc < 2 || "restinio_defaults"s == argv[ 1 ] )
19 return []( restinio::string_view_t what ) {
20 return restinio::try_parse_query<
21 restinio::parse_query_traits::restinio_defaults >( what );
22 };
23
24 if( 2 == argc )
25 {
26 if( "javascript_compatible"s == argv[ 1 ] )
27 return []( restinio::string_view_t what ) {
28 return restinio::try_parse_query<
29 restinio::parse_query_traits::javascript_compatible >( what );
30 };
31 if( "x_www_form_urlencoded"s == argv[ 1 ] )
32 return []( restinio::string_view_t what ) {
33 return restinio::try_parse_query<
34 restinio::parse_query_traits::x_www_form_urlencoded >( what );
35 };
36 if( "relaxed"s == argv[ 1 ] ) {
37 return []( restinio::string_view_t what ) {
38 return restinio::try_parse_query<
39 restinio::parse_query_traits::relaxed >( what );
40 };
41 }
42 }
43
44 throw std::runtime_error{
45 "one optional argument expected: "
46 "restinio_defaults, javascript_compatible, x_www_form_urlencoded or "
47 "relaxed"
48 };
49 }
50
51 // Create request handler.
handler(const restinio::request_handle_t & req,query_string_parser_type parser)52 restinio::request_handling_status_t handler(
53 const restinio::request_handle_t& req,
54 query_string_parser_type parser )
55 {
56 if( restinio::http_method_get() == req->header().method() )
57 {
58 fmt::basic_memory_buffer< char, 1u > response_body;
59 fmt::format_to( response_body, "GET request to '{}'\n",
60 req->header().request_target() );
61
62 // Request header fields.
63 fmt::format_to( response_body, "HTTP-fields ({}):\n",
64 req->header().fields_count() );
65 for( const auto & f : req->header() )
66 {
67 fmt::format_to( response_body, "{}: {}\n",
68 f.name(), f.value() );
69 }
70
71 // An attempt to parse query-string.
72 const auto qs_parse_result = parser( req->header().query() );
73 if( !qs_parse_result )
74 {
75 // Return a negative response.
76 req->create_response( restinio::status_bad_request() )
77 .append_header( restinio::http_field::server, "RESTinio query string params server" )
78 .append_header_date_field()
79 .append_header( restinio::http_field::content_type, "text/plain; charset=utf-8" )
80 .set_body( "Unable to parse query-string: " +
81 qs_parse_result.error().description() )
82 .done();
83
84 return restinio::request_accepted();
85 }
86
87 // Handle query-string params.
88 const auto & qp = *qs_parse_result;
89 if( qp.empty() )
90 {
91 fmt::format_to( response_body, "No query parameters." );
92 }
93 else
94 {
95 fmt::format_to( response_body, "Query params ({}):\n", qp.size() );
96
97 for( const auto p : qp )
98 {
99 fmt::format_to( response_body, "'{}' => '{}'\n",
100 p.first, p.second );
101 }
102 }
103
104 if( qp.has( "debug" ) && qp[ "debug" ] == "true" )
105 {
106 std::cout.write( response_body.data(), response_body.size() );
107 std::cout << std::flush;
108 }
109
110 req->create_response()
111 .append_header( restinio::http_field::server, "RESTinio query string params server" )
112 .append_header_date_field()
113 .append_header( restinio::http_field::content_type, "text/plain; charset=utf-8" )
114 .set_body( std::move(response_body) )
115 .done();
116
117 return restinio::request_accepted();
118 }
119
120 return restinio::request_rejected();
121 }
122
main(int argc,char ** argv)123 int main( int argc, char ** argv )
124 {
125 try
126 {
127 restinio::run(
128 restinio::on_thread_pool( std::thread::hardware_concurrency() )
129 .port( 8080 )
130 .address( "localhost" )
131 .request_handler(
132 [parser = create_parser( argc, argv )]( const auto & req ) {
133 return handler( req, parser );
134 } )
135 );
136 }
137 catch( const std::exception & ex )
138 {
139 std::cerr << "Error: " << ex.what() << std::endl;
140 return 1;
141 }
142
143 return 0;
144 }
145
146