http11: support underscores in URI hostnames
[unicorn.git] / ext / unicorn / http11 / http11_parser_common.rl
blobae01a5545ec75bd5abe76a4b0e103ed2c0c49c29
1 %%{
2   
3   machine http_parser_common;
5 #### HTTP PROTOCOL GRAMMAR
6 # line endings
7   CRLF = "\r\n";
9 # character types
10   CTL = (cntrl | 127);
11   safe = ("$" | "-" | "_" | ".");
12   extra = ("!" | "*" | "'" | "(" | ")" | ",");
13   reserved = (";" | "/" | "?" | ":" | "@" | "&" | "=" | "+");
14   sorta_safe = ("\"" | "<" | ">");
15   unsafe = (CTL | " " | "#" | "%" | sorta_safe);
16   national = any -- (alpha | digit | reserved | extra | safe | unsafe);
17   unreserved = (alpha | digit | safe | extra | national);
18   escape = ("%" xdigit xdigit);
19   uchar = (unreserved | escape | sorta_safe);
20   pchar = (uchar | ":" | "@" | "&" | "=" | "+");
21   tspecials = ("(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\"" | "/" | "[" | "]" | "?" | "=" | "{" | "}" | " " | "\t");
23 # elements
24   token = (ascii -- (CTL | tspecials));
26 # URI schemes and absolute paths
27   scheme = ( "http"i ("s"i)? ) $downcase_char >mark %scheme;
28   hostname = (alnum | "-" | "." | "_")+;
29   host_with_port = (hostname (":" digit*)?) >mark %host;
31   path = ( pchar+ ( "/" pchar* )* ) ;
32   query = ( uchar | reserved )* %query_string ;
33   param = ( pchar | "/" )* ;
34   params = ( param ( ";" param )* ) ;
35   rel_path = ( path? %request_path (";" params)? ) ("?" %start_query query)?;
36   absolute_path = ( "/"+ rel_path );
37   path_uri = absolute_path > mark %request_uri;
38   Absolute_URI = (scheme "://" host_with_port path_uri);
40   Request_URI = ((absolute_path | "*") >mark %request_uri) | Absolute_URI;
41   Fragment = ( uchar | reserved )* >mark %fragment;
42   Method = ( upper | digit | safe ){1,20} >mark %request_method;
44   http_number = ( digit+ "." digit+ ) ;
45   HTTP_Version = ( "HTTP/" http_number ) >mark %http_version ;
46   Request_Line = ( Method " " Request_URI ("#" Fragment){0,1} " " HTTP_Version CRLF ) ;
48   field_name = ( token -- ":" )+ >start_field $snake_upcase_field %write_field;
50   field_value = any* >start_value %write_value;
52   message_header = field_name ":" " "* field_value :> CRLF;
54   Request = Request_Line ( message_header )* ( CRLF @done );
56 main := Request;
58 }%%