Grammar::HTTP

HTTP request, response, and message body parsing grammar

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

The Camelia image is copyright 2009 by Larry Wall. "Raku" is trademark of the Yet Another Society. All rights reserved.