NAME

Hypersonic::Request - JIT-compiled request object for Hypersonic

SYNOPSIS

use Hypersonic;

my $server = Hypersonic->new();

# Dynamic route handler receives a Request object
$server->get('/users/:id' => sub {
    my ($req) = @_;

    # Basic request info
    my $method = $req->method;           # 'GET'
    my $path   = $req->path;             # '/users/42'
    my $body   = $req->body;             # Request body string

    # Path parameters (from :param in route)
    my $id = $req->param('id');          # '42'

    # Query string parameters (?key=value)
    my $page = $req->query_param('page');     # '1'
    my $all  = $req->query;                   # { page => '1', ... }

    # HTTP headers (normalized to lowercase_underscore)
    my $auth = $req->header('Authorization'); # 'Bearer xxx'
    my $ct   = $req->header('Content-Type');  # 'application/json'

    # Cookies
    my $sid = $req->cookie('session_id');     # 'abc123'

    # JSON body (auto-parsed)
    my $data = $req->json;                    # { name => 'foo' }

    # Form data (application/x-www-form-urlencoded)
    my $email = $req->form_param('email');    # 'user@example.com'

    # Path segments
    my $segments = $req->segments;            # ['users', '42']

    return '{"id":"' . $id . '"}';
});

# Enable specific parsing features for performance
$server->post('/api/data' => sub {
    my ($req) = @_;
    my $data = $req->json;
    return '{"received":true}';
}, {
    dynamic     => 1,
    parse_json  => 1,    # Enable JSON body parsing
});

DESCRIPTION

Hypersonic::Request provides a JIT-compiled request object passed to dynamic route handlers. All accessor methods are compiled to native XS code at startup for maximum performance.

The request object is array-based (not hash-based) with slot accessors. This allows direct array indexing for the fastest possible access when needed.

INTERNAL STRUCTURE

The request is an array-based object with the following slots:

Slot 0:  method            - HTTP method (GET, POST, etc.)
Slot 1:  path              - Request path
Slot 2:  body              - Request body string
Slot 3:  params            - HV* of named path parameters
Slot 4:  query             - HV* of query string parameters
Slot 5:  query_string      - Raw query string
Slot 6:  headers           - HV* of HTTP headers
Slot 7:  cookies           - HV* of cookies
Slot 8:  json              - Parsed JSON body (if requested)
Slot 9:  form              - HV* of form data
Slot 10: segments          - AV* of path segments
Slot 11: id                - Last path segment (legacy)
Slot 12: session           - Session data hashref (if enabled)
Slot 13: session_id        - Session ID string (if enabled)
Slot 14: session_modified  - Session modified flag (if enabled)

METHODS

All methods are JIT-compiled to XS for maximum speed.

method

my $method = $req->method;

Returns the HTTP method (GET, POST, PUT, DELETE, etc.).

path

my $path = $req->path;

Returns the request path (e.g., /users/42).

body

my $body = $req->body;

Returns the raw request body as a string.

query_string

my $qs = $req->query_string;

Returns the raw query string (without the leading ?).

param

my $value = $req->param('name');
my $all   = $req->param;

Get a named path parameter (from :name in route definition). Without arguments, returns the entire params hashref.

query_param

my $value = $req->query_param('key');
my $all   = $req->query_param;

Get a query string parameter. Without arguments, returns the entire query params hashref.

my $value = $req->header('Content-Type');
my $value = $req->header('content_type');  # Normalized
my $all   = $req->header;

Get an HTTP header value. Header names are normalized to lowercase_underscore format internally. Without arguments, returns the entire headers hashref.

my $value = $req->cookie('session_id');
my $all   = $req->cookie;

Get a cookie value by name. Without arguments, returns the entire cookies hashref.

json

my $data = $req->json;

Returns the parsed JSON body as a Perl data structure. Requires parse_json => 1 route option for JIT optimization.

form_param

my $value = $req->form_param('field');
my $all   = $req->form_param;

Get a form field value (from application/x-www-form-urlencoded body). Without arguments, returns the entire form data hashref. Requires parse_form => 1 route option.

segments

my $segs = $req->segments;  # ['users', '42']

Returns an arrayref of path segments.

id

my $id = $req->id;

Returns the last path segment. Legacy method for simple /resource/:id patterns.

is_json

if ($req->is_json) { ... }

Returns true if the Content-Type header indicates JSON.

is_form

if ($req->is_form) { ... }

Returns true if the Content-Type header indicates form-urlencoded data.

SESSION METHODS

These methods provide session access when sessions are enabled via $server->session_config(). See Hypersonic::Session for details.

session

# Get a session value
my $user = $req->session('user');

# Set a session value
$req->session('user', 'alice');
$req->session('logged_in', 1);

Get or set a session value. When called with one argument, returns the value. When called with two arguments, sets the value and marks the session as modified.

session_data

my $data = $req->session_data;
# { user => 'alice', logged_in => 1, _created => 1234567890 }

Returns the entire session data hashref.

session_clear

$req->session_clear;

Clears all session data. The session cookie will still be sent, but the data will be empty.

session_regenerate

my $new_id = $req->session_regenerate;

Regenerates the session ID. This is a security best practice after authentication (login) to prevent session fixation attacks. The session data is preserved.

RESPONSE HELPERS

These methods create response hashrefs for convenience:

json_response

return $req->json_response({ data => 'value' });
return $req->json_response({ data => 'value' }, 201);

Create a JSON response with optional status code.

text_response

return $req->text_response("Hello World");
return $req->text_response("Created", 201);

Create a plain text response.

html_response

return $req->html_response("<h1>Hello</h1>");

Create an HTML response.

redirect

return $req->redirect('/new-location');
return $req->redirect('/new-location', 301);

Create a redirect response (default 302).

error

return $req->error("Something went wrong", 500);

Create an error response.

not_found

return $req->not_found("User not found");

Create a 404 response.

bad_request

return $req->bad_request("Invalid input");

Create a 400 response.

unauthorized

return $req->unauthorized("Invalid token");

Create a 401 response.

forbidden

return $req->forbidden("Access denied");

Create a 403 response.

SLOT CONSTANTS

For maximum performance, you can access slots directly:

use Hypersonic::Request qw(
    SLOT_METHOD SLOT_PATH SLOT_BODY SLOT_PARAMS
    SLOT_QUERY SLOT_QUERY_STRING SLOT_HEADERS
    SLOT_COOKIES SLOT_JSON SLOT_FORM SLOT_SEGMENTS
);

# Direct array access (fastest)
my $method = $req->[SLOT_METHOD];
my $params = $req->[SLOT_PARAMS];

JIT OPTIMIZATION

Hypersonic analyzes your handlers and only generates parsing code for features actually used. Explicitly enable features for clarity:

$server->get('/search' => sub {
    my ($req) = @_;
    my $q = $req->query_param('q');
    return $req->json_response({ query => $q });
}, {
    dynamic       => 1,
    parse_query   => 1,    # Generate query parsing code
});

$server->post('/api/users' => sub {
    my ($req) = @_;
    my $data = $req->json;
    my $auth = $req->header('Authorization');
    return $req->json_response({ ok => 1 });
}, {
    dynamic       => 1,
    parse_json    => 1,    # Generate JSON parsing code
    parse_headers => 1,    # Generate header parsing code
});

SEE ALSO

Hypersonic - Main HTTP server module

Hypersonic::Response - Fluent response builder

XS::JIT - The JIT compiler

AUTHOR

LNATION <email@lnation.org>

LICENSE

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.