Skip to content
HTTP request, response, and message body parsing grammar
Branch: master
Clone or download
ugexe Fix negative substring bug
Changes to/from -> sent-to/sent-from so as not to conflict with the
match object's to/from methods.

Resolves #6
Latest commit 210371b Aug 22, 2017
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
lib/Grammar Fix negative substring bug Aug 22, 2017
t Revert "Bugfix: add `no precompilation` to every module and test file" Dec 28, 2015
.appveyor.yml Update .appveyor.yml May 2, 2017
.travis.yml
LICENSE Create LICENSE May 2, 2017
META6.json Fix negative substring bug Aug 22, 2017
README.pod Fix appveyor links (s/--/-/) Feb 28, 2016

README.pod

Grammar::HTTP

Grammars for parsing HTTP headers, message bodies, and URIs

Synopsis

use Grammar::HTTP;

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

# 「GET / HTTP/1.1
# Host: www.perl6.org
#
#」
# HTTP-message => 「GET / HTTP/1.1
# Host: www.perl6.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.perl6.org」
#   name => 「Host」
#   value => 「www.perl6.org」
#    host => 「www.perl6.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

You can’t perform that action at this time.