Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Http Server Form Parser Laravel Package

amphp/http-server-form-parser

Parses application/x-www-form-urlencoded and multipart/form-data request bodies for amphp/http-server, giving handlers easy access to submitted form fields and uploaded files with a simple, asynchronous API.

Deep Wiki
Context7

Getting Started

Install alongside an existing amphp/http-server v3 application:

composer require amphp/http-server-form-parser

You need PHP 8.1+ and amphp/http-server v3. The package is tiny; start by reading src/Form.php, src/File.php, and src/StreamingFormParser.php. The public surface is essentially three things: a parser you instantiate, a Form value object, and File objects for uploads.

A first handler looks like this:

use Amp\Http\Server\FormParser\StreamingFormParser;
use Amp\Http\Server\Request;
use Amp\Http\Server\Response;
use Amp\Http\Server\RequestHandler\ClosureRequestHandler;

$formParser = new StreamingFormParser();

$router->addRoute('POST', '/contact', new ClosureRequestHandler(
    function (Request $request) use ($formParser): Response {
        $form = $formParser->parseRequest($request);

        $name  = $form->getValue('name');
        $email = $form->getValue('email');

        if ($name === null || $email === null) {
            return new Response(422, [], 'Missing fields');
        }

        return new Response(200, [], "Thanks, {$name}");
    }
));

The first realistic use case is a contact/login/upload form: parse application/x-www-form-urlencoded or multipart/form-data, pull scalar values with getValue() and uploaded files with getFile(). Older releases exposed Form::fromRequest($request); if you are on a pre-v2 version, check the README and use that entry point instead.

Implementation Patterns

  • Create the parser once, reuse it. Instantiate StreamingFormParser at application boot and inject it into handlers or a shared container. It is stateless per request.

  • Parse per request, not globally. Call parseRequest($request) at the top of the handler that owns form handling. Avoid a blanket middleware that parses every request; most routes don’t need it and body parsing can be expensive.

  • Single value vs. multi-value. Use getValue('field') for the common case. When a form can repeat a name (checkboxes, multi-selects), use getFields()['field'] ?? [] and iterate. Uploads follow then same shape: getFiles()['attachments'] ?? [], each item a File.

  • Stream uploads to disk instead of buffering. File::getContents() returns a ReadableStream. For anything larger than trivial, pipe it straight to an Amp\File\WritableFile or object storage rather than calling buffer():

    $file = $form->getFile('avatar');
    if ($file !== null) {
        $target = Amp\File\openFile($path, 'w');
        Amp\ByteStream\pipe($file->getContents(), $target);
    }
    
  • Keep validation in your own layer. The parser gives you strings and streams, not typed data. Convert to DTOs, run your validator, and only then touch the database or filesystem.

  • Compose with Router and ClosureRequestHandler/custom handlers. This package has no framework integration; it is a low-level primitive inside the Amp request lifecycle. The idiomatic flow is: router → handler → parser → validate → respond.

  • Testing pattern. Build a Request with a body stream containing the encoded form, invoke the handler, and assert on the Response. This is fast and avoids a live server. For multipart tests, generate bodies with curl once and store fixtures, or construct them manually with the correct boundary.

  • Use route-level guards. Parse form data only after method/content-type checks, e.g. reject GET and non-form Content-Type before invoking the parser.

Gotchas and Tips

  • The request body is single-use. If any middleware or earlier code reads $request->getBody(), the form parser will see an empty or broken body. Parse once and pass the resulting Form around, not the Request.
  • Watch default body-size limits. amphp/http-server commonly runs with ClientBodySizeMiddleware; multipart uploads that exceed it will be rejected before your handler sees them. Tune or disable that middleware deliberately, and add your own file-size checks.
  • Streams must be consumed before the request lifecycle ends. File::getContents() is backed by the request body. If you return a response and try to read the stream later (background job, queued upload), you may get a closed stream. Copy or persist the file inside the handler.
  • Duplicate field names produce arrays, not last-wins. Laravel/Symfony developers expecting getValue() to return the final occurrence can be surprised. Always check getFields() when names may repeat.
  • Nested bracket syntax is not interpreted. user[name] remains the literal key user[name]; there is no PHP-style array expansion. Flatten in your application or use explicit field names.
  • Content-Type matters. multipart/form-data with a missing/mismatched boundary, or an unsupported content type, will produce an empty form or a parse exception depending on version. Catch parse failures and return 400 rather than letting them bubble to a 500.
  • Run inside the event loop/fiber. Parsing suspends while reading the body. Calling it from a non-fiber context or outside an Amp request will fail or block the loop. Keep handler code fiber-safe.
  • Filename and MIME trust. File::getName() and getMimeType() come from the client. Never use the raw filename as a destination path; generate your own and validate MIME by sniffing content.
  • Low adoption, slow cadence. Last release was August 2023 with a modest star count. The API is small and stable, but don’t expect frequent fixes. Pin the version, read the source when behavior is unclear, and keep a fallback plan (raw multipart parsing or a different framework integration) for edge cases.
  • Debugging tip. When a form unexpectedly arrives empty, log the request method, Content-Type, Content-Length, and whether the body stream was already consumed. Reproduce with curl -F and curl --data-urlencode separately; URL-encoded and multipart paths fail differently.
  • Extension points are minimal. There is no plugin system; customization happens in your handler and through amphp/http-server middleware (body limits, timeouts, compression). Treat the parser as a narrow utility, not a form framework.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console