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

Psr7 Laravel Package

workerman/psr7

PSR-7 HTTP message implementation for Workerman, offering interoperable request and response objects for middleware-friendly PHP services on the Workerman event loop. Lightweight and easy to integrate into existing Workerman HTTP applications.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is a PSR-7 (HTTP message interfaces) implementation maintained by the Workerman author. It is not an HTTP client or server — it is the data model for Request, Response, Stream, Uri, and UploadedFile objects, plus helpers to convert between Workerman's native HTTP request/response and PSR-7.

If you are in a plain Laravel app (nginx/php-fpm or Octane on Swoole/RoadRunner/FrankenPHP), you will almost never install this. Reach for it only when you are already inside the Workerman ecosystem — webman, workerman/http-client, or a custom Workerman\Worker HTTP server — and need PSR-7 messages to hand to PSR-15 middleware, a signed-URL/guzzle-based client that consumes PSR-7, or your own framework glue.

composer require workerman/psr7

First things to read in src/:

  • MessageTrait / StreamTrait — the immutable message base everything else composes.
  • ServerRequest (or the equivalent factory in Workerman\Psr7\) — the class that wraps a Workerman Request.
  • Response + Stream — how bodies are written and flushed.
  • Uri — parsing/merging rules that will bite you on query strings.

First use case: wrap an incoming Workerman request into a PSR-7 ServerRequest, run it through a PSR-15 middleware pipeline (e.g. relay/relay), then turn the resulting ResponseInterface back into something Workerman can send().

Implementation Patterns

Bridging a Workerman request into PSR-7. Inside an onMessage callback you typically do something like reconstruct a ServerRequest from the Workerman $request->get(), $request->header(), $request->uri() and $request->post() values. Keep this conversion in a single factory class — do not scatter it across handlers.

Bridging PSR-7 back to Workerman. Iterate getHeaders(), call getBody()->rewind() (or copy it into a Workerman Response's body), then set $response->withStatus($psr->getStatusCode()). This is the piece people forget and end up with zero-length bodies.

Middleware pipelines. Because the objects are standard PSR-7 and (if the package implements it) PSR-15, you can drop in any ecosystem middleware — auth, CORS, request-id — without pulling Guzzle's PSR-7 as a second implementation. This is the main reason to prefer it over writing your own message classes in a Workerman service.

Inside webman. webman's HTTP client and several plugins already use this package's messages; if you write a plugin or a controller that talks to that client, you get ResponseInterface back. $resp->getBody()->getContents() and stream through large downloads rather than casting to string.

Interop with Laravel's kernel. If you genuinely need to call a Laravel controller from a Workerman handler, convert the PSR-7 request to a Symfony Request via symfony/psr-http-message-bridge + nyholm/psr7 (or this package, which is interface-compatible), dispatch through app()->handle(), then convert the Symfony\Component\HttpFoundation\Response back into PSR-7 with the same bridge. Do not try to reuse this package to talk to Laravel's kernel directly — the interfaces are different.

Uploads. Use getUploadedFiles() with moveTo() to persist files; PSR-7 gives you the target path, not a magic storage() helper. Wire this to Laravel's filesystem if you're sharing storage.

Testing. Because messages are immutable and streams are in-memory by default, you can unit-test handlers by constructing requests directly (e.g. new ServerRequest('GET', '/x') plus withHeader(...)) without spinning up a Workerman server. Write a tiny helper that builds a ServerRequest from an array — you will reuse it constantly.

Gotchas and Tips

  • Ten stars, zero dependents. You are effectively the QA team. Pin the version exactly, run your own smoke tests, and be prepared for upstream to move slowly. The release date (2025-03-06) tells you the project is alive but not actively churning.
  • It is a fork-shaped package. Much of the code will look like guzzlehttp/psr7 or nyholm/psr7. Before committing to it, diff surface APIs — often you are better off pulling guzzlehttp/psr7 which has vastly more adoption, a test suite, and downstream tooling. Choose workerman/psr7 only when its Workerman-specific conversion helpers are what you actually need.
  • Immutability. Every with* returns a new object. Forgetting to reassign ($request->withHeader('X', 'y') with the return value dropped) is the #1 silent bug.
  • Streams and rewind. getContents() consumes the stream; call rewind() before re-reading. Reading twice without a rewind will produce an empty string, which is easy to misdiagnose as an empty body.
  • Header casing. PSR-7 header lookups are case-insensitive but storage is not always normalized. If you have downstream code comparing raw header arrays, normalize to lowercase on the way in.
  • Query string merging in Uri::withQueryValue. The Uri implementation here follows the spec quirks (space vs +, duplicate keys, array values). Test with arrays (?a[]=1&a[]=2) from Laravel-generated URLs — round-tripping through PSR-7 sometimes re-encodes them differently.
  • No global server-request factory from $_SERVER. This package is aimed at Workerman, not PHP-FPM. If you need a from-globals factory (e.g. for tests, or bridging into a legacy handler), write it yourself or pull in nyholm/psr7 for that path.
  • Body size and memory. Workerman is long-lived; streams backed by php://temp will grow per request. Close/reset streams after sending responses, and stream large responses in chunks rather than buffering everything into a string.
  • HTTP/2 and withProtocolVersion. Workerman HTTP/2 support is separate; don't assume this package negotiates it for you. If you forward getProtocolVersion(), handle '2' and '2.0' defensively.
  • Debugging tips. When a response comes back empty, log $response->getStatusCode(), count($response->getHeaders()), and (string) $response->getBody() in that order — this distinguishes "wrong response object" from "empty stream" quickly. For requests, log (string) $request->getUri() plus getMethod() before invoking middleware.
  • Extension points. Most integration is expected through implementing Psr\Http\Message\*Interface or composing Workerman\Psr7\* classes; subclassing is rarely necessary and likely to break if the base traits change between minor versions. Keep your conversion layer behind your own interface (WorkermanRequestAdapter, PsrResponseEmitter) so you can swap to guzzlehttp/psr7 or nyholm/psr7 in one file if this package stalls.
  • Laravel-specific reminder. Laravel, Guzzle, and most Laravel ecosystem packages are built on symfony/http-foundation for the server side and psr/http-message for the client side — this library is on the client side of that split. Using it as an ad-hoc Symfony replacement will cost you more than it 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.
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
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource