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

Shadowfax Laravel Package

huang-yi/shadowfax

Shadowfax is a Laravel package for sending HTTP requests concurrently, making it easy to run multiple requests in parallel and handle responses efficiently. Built on Guzzle, it offers a simple API to reduce wait times when your app depends on several external services.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Check prerequisites before anything else. Shadowfax needs the Swoole PHP extension (or OpenSwoole) compiled in, plus a Laravel version whose Illuminate\Foundation\Http\Kernel is compatible with the package. Verify with php -m | grep -i swoole and php --ri swoole. The last tagged release was January 2022, so it targets Laravel 8-ish — on newer Laravel versions you may need to pin laravel/framework or fork the package.
  2. Install and publish.
    composer require huang-yi/shadowfax
    php artisan vendor:publish --provider="HuangYi\Shadowfax\ShadowfaxServiceProvider"
    
    This gives you config/shadowfax.php. Read it first — it is the fastest way to understand how the package maps Swoole server options, worker counts, and host/port to your app.
  3. Start the server with the provided artisan command (typically php artisan shadowfax:serve). Point a browser at http://127.0.0.1:<port> (the default in the config). If you are used to Nginx + PHP-FPM, this single process is now your web tier.
  4. First real use case: high-throughput JSON/API endpoints. Shadowfax bootstraps the Laravel container once per worker and reuses it across requests, which removes the framework boot cost that dominates short PHP-FPM requests. Bench a simple /api/ping route under ab or wrk before and after to confirm the win on your machine.
  5. Where to look in the source when behavior surprises you: the service provider (what it swaps into the container), the Server/kernel wrapper (how it builds Illuminate\Http\Request from Swoole\Http\Request and writes Swoole\Http\Response), and the artisan command (what options it exposes). Those three files explain 90% of the package.

Implementation Patterns

  • Keep the boot-once model in mind. Unlike PHP-FPM, your AppServiceProvider::boot, config loading, and autoloading run once per worker, not once per request. Treat service-provider code as long-lived: do expensive setup there, but do not capture request state in it.
  • Bind per-request work, not per-worker work. If you register singletons, ask whether the object holds request-scoped data (current user, request ID, locale). Anything user- or request-specific should be resolved in middleware/controllers or bound as a scoped instance, not stored on a singleton.
  • Middleware is your reset layer. A common pattern is a lightweight middleware that clears or re-binds stateful services at the start of each request (auth guards, translation locale, Request::setUserResolver, etc.). This keeps long-lived workers behaving like fresh PHP-FPM requests without giving up the performance gain.
  • Coroutine-friendly IO only. If you enable Swoole's coroutine runtime (Swoole\Runtime::enableCoroutine() or the equivalent config flag), your database/Redis/HTTP clients must be coroutine-safe. Use Swoole-aware clients or connection pools (e.g. Redis/PDO pools) rather than the default Laravel drivers, which hold a single blocking connection per worker.
  • Split web and worker processes. Serve HTTP with Shadowfax in one process group and keep php artisan queue:work, scheduled commands, and websocket/background jobs in separate, ordinary PHP processes. Do not try to run the queue worker inside the Swoole HTTP workers — a blocking job will stall every request that worker handles.
  • Config and route caching still apply. Run php artisan config:cache and php artisan route:cache before deploying. Because the app boots once, cached config is read a single time — a change requires a worker restart (php artisan shadowfax:reload or sending SIGTERM/SIGUSR1 to the master, depending on what the package wires up).
  • Deployment pattern. Run the Swoole server behind Nginx or a load balancer for TLS termination, static files, and health checks, and set worker_num to roughly CPU cores for CPU-bound apps (more if you lean on coroutine IO). Use systemd or Supervisor to keep the master process alive and to restart on deploy.
  • Feature flags and gradual migration. You can run Shadowfax only for a subset of routes while the rest stays on FPM during a migration — just front both with the same load balancer and route by path or header.

Gotchas and Tips

  • Static state bleeds across requests. Any static property on a class, $_SERVER/$_ENV mutation, or cached singleton holding a Request will leak to the next user on the same worker. This is the #1 source of "works locally, corrupts in production" bugs with Swoole-backed Laravel. Audit your own service providers and middleware for statics.
  • app()->forgetInstance() is your friend when debugging. If a test passes alone but fails under load, suspect a stale binding. Reproduce by hitting the same worker repeatedly (keep the connection alive) and inspecting the resolved instance.
  • Blocking calls freeze the worker. A synchronous file_get_contents on a remote URL, a big sleep, or a heavy report will block all requests assigned to that coroutine/worker. Move them to a queue or make them async.
  • File uploads and streaming responses are the usual compatibility gaps. Verify $request->file(), StreamedResponse, and large response()->download() behavior explicitly — the Swoole response object does not behave identically to the FPM SAPI.
  • Don't rely on $_SERVER/$_FILES/php://input. Use Laravel's Request API. Shadowfax constructs the request from the Swoole request object, and superglobals may be stale or empty.
  • Config changes need a restart. With boot-once semantics, editing config/*.php or .env has no effect until you reload workers. Same for package discovery after composer require.
  • Version pinning is essential. Given the 2022 last release, pin the package and Laravel versions together and run your full test suite under the Swoole server (APP_ENV=testing hitting the real port) rather than only via phpunit with the FPM test client. Differences in header casing, cookies, and Content-Length handling show up only there.
  • Logging and error handling can be swallowed. Swoole's worker lifecycle differs from FPM's shutdown; make sure exceptions surface. Configure a Monolog channel that flushes and check the package's error hook (often on('WorkerError') or a custom exception handler) so a crashing worker is loud, not silent.
  • Memory grows if you cache per-request data in globals. Watch memory_get_usage() per worker over time, set max_request in the Swoole options (e.g. 500–1000) to recycle workers, and avoid accumulating entries in static arrays. A periodic worker restart masks leaks but is not a fix.
  • Extension points. The service provider is designed to be extended — you can override the kernel wrapper or the request factory by rebinding the relevant container keys. If a Laravel feature misbehaves, look there before patching vendor/. Forking is realistic on modern Laravel; a shallow fork that keeps the server and request/response adapters while dropping stale framework assumptions is usually cheaper than fighting the pinned version.
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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package