1 // Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey 2 // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ 3 4 #ifndef TAO_PEGTL_CONTRIB_HTTP_HPP 5 #define TAO_PEGTL_CONTRIB_HTTP_HPP 6 7 #include "../ascii.hpp" 8 #include "../config.hpp" 9 #include "../rules.hpp" 10 #include "../utf8.hpp" 11 12 #include "abnf.hpp" 13 #include "uri.hpp" 14 15 namespace tao 16 { 17 namespace TAO_PEGTL_NAMESPACE 18 { 19 namespace http 20 { 21 // HTTP 1.1 grammar according to RFC 7230. 22 23 // This grammar is a direct PEG translation of the original HTTP grammar. 24 // It should be considered experimental -- in case of any issues, in particular 25 // missing rules for attached actions, please contact the developers. 26 27 using OWS = star< abnf::WSP >; // optional whitespace 28 using RWS = plus< abnf::WSP >; // required whitespace 29 using BWS = OWS; // "bad" whitespace 30 31 // cppcheck-suppress constStatement 32 using obs_text = not_range< 0x00, 0x7F >; 33 using obs_fold = seq< abnf::CRLF, plus< abnf::WSP > >; 34 35 // clang-format off 36 struct tchar : sor< abnf::ALPHA, abnf::DIGIT, one< '!', '#', '$', '%', '&', '\'', '*', '+', '-', '.', '^', '_', '`', '|', '~' > > {}; 37 struct token : plus< tchar > {}; 38 39 struct field_name : token {}; 40 41 struct field_vchar : sor< abnf::VCHAR, obs_text > {}; 42 struct field_content : list< field_vchar, plus< abnf::WSP > > {}; 43 struct field_value : star< sor< field_content, obs_fold > > {}; 44 45 struct header_field : seq< field_name, one< ':' >, OWS, field_value, OWS > {}; 46 47 struct method : token {}; 48 49 struct absolute_path : plus< one< '/' >, uri::segment > {}; 50 51 struct origin_form : seq< absolute_path, uri::opt_query > {}; 52 struct absolute_form : uri::absolute_URI {}; 53 struct authority_form : uri::authority {}; 54 struct asterisk_form : one< '*' > {}; 55 56 struct request_target : sor< origin_form, absolute_form, authority_form, asterisk_form > {}; 57 58 struct status_code : rep< 3, abnf::DIGIT > {}; 59 struct reason_phrase : star< sor< abnf::VCHAR, obs_text, abnf::WSP > > {}; 60 61 struct HTTP_version : if_must< string< 'H', 'T', 'T', 'P', '/' >, abnf::DIGIT, one< '.' >, abnf::DIGIT > {}; 62 63 struct request_line : if_must< method, abnf::SP, request_target, abnf::SP, HTTP_version, abnf::CRLF > {}; 64 struct status_line : if_must< HTTP_version, abnf::SP, status_code, abnf::SP, reason_phrase, abnf::CRLF > {}; 65 struct start_line : sor< status_line, request_line > {}; 66 67 struct message_body : star< abnf::OCTET > {}; 68 struct HTTP_message : seq< start_line, star< header_field, abnf::CRLF >, abnf::CRLF, opt< message_body > > {}; 69 70 struct Content_Length : plus< abnf::DIGIT > {}; 71 72 struct uri_host : uri::host {}; 73 struct port : uri::port {}; 74 75 struct Host : seq< uri_host, opt< one< ':' >, port > > {}; 76 77 // PEG are different from CFGs! (this replaces ctext and qdtext) 78 using text = sor< abnf::HTAB, range< 0x20, 0x7E >, obs_text >; 79 80 struct quoted_pair : if_must< one< '\\' >, sor< abnf::VCHAR, obs_text, abnf::WSP > > {}; 81 struct quoted_string : if_must< abnf::DQUOTE, until< abnf::DQUOTE, sor< quoted_pair, text > > > {}; 82 83 struct transfer_parameter : seq< token, BWS, one< '=' >, BWS, sor< token, quoted_string > > {}; 84 struct transfer_extension : seq< token, star< OWS, one< ';' >, OWS, transfer_parameter > > {}; 85 struct transfer_coding : sor< istring< 'c', 'h', 'u', 'n', 'k', 'e', 'd' >, 86 istring< 'c', 'o', 'm', 'p', 'r', 'e', 's', 's' >, 87 istring< 'd', 'e', 'f', 'l', 'a', 't', 'e' >, 88 istring< 'g', 'z', 'i', 'p' >, 89 transfer_extension > {}; 90 91 struct rank : sor< seq< one< '0' >, opt< one< '.' >, rep_opt< 3, abnf::DIGIT > > >, 92 seq< one< '1' >, opt< one< '.' >, rep_opt< 3, one< '0' > > > > > {}; 93 94 struct t_ranking : seq< OWS, one< ';' >, OWS, one< 'q', 'Q' >, one< '=' >, rank > {}; 95 struct t_codings : sor< istring< 't', 'r', 'a', 'i', 'l', 'e', 'r', 's' >, seq< transfer_coding, opt< t_ranking > > > {}; 96 97 struct TE : opt< sor< one< ',' >, t_codings >, star< OWS, one< ',' >, opt< OWS, t_codings > > > {}; 98 99 template< typename T > 100 using make_comma_list = seq< star< one< ',' >, OWS >, T, star< OWS, one< ',' >, opt< OWS, T > > >; 101 102 struct connection_option : token {}; 103 struct Connection : make_comma_list< connection_option > {}; 104 105 struct Trailer : make_comma_list< field_name > {}; 106 107 struct Transfer_Encoding : make_comma_list< transfer_coding > {}; 108 109 struct protocol_name : token {}; 110 struct protocol_version : token {}; 111 struct protocol : seq< protocol_name, opt< one< '/' >, protocol_version > > {}; 112 struct Upgrade : make_comma_list< protocol > {}; 113 114 struct pseudonym : token {}; 115 116 struct received_protocol : seq< opt< protocol_name, one< '/' > >, protocol_version > {}; 117 struct received_by : sor< seq< uri_host, opt< one< ':' >, port > >, pseudonym > {}; 118 119 struct comment : if_must< one< '(' >, until< one< ')' >, sor< comment, quoted_pair, text > > > {}; 120 121 struct Via : make_comma_list< seq< received_protocol, RWS, received_by, opt< RWS, comment > > > {}; 122 123 struct http_URI : if_must< istring< 'h', 't', 't', 'p', ':', '/', '/' >, uri::authority, uri::path_abempty, uri::opt_query, uri::opt_fragment > {}; 124 struct https_URI : if_must< istring< 'h', 't', 't', 'p', 's', ':', '/', '/' >, uri::authority, uri::path_abempty, uri::opt_query, uri::opt_fragment > {}; 125 126 struct partial_URI : seq< uri::relative_part, uri::opt_query > {}; 127 128 struct chunk_size : plus< abnf::HEXDIG > {}; 129 130 struct chunk_ext_name : token {}; 131 struct chunk_ext_val : sor< quoted_string, token > {}; 132 struct chunk_ext : star_must< one< ';' >, chunk_ext_name, if_must< one< '=' >, chunk_ext_val > > {}; 133 134 struct chunk_data : until< at< abnf::CRLF >, abnf::OCTET > {}; 135 136 struct chunk : seq< chunk_size, opt< chunk_ext >, abnf::CRLF, chunk_data, abnf::CRLF > {}; 137 138 struct last_chunk : seq< plus< one< '0' > >, opt< chunk_ext >, abnf::CRLF > {}; 139 140 struct trailer_part : star< header_field, abnf::CRLF > {}; 141 142 struct chunked_body : seq< until< last_chunk, chunk >, trailer_part, abnf::CRLF > {}; 143 // clang-format on 144 145 } // namespace http 146 147 } // namespace TAO_PEGTL_NAMESPACE 148 149 } // namespace tao 150 151 #endif 152