about summary refs log tree commit homepage
path: root/ext/kcar/kcar_http_common.rl
diff options
context:
space:
mode:
Diffstat (limited to 'ext/kcar/kcar_http_common.rl')
-rw-r--r--ext/kcar/kcar_http_common.rl56
1 files changed, 56 insertions, 0 deletions
diff --git a/ext/kcar/kcar_http_common.rl b/ext/kcar/kcar_http_common.rl
new file mode 100644
index 0000000..54206ed
--- /dev/null
+++ b/ext/kcar/kcar_http_common.rl
@@ -0,0 +1,56 @@
+%%{
+
+  machine kcar_http_common;
+
+#### HTTP PROTOCOL GRAMMAR
+# line endings, some sites (notably http://news.ycombinator.com as of
+# April 2010) do not send '\r', only '\n', so we need to accomodate them.
+  CRLF = ("\r")? "\n";
+
+# character types
+  CTL = (cntrl | 127);
+  safe = ("$" | "-" | "_" | ".");
+  extra = ("!" | "*" | "'" | "(" | ")" | ",");
+  reserved = (";" | "/" | "?" | ":" | "@" | "&" | "=" | "+");
+  sorta_safe = ("\"" | "<" | ">");
+  unsafe = (CTL | " " | "#" | "%" | sorta_safe);
+  national = any -- (alpha | digit | reserved | extra | safe | unsafe);
+  unreserved = (alpha | digit | safe | extra | national);
+  escape = ("%" xdigit xdigit);
+  uchar = (unreserved | escape | sorta_safe);
+  pchar = (uchar | ":" | "@" | "&" | "=" | "+");
+  tspecials = ("(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\"" | "/" | "[" | "]" | "?" | "=" | "{" | "}" | " " | "\t");
+  lws = (" " | "\t");
+
+# elements
+  token = (ascii -- (CTL | tspecials));
+  phrase = (any -- CRLF)+;
+  Status_Phrase = (digit+ (" "+ phrase)?) >mark %status_phrase ;
+  http_number = (digit+ "." digit+) ;
+  HTTP_Version = ("HTTP/" http_number) >mark %http_version ;
+  Status_Line = HTTP_Version " "+ Status_Phrase :> CRLF;
+
+  field_name = ( token -- ":" )+ >start_field %write_field;
+
+  field_value = any* >start_value %write_value;
+
+  value_cont = lws+ any* >start_value %write_cont_value;
+
+  message_header = ((field_name ":" " "* field_value)|value_cont) :> CRLF;
+  chunk_ext_val = token*;
+  chunk_ext_name = token*;
+  chunk_extension = ( ";" " "* chunk_ext_name ("=" chunk_ext_val)? )*;
+  last_chunk = "0"+ chunk_extension CRLF;
+  chunk_size = (xdigit* [1-9a-fA-F] xdigit*) $add_to_chunk_size;
+  chunk_end = CRLF;
+  chunk_body = any >skip_chunk_data;
+  chunk_begin = chunk_size chunk_extension CRLF;
+  chunk = chunk_begin chunk_body chunk_end;
+  ChunkedBody := chunk* last_chunk @end_chunked_body;
+  Trailers := (message_header)* CRLF @end_trailers;
+
+  FullResponse = Status_Line (message_header)* CRLF @header_done;
+
+main := FullResponse;
+
+}%%