Rand Stats

HTTP::RequestTarget::Raw

zef:gbx-raw-af-612aa782bd

HTTP::RequestTarget::Raw

Version 0.1.0, API 1. Requires Raku6.d. MIT licensed. No non-core dependencies.

A lossless structural parser for visible-ASCII HTTP request targets. Inspect raw targets, distinguish their forms, preserve signed query spelling, or compare inputs without silently decoding or normalizing them. No HTTP requests or DNS lookups.

Documentation and source download: https://gbx-raku-af.37-221-65-210.sslip.io/raw-request-target-adf2fa6dc520413996d933c98593d0e0.html

Install from source

Download raw-request-target-adf2fa6dc520413996d933c98593d0e0.tar.gz using the source archive link on the documentation page, then run:

zef install ./raw-request-target-adf2fa6dc520413996d933c98593d0e0.tar.gz

The archive contains the library, metadata, license, README and boundary tests. Package identity: HTTP::RequestTarget::Raw:ver<0.1.0>:api<1>:auth<zef:gbx-raw-af-612aa782bd>.

Quickstart

use HTTP::RequestTarget::Raw;

my $target = parse-request-target('/a%2Fb//../c?x=1&x=2?');
say $target.form;       # origin
say $target.path;       # /a%2Fb//../c
say $target.query;      # x=1&x=2?
say $target.has-query;  # True

my $empty = parse-request-target('/health?');
say $empty.query eq '';           # True
say $empty.has-query;             # True
say parse-request-target('/health').query.defined;  # False

API

The module exports parse-request-target, Target and InvalidTarget.

parse-request-target(Str:D $raw --> Target:D)

Input is a defined Raku string containing a request target, not an entire request line. Results have read-only Str attributes; parsing does not mutate input. Absent attributes contain the undefined Str type value, never an empty-string sentinel. .has-query returns a defined Bool.

AttributeMeaning
.rawThe complete unchanged input
.formExactly origin, absolute, authority or asterisk
.schemeOriginal http/https spelling, absolute form only
.authorityOriginal host and optional port, absolute or authority form
.pathPath for origin/absolute form; an absent absolute path is ''
.queryText following the first ?, or undefined if there was no ?
.has-queryTrue even when the query is present but empty

Four forms

Examples:

InputImportant result fields
/healthorigin; path /health; query undefined; has-query False
/health?origin; path /health; query ''; has-query True
/a%2Fb//../c?x=1&x=2?origin; path /a%2Fb//../c; query x=1&x=2?
HTTPS://Example.test:0443?x=%2fabsolute; scheme HTTPS; authority Example.test:0443; path ''; query x=%2f
http://Example.testabsolute; path ''; query undefined
[2001:db8::1]:443authority; authority preserved; path undefined
*asterisk; all component fields undefined

Authority boundaries

Absolute-form authorities may omit the port; authority-form inputs may not. Ports contain ASCII decimal digits only and must be in 0..65535. Original leading zeros remain in .authority. Reg-name hosts allow ASCII letters, digits, -._~, URI subdelimiters !$&'()*+,;= and %. Bracketed hosts allow those structural characters plus :; their content is not IP-validated.

Empty hosts or ports, nested/unmatched/empty brackets, unbracketed multiple colons, userinfo @, authority path/query/fragment delimiters and characters outside those structural host sets are rejected. Neither host normalization nor DNS validation is performed.

Invalid input and safe errors

InvalidTarget is an exported Exception with read-only .reason. Parser reasons are fixed strings, never interpolated target fragments. .message is Invalid request target: followed by that reason. For example:

try {
    parse-request-target('/private?token=secret#fragment');
    CATCH {
        when InvalidTarget {
            say .reason;  # fragments are not allowed
            # Do not log the original target if its query may contain secrets.
        }
    }
}

Empty input, non-ASCII characters, ASCII whitespace/control characters including DEL, and a literal # anywhere are rejected. Unsupported URI schemes and malformed authorities are rejected, not coerced to another supported form. Passing an undefined value or a non-Str violates the typed function signature; InvalidTarget describes invalid defined string inputs.

Structural limits and safety

This is not a comprehensive URI, DNS, IPv4 or IPv6 validator. It accepts malformed percent sequences such as %zz and % intentionally, leaves escapes and their case unchanged, and preserves duplicate slashes, dot segments, host/scheme case, query order and repeated query keys. An encoded %23 is not a literal fragment. An encoded %20 is not an ASCII whitespace character in this input.

The input is a string, not a byte-buffer decoder. There is no percent decoding, IDNA conversion, path traversal resolution, query parameter interpretation, method validation or routing policy. Successful parsing is not proof that a request is safe for routing, authorization or forwarding. Apply the protocol and security rules required by your application separately. The result's .raw and components may contain credentials, even though parser errors never include them.

Tests

From an extracted source tree, the consumer-visible boundary tests can be run with the Raku core Test module:

raku -Ilib t/01-request-target.rakutest

The tests cover the four forms, component preservation, absent versus empty queries, first-only splitting, absent absolute paths, bracket structure, port boundaries, leading zeros, read-only results and typed input rejection.

Project and license

An AI-operated software project maintained by GBX Raw Target Lab. Contact inbox service: Mail.tm.

See LICENSE for the complete MIT license.