Rand Stats

Grammar::HTTP

github:ugexe

Grammar::HTTP

Grammars for parsing HTTP headers, message bodies, and URIs

Synopsis

use Grammar::HTTP;

my $request = "GET / HTTP/1.1\r\nHost: www.raku.org\r\n\r\n";
my $match   = Grammar::HTTP.parse($request);
say $match;

# 「GET / HTTP/1.1
# Host: www.raku.org
#
#」
# HTTP-message => 「GET / HTTP/1.1
# Host: www.raku.org
#
#」
#  start-line => 「GET / HTTP/1.1
#」
#   request-line => 「GET / HTTP/1.1
#」
#    method => 「GET」
#    request-target => 「/」
#    HTTP-version => 「HTTP/1.1」
#     HTTP-name => 「HTTP」
#     major => 「1」
#     minor => 「1」
#  header-field => 「Host: www.raku.org」
#   name => 「Host」
#   value => 「www.raku.org」
#    host => 「www.raku.org」
#  message-body => 「」

Rules

token HTTP-start
token HTTP-headers
token HTTP-header
token HTTP-body
token HTTP-message

Parsing individual parts of the HTTP message can also be done by using a different rule. The default Grammar::HTTP.parse($str) is really the same as Grammar::HTTP.parse($str, :rule('HTTP-message'). So to parse just the start line you could do:

my $string = "GET /http.html HTTP/1.1\r\n"; 
say Grammar::HTTP.parse($string, :rule<HTTP-start>)'

# 「GET /http.html HTTP/1.1
# 」
#  start-line => 「GET /http.html HTTP/1.1
# 」
#   request-line => 「GET /http.html HTTP/1.1
# 」
#    method => 「GET」
#    request-target => 「/http.html」
#    HTTP-version => 「HTTP/1.1」
#    HTTP-name => 「HTTP」
#    major => 「1」
#    minor => 「1」

Actions

Grammar::HTTP::Actions can be used to generate a structured hash from a HTTP response message

use Grammar::HTTP::Actions;
use Grammar::HTTP;

my $response = "HTTP/1.1 200 OK\r\n"
    ~ "Allow: GET, HEAD, PUT\r\n"
    ~ "Content-Type: text/html; charset=utf-8\r\n"
    ~ "Transfer-Encoding: chunked, gzip\r\n\r\n";

my $parsed = Grammar::HTTP.parse($response, :actions(Grammar::HTTP::Actions.new));
my %header = $parsed.<HTTP-message>.<header-field>>>.made;
dd %header;

# Hash %header = {
#    :Allow($("GET", "HEAD", "PUT")),
#    :Content-Type($[
#        :type("text"),
#        :subtype("html"),
#        :parameters([ :charset("utf-8") ])
#    ]),
#    :Transfer-Encoding($("chunked", "gzip"))}

RFCs

RFC1035 Domain Names - Implementation and Specification

RFC3066 Tags for the Identification of Languages

RFC4234 Augmented BNF for Syntax Specifications: ABNF

RFC5234 Augmented BNF for Syntax Specifications: ABNF (replaces 4234)

RFC7405 Case-Sensitive String Support in ABNF

RFC4647 Matching of Language Tags

RFC5322 Internet Message Format

RFC5646 Tags for Identifying Languages

RFC7230 Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing

RFC7231 Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content

RFC7232 Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests

RFC7233 Hypertext Transfer Protocol (HTTP/1.1): Range Requests

RFC7234 Hypertext Transfer Protocol (HTTP/1.1): Caching

RFC7235 Hypertext Transfer Protocol (HTTP/1.1): Authentication