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

Yurun Http Laravel Package

yurunsoft/yurun-http

YurunHttp is a feature-rich PHP HTTP client with Curl, Swoole, and Socket drivers. It supports synchronous and asynchronous requests, coroutines, HTTP/2, WebSocket, uploads/downloads, cookies, redirects, proxies, retries, and a simple consistent API for API clients, crawlers, and service integration...

View on GitHub
Deep Wiki
Context7

Getting Started

composer require yurunsoft/yurun-http

There is no service provider, facade, or config file — it is a plain PHP library. You instantiate Yurun\Util\HttpRequest and chain options onto it, then call a verb method. The first thing to read is the README's chain-method examples and src/HttpRequest.php, because the public API is the setter list.

Minimal call:

use Yurun\Util\HttpRequest;

$response = (new HttpRequest)
    ->timeout(10)
    ->header('Accept', 'application/json')
    ->get('https://api.example.com/users');

$status = $response->getStatusCode();
$data   = $response->json();      // decoded array
$raw    = $response->body();      // string
$headers = $response->headers();  // array

Chained POST with automatic JSON encoding:

$response = (new HttpRequest)
    ->timeout(10)
    ->header('Authorization', 'Bearer '.$token)
    ->bodyFormat('json')
    ->post('https://api.example.com/users', ['name' => 'yurun']);

First realistic use case: as a drop-in replacement for Guzzle in a Laravel app running under Octane/Swoole, where Guzzle's blocking cURL calls pin the worker. Swapping to the Swoole handler lets requests yield the coroutine instead of blocking, with no other change to your call sites.

Implementation Patterns

Bind a configured, transient client in the container. Do not make it a singleton — the instance carries cookies and mutated options.

// AppServiceProvider::register()
$this->app->bind(HttpRequest::class, function () {
    return (new HttpRequest)
        ->timeout(10)
        ->connectTimeout(3)
        ->header('User-Agent', 'myapp/1.0');
});

Wrap it behind your own interface, not scattered through controllers. This is the single most valuable pattern, because it is the only way to make the client mockable (see Gotchas) and it gives you one place to add logging, tracing IDs, and metrics.

final class ExampleApi
{
    public function __construct(private HttpRequest $http) {}

    public function createUser(array $payload): array
    {
        $res = $this->http->bodyFormat('json')
            ->post(config('services.example.url').'/users', $payload);

        if ($res->getStatusCode() >= 400) {
            throw new ApiException($res->body(), $res->getStatusCode());
        }

        return $res->json() ?? [];
    }
}

Choose the handler once, at bootstrap. The handler (cURL vs Swoole) is effectively process-global for HttpRequest defaults; set it in a service provider or bootstrap/app.php, never mid-request:

use Yurun\Util\YurunHttp;
YurunHttp::setDefaultHandler(YurunHttp::HANDLER_SWOOLE);

Fan out with Swoole coroutines — this is where the package earns its keep versus Guzzle:

use Swoole\Coroutine;
use Yurun\Util\HttpRequest;

Coroutine\run(function () {
    $results = [];
    foreach ($urls as $i => $url) {
        Coroutine\create(function () use ($url, $i, &$results) {
            // one client per coroutine
            $results[$i] = (new HttpRequest)->timeout(10)->get($url)->json();
        });
    }
});

Queued jobs: create the client inside handle(), not as a constructor-injected property on a long-lived job class, so retries and worker reuse start clean.

Cookie-aware flows (login then scrape): keep one HttpRequest instance across the sequence and use its cookie manager; the jar persists per instance.

Retry/timeout policy: put ->timeout() and ->retry() in the container binding so every caller inherits sane limits rather than relying on memory.

Gotchas and Tips

  • 4xx/5xx do not throw. The library throws only on transport-level failures. You must check getStatusCode() yourself — forgetting this is the classic silent-bug source, and errors get cached as if they were successful payloads.
  • No Http::fake() equivalent. There is no test double, no recorded-transport hook, and no middleware pipeline. Inject a your-own interface and fake that in tests, or point a configurable base URL at a local stub server.
  • State leaks under Octane. Cookies, headers, and options live on the instance. A container singleton will happily send user A's Authorization header to user B's request. Bind as bind, not singleton, and never share a client across coroutines.
  • Swoole handler needs a coroutine context. Calling it from a plain FPM request, an artisan command, or outside Co\run fails or silently falls back. Guard the handler selection on extension_loaded('swoole') and on actually being in a coroutine.
  • Set a connect timeout explicitly. An unset connect timeout means a hung upstream can hold a worker indefinitely; that is far worse under Octane than under FPM.
  • Retries replay the whole request. ->retry() is not idempotency-aware — never let it retry a POST that charges a card, or add an idempotency key upstream.
  • SSL verification is on by default; keep it on. If you hit certificate errors, fix the CA bundle (common on Alpine/slim images) rather than disabling verification. If you must, scope it to local dev config only.
  • Redirects: the cURL handler follows them and preserves cookies across hops by default. Check getHeaderLine('Location') semantics if you need the intermediate response, and cap max redirects for hostile upstreams.
  • Large bodies land in memory. For file downloads or big API dumps, prefer writing to disk / streaming over pulling body() into a variable, especially in a worker that serves many requests.
  • Multipart uploads need real CURLFile objects, and the Swoole handler's accepted form differs from cURL's. Test uploads against both handlers if you switch between FPM and Octane.
  • Debugging: dump getStatusCode(), headers(), and the error fields on the response object before the body — a truncated body usually means a transport error, not a parsing problem. Verbose cURL output is only reachable through the pass-through options array, so log status + timing from your wrapper instead.
  • Extension points are thin. There is no event system; if you need instrumentation, subclass HttpRequest or (better) decorate your own wrapper. Custom handlers are possible but are a big lift for a one-off need — reach for Guzzle if you need a middleware ecosystem.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings