Skip to content

Stdlib: request_parse_body() — PHP 8.4 HTTP body parser without superglobals (ext/standard/http.c) #5965

Description

@PurHur

Category

stdlib

Problem

PHP 8.4 adds request_parse_body(string $body, array $options = []): array — parse application/x-www-form-urlencoded and multipart/form-data payloads without populating $_POST / $_FILES. CLI tools, unit tests, and middleware use it to inspect raw HTTP bodies.

This compiler has no such function (function_exists('request_parse_body') → false). Multipart support exists for CGI (lib/Web/ populates $_POST/$_FILES) but not as a standalone API.

PHP 8.4 also adds RequestParseBodyException (extends Exception) for malformed bodies — must be registered before the function ships.

php-src reference

Repro (undefined function today)

test/repro-maintainer/maintainer_request_parse_body.php:

<?php
declare(strict_types=1);

// URL-encoded
$body = "a=1&b=two";
$result = request_parse_body($body);
var_export($result);
echo "\n";

// Multipart (minimal)
$boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW';
$multipart = "--$boundary\r\n"
    . "Content-Disposition: form-data; name=\"field\"\r\n\r\n"
    . "value\r\n"
    . "--$boundary--\r\n";
$result2 = request_parse_body($multipart, ['content_type' => "multipart/form-data; boundary=$boundary"]);
var_export($result2['post']['field'] ?? 'missing');
echo "\n";
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh
php test/repro-maintainer/maintainer_request_parse_body.php 2>&1 | head -5   # Zend 8.4+
php bin/vm.php test/repro-maintainer/maintainer_request_parse_body.php 2>&1 | head -2
'
Runtime Result
Zend PHP 8.4+ array ('post' => array ('a' => '1', 'b' => 'two'), 'files' => array ()) + multipart value
bin/vm.php Call to undefined function request_parse_body()

Exception class probe

test/repro-maintainer/parity_request_parse_body_exception.php (Zend 8.4+ only):

<?php
declare(strict_types=1);
var_dump(class_exists('RequestParseBodyException'));
try {
    throw new RequestParseBodyException('malformed body');
} catch (RequestParseBodyException $e) {
    echo 'caught:', $e->getMessage(), "\n";
}

On Zend 8.4+: class_exists true and typed catch works. VM must match when implementing #5965 (do not ship function without exception class).

Scope (this repo)

Module Path
Parser core reuse/adapt lib/Web/MultipartParser.php → shared VmHttpBodyParser
Builtin ext/standard/request_parse_body.php
Exception register RequestParseBodyException in ext/standard/ThrowableManifest.php (or sibling)
Registration ext/standard/Module.php
Options content_type, max_parts, max_input_vars parity subset per php-src
Tests test/compliance/cases/stdlib/request_parse_body_urlencoded.phpt, request_parse_body_multipart.phpt, request_parse_body_exception.phpt
JIT/AOT VM-first v1

PHP-in-PHP: parser logic in ext/ + lib/Web/; C only for unavoidable platform I/O (none for string-in API).

Done when (php-src-strict)

  • function_exists('request_parse_body') true; URL-encoded repro matches Zend return shape
  • Multipart repro populates post + files nested arrays like Zend
  • RequestParseBodyException registered; malformed body throws it (not generic Exception)
  • Invalid content_type / malformed body errors match Zend (ValueError / RequestParseBodyException per php-src)
  • ./script/ci-fast.sh --filter request_parse_body green

Verification

./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && vendor/bin/phpunit --filter request_parse_body'

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:vmVirtual machinearea:webWeb / CGI / superglobalsenhancementNew feature or requestimplementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claimphase-4:stdlibPhase 4 – stdlib for web apps

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions