2014-04-01 13:58:52 +00:00
# pragma once
2014-03-31 16:51:50 +00:00
# include <string>
2014-04-01 12:25:16 +00:00
# include <unordered_map>
2014-09-22 20:34:22 +00:00
# include <algorithm>
2014-04-01 12:25:16 +00:00
2016-09-21 14:11:06 +00:00
# include "crow/http_request.h"
2022-08-21 18:33:04 +00:00
# include "crow/http_parser_merged.h"
2014-04-01 13:58:52 +00:00
2014-04-26 17:19:59 +00:00
namespace crow
2014-03-31 16:51:50 +00:00
{
2020-11-18 22:13:57 +00:00
/// A wrapper for `nodejs/http-parser`.
2021-12-03 03:39:23 +00:00
2020-11-18 22:13:57 +00:00
///
2021-11-25 11:45:38 +00:00
/// Used to generate a \ref crow.request from the TCP socket buffer.
template < typename Handler >
2014-03-31 16:51:50 +00:00
struct HTTPParser : public http_parser
{
2022-08-21 21:38:03 +00:00
static int on_message_begin ( http_parser * )
2014-03-31 16:51:50 +00:00
{
return 0 ;
}
2022-07-18 03:33:56 +00:00
static int on_method ( http_parser * self_ )
{
HTTPParser * self = static_cast < HTTPParser * > ( self_ ) ;
self - > req . method = static_cast < HTTPMethod > ( self - > method ) ;
return 0 ;
}
2014-03-31 16:51:50 +00:00
static int on_url ( http_parser * self_ , const char * at , size_t length )
{
HTTPParser * self = static_cast < HTTPParser * > ( self_ ) ;
2022-07-18 03:33:56 +00:00
self - > req . raw_url . insert ( self - > req . raw_url . end ( ) , at , at + length ) ;
self - > req . url_params = query_string ( self - > req . raw_url ) ;
self - > req . url = self - > req . raw_url . substr ( 0 , self - > qs_point ! = 0 ? self - > qs_point : std : : string : : npos ) ;
self - > process_url ( ) ;
2014-03-31 16:51:50 +00:00
return 0 ;
}
static int on_header_field ( http_parser * self_ , const char * at , size_t length )
{
HTTPParser * self = static_cast < HTTPParser * > ( self_ ) ;
2014-04-01 12:25:16 +00:00
switch ( self - > header_building_state )
{
case 0 :
if ( ! self - > header_value . empty ( ) )
{
2022-07-18 03:33:56 +00:00
self - > req . headers . emplace ( std : : move ( self - > header_field ) , std : : move ( self - > header_value ) ) ;
2014-04-01 12:25:16 +00:00
}
2021-11-25 11:45:38 +00:00
self - > header_field . assign ( at , at + length ) ;
2014-04-01 12:25:16 +00:00
self - > header_building_state = 1 ;
break ;
case 1 :
2021-11-25 11:45:38 +00:00
self - > header_field . insert ( self - > header_field . end ( ) , at , at + length ) ;
2014-04-01 12:25:16 +00:00
break ;
}
2014-03-31 16:51:50 +00:00
return 0 ;
}
static int on_header_value ( http_parser * self_ , const char * at , size_t length )
{
HTTPParser * self = static_cast < HTTPParser * > ( self_ ) ;
2014-04-01 12:25:16 +00:00
switch ( self - > header_building_state )
{
case 0 :
2021-11-25 11:45:38 +00:00
self - > header_value . insert ( self - > header_value . end ( ) , at , at + length ) ;
2014-04-01 12:25:16 +00:00
break ;
case 1 :
self - > header_building_state = 0 ;
2021-11-25 11:45:38 +00:00
self - > header_value . assign ( at , at + length ) ;
2014-04-01 12:25:16 +00:00
break ;
}
2014-03-31 16:51:50 +00:00
return 0 ;
}
static int on_headers_complete ( http_parser * self_ )
{
HTTPParser * self = static_cast < HTTPParser * > ( self_ ) ;
2014-04-01 12:25:16 +00:00
if ( ! self - > header_field . empty ( ) )
{
2022-07-18 03:33:56 +00:00
self - > req . headers . emplace ( std : : move ( self - > header_field ) , std : : move ( self - > header_value ) ) ;
2014-04-01 12:25:16 +00:00
}
2022-02-05 15:15:19 +00:00
2022-02-10 21:56:30 +00:00
self - > set_connection_parameters ( ) ;
2022-02-05 15:15:19 +00:00
2014-05-02 12:54:25 +00:00
self - > process_header ( ) ;
2014-03-31 16:51:50 +00:00
return 0 ;
}
static int on_body ( http_parser * self_ , const char * at , size_t length )
{
HTTPParser * self = static_cast < HTTPParser * > ( self_ ) ;
2022-07-18 03:33:56 +00:00
self - > req . body . insert ( self - > req . body . end ( ) , at , at + length ) ;
2014-03-31 16:51:50 +00:00
return 0 ;
}
static int on_message_complete ( http_parser * self_ )
{
HTTPParser * self = static_cast < HTTPParser * > ( self_ ) ;
2014-10-14 08:48:35 +00:00
2022-08-21 18:33:04 +00:00
self - > message_complete = true ;
2014-04-01 12:25:16 +00:00
self - > process_message ( ) ;
2014-03-31 16:51:50 +00:00
return 0 ;
}
2021-11-25 11:45:38 +00:00
HTTPParser ( Handler * handler ) :
handler_ ( handler )
2014-08-15 02:06:00 +00:00
{
2022-02-05 15:15:19 +00:00
http_parser_init ( this ) ;
2014-08-15 02:06:00 +00:00
}
// return false on error
2020-11-18 22:13:57 +00:00
/// Parse a buffer into the different sections of an HTTP request.
2014-08-15 02:06:00 +00:00
bool feed ( const char * buffer , int length )
{
2022-08-21 18:33:04 +00:00
if ( message_complete )
return true ;
2014-08-15 02:06:00 +00:00
const static http_parser_settings settings_ {
2021-11-25 11:45:38 +00:00
on_message_begin ,
2022-07-18 03:33:56 +00:00
on_method ,
2021-11-25 11:45:38 +00:00
on_url ,
on_header_field ,
on_header_value ,
on_headers_complete ,
on_body ,
on_message_complete ,
2014-08-15 02:06:00 +00:00
} ;
2014-03-31 16:51:50 +00:00
int nparsed = http_parser_execute ( this , & settings_ , buffer , length ) ;
2022-02-05 15:15:19 +00:00
if ( http_errno ! = CHPE_OK )
2021-11-01 09:02:25 +00:00
{
return false ;
}
2014-04-01 12:25:16 +00:00
return nparsed = = length ;
2014-03-31 16:51:50 +00:00
}
2014-04-01 12:25:16 +00:00
bool done ( )
2014-03-31 16:51:50 +00:00
{
2014-08-15 02:06:00 +00:00
return feed ( nullptr , 0 ) ;
2014-03-31 16:51:50 +00:00
}
2014-04-01 12:25:16 +00:00
void clear ( )
{
2022-07-18 03:33:56 +00:00
req = crow : : request ( ) ;
2014-04-01 12:25:16 +00:00
header_field . clear ( ) ;
header_value . clear ( ) ;
2022-02-21 14:32:09 +00:00
header_building_state = 0 ;
qs_point = 0 ;
2022-08-21 18:33:04 +00:00
message_complete = false ;
state = CROW_NEW_MESSAGE ( ) ;
2022-07-18 03:33:56 +00:00
}
inline void process_url ( )
{
handler_ - > handle_url ( ) ;
2014-04-01 12:25:16 +00:00
}
2022-02-05 15:15:19 +00:00
inline void process_header ( )
2014-05-02 12:54:25 +00:00
{
handler_ - > handle_header ( ) ;
}
2022-02-05 15:15:19 +00:00
inline void process_message ( )
2014-04-01 12:25:16 +00:00
{
handler_ - > handle ( ) ;
}
2022-02-10 21:56:30 +00:00
inline void set_connection_parameters ( )
{
2022-07-18 03:33:56 +00:00
req . http_ver_major = http_major ;
req . http_ver_minor = http_minor ;
2022-02-10 21:56:30 +00:00
//NOTE(EDev): it seems that the problem is with crow's policy on closing the connection for HTTP_VERSION < 1.0, the behaviour for that in crow is "don't close the connection, but don't send a keep-alive either"
// HTTP1.1 = always send keep_alive, HTTP1.0 = only send if header exists, HTTP?.? = never send
2022-07-18 03:33:56 +00:00
req . keep_alive = ( http_major = = 1 & & http_minor = = 0 ) ?
( ( flags & F_CONNECTION_KEEP_ALIVE ) ? true : false ) :
( ( http_major = = 1 & & http_minor = = 1 ) ? true : false ) ;
2022-02-10 21:56:30 +00:00
// HTTP1.1 = only close if close header exists, HTTP1.0 = always close unless keep_alive header exists, HTTP?.?= never close
2022-07-18 03:33:56 +00:00
req . close_connection = ( http_major = = 1 & & http_minor = = 0 ) ?
( ( flags & F_CONNECTION_KEEP_ALIVE ) ? false : true ) :
( ( http_major = = 1 & & http_minor = = 1 ) ? ( ( flags & F_CONNECTION_CLOSE ) ? true : false ) : false ) ;
req . upgrade = static_cast < bool > ( upgrade ) ;
2014-05-02 12:54:25 +00:00
}
2022-07-18 03:33:56 +00:00
/// The final request that this parser outputs.
///
/// Data parsed is put directly into this object as soon as the related callback returns. (e.g. the request will have the cooorect method as soon as on_method() returns)
request req ;
2014-09-22 20:34:22 +00:00
2022-07-18 03:33:56 +00:00
private :
2014-04-01 12:25:16 +00:00
int header_building_state = 0 ;
2022-08-21 18:33:04 +00:00
bool message_complete = false ;
2014-04-01 12:25:16 +00:00
std : : string header_field ;
std : : string header_value ;
2020-11-18 22:13:57 +00:00
Handler * handler_ ; ///< This is currently an HTTP connection object (\ref crow.Connection).
2014-03-31 16:51:50 +00:00
} ;
2021-11-25 11:45:38 +00:00
} // namespace crow
2022-08-21 18:33:04 +00:00
# undef CROW_NEW_MESSAGE
# undef CROW_start_state