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

Httpmessage Laravel Package

kambo/httpmessage

kambo/httpmessage is a PHP package for working with HTTP messages in an object-oriented way. It helps you build, inspect, and manipulate requests, responses, headers, and bodies consistently, making HTTP handling cleaner and easier to reuse across applications.

View on GitHub
Deep Wiki
Context7

Getting Started

kambo/httpmessage is a bare PSR-7 implementation — no service provider, no facade, no config file, no Laravel auto-discovery. Installing it does nothing on its own; you only feel it when something in your dependency tree demands a Psr\Http\Message\RequestInterface or ResponseInterface.

composer require kambo/httpmessage

Where to look first

  1. vendor/kambo/httpmessage/composer.json — check the psr/http-message constraint. This package predates PSR-17/PSR-18, so it almost certainly pins ^1.0. If any other package in your app needs psr/http-message:^2.0, Composer will refuse to resolve and this package is a non-starter for that project.
  2. The class list under Kambo\HttpMessage\ — expect the usual five: Request, Response, Stream, Uri, UploadedFile, plus a ServerRequest. Read the actual constructor signatures from the source; they are not guaranteed to match the canonical ($method, $uri, $headers, $body, $version) ordering used by Guzzle/Nyholm.
  3. The README, for factory helpers. If there is no PSR-17 *FactoryInterface implementation, plan on writing thin adapters yourself.

First use case

The realistic entry point is "a library handed me an interface, not an object." For example, a PSR-15 middleware stack, an OAuth2 server implementation, or an HTTP client decorator that type-hints PSR-7. Smoke-test it in Tinker:

$response = new Kambo\HttpMessage\Response(200, ['Content-Type' => 'application/json']);
$response->getBody()->write(json_encode(['ok' => true]));

echo $response->getStatusCode();          // 200
echo $response->getHeaderLine('Content-Type');
echo (string) $response->getBody();       // {"ok":true}

If that round-trips cleanly, the package does its one job.

Implementation Patterns

Treat it as an adapter layer, not a framework citizen. Laravel speaks Illuminate\Http\Request/Response (Symfony HttpFoundation). Kambo speaks PSR-7. Any use of this package is a translation at the boundary.

// PSR-7 response -> Laravel response (controller return value)
public function show(ResponseInterface $psrResponse): \Illuminate\Http\Response
{
    return response(
        (string) $psrResponse->getBody(),
        $psrResponse->getStatusCode(),
        $psrResponse->getHeaders()   // note: values are string[]
    );
}

Inbound: Laravel request -> PSR-7. The standard tool is symfony/psr-http-message-bridge, but its PsrHttpFactory constructor wants PSR-17 factories. Since Kambo likely ships none, write a small factory class that wraps the Kambo constructors and implements Psr\Http\Message\RequestFactoryInterface, StreamFactoryInterface, and UploadedFileFactoryInterface. Register it as a singleton so the bridge can be injected:

// app/Providers/AppServiceProvider.php
$this->app->singleton(\Psr\Http\Message\RequestFactoryInterface::class, \App\Http\KamboRequestFactory::class);
$this->app->singleton(\Psr\Http\Message\StreamFactoryInterface::class,  \App\Http\KamboStreamFactory::class);
$this->app->singleton(\Symfony\Bridge\PsrHttpMessage\HttpFoundationFactoryInterface::class, ...);
$this->app->singleton(\Symfony\Bridge\PsrHttpMessage\PsrHttpFactory::class);

Immutability discipline. Every with* method returns a clone. The pattern is always reassign:

$request = $request
    ->withMethod('POST')
    ->withHeader('Authorization', 'Bearer ' . $token)
    ->withBody($stream);

Never assume $request->withHeader(...) mutated $request in place — that is the single most common source of "my header/body never arrived" bugs.

Outbound calls. Guzzle already returns PSR-7 responses, so you rarely need Kambo for outbound traffic. Where it earns its keep is when you need to construct the request yourself and hand it to a client that takes a RequestInterface:

$request  = new Kambo\HttpMessage\Request('GET', new Kambo\HttpMessage\Uri('https://api.example.com/v1/items'));
$response = $client->sendRequest($request); // PSR-18 client

Testing. A lightweight, dependency-free PSR-7 stub is genuinely useful in unit tests — you can assert on what your code did to a message without booting Guzzle:

$fake = new Kambo\HttpMessage\Response(200, [], '{"id":1}');
$handler = new YourService($fake);
$this->assertSame('application/json', $handler->contentTypeOf());

Decorators for logging. Because everything is an interface, wrap a Kambo message in your own ResponseInterface decorator that logs on getBody()/getStatusCode(). That's the clean extension point — don't subclass and override with* methods, since the clone will lose your subclass's state.

Gotchas and Tips

  • Stale dependency. Last release is January 2018, five stars, zero dependents. It predates PSR-17 (factories) and PSR-18 (clients), so it will not slot into modern auto-wiring. Expect to hand-roll factories.
  • PSR-7 v1 lock. psr/http-message 2.0 added native return types to the interfaces. A 2018-era implementation almost certainly does not satisfy ^2.0. Pin "psr/http-message": "^1.0" and accept that you're blocking upgrades for the rest of the tree. Run composer why psr/http-message before committing to this.
  • PHP 8 friction. The code was written against PHP 7.0/7.1. Watch for implicit nullable parameters (Type $x = null) deprecations, and for __toString() implementations that don't handle exceptions — PHP 7.4+ forbids throwing from __toString().
  • Stream pointer state. After write(), the pointer sits at the end. getContents() returns an empty string. Either call rewind() first or cast: (string) $response->getBody(). Kambo's Stream::__toString() may or may not rewind for you — verify before relying on it.
  • getHeaders() shape. getHeader() returns string[], getHeaderLine() returns a comma-joined string, getHeaders() returns string[][]. Passing getHeaders() straight into Laravel's response() works; passing getHeader() does not.
  • Host header. withUri($uri, $preserveHost = false) is the only way the Host header is re-derived. If you build a request and then swap the URI, the old host sticks unless you pass true or don't preserve it.
  • Uploaded file nesting. ServerRequest::getUploadedFiles() should return UploadedFileInterface[] with nested arrays mirroring name="form[file]". Flat implementations silently break multi-file forms.
  • Debugging. Do not var_dump or json_encode a PSR-7 message — bodies are streams and won't serialize. Always inspect via getStatusCode(), getHeaders(), and (string) $body.
  • Extension points worth using: inject the interfaces (RequestInterface, ResponseInterface) rather than the concrete Kambo classes, so you can swap in nyholm/psr7 later without touching call sites.
  • Honest recommendation. For greenfield Laravel work, reach for nyholm/psr7 (tiny, actively maintained, PSR-17 compliant) or guzzlehttp/psr7 (already present if you use Guzzle). Choose kambo/httpmessage only when it's already transitively installed and you need one more message object, or when the "zero extra dependencies" trade-off genuinely matters. The absence of PSR-17 factories alone usually costs more in glue code than the package saves.
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