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 Laravel Package

overtrue/http

overtrue/http provides a simple, expressive HTTP client for PHP, making GET/POST requests, JSON handling, headers, and response parsing easy. It works in standalone PHP and Laravel projects, offering a lightweight alternative to heavier HTTP clients.

Deep Wiki
Context7

Getting Started

overtrue/http is a thin, expressive wrapper around Guzzle. It does not ship its own transport — it composes guzzlehttp/guzzle and exposes a smaller, Laravel-Http-like surface. That single fact drives most of the assessment below: the value you get is ergonomics, and the cost is one more dependency between you and Guzzle.

Install it like any Composer package:

composer require overtrue/http

Before writing code, open the following in this order:

  1. README.md — the canonical usage examples; short and the fastest path to a working request.
  2. src/ — typically a Client/Http entry class plus a Response wrapper. Confirm the exact class name and static methods, since the wrapper is small enough to read end-to-end in a few minutes.
  3. composer.json — check the pinned Guzzle major version; this determines which request options you can pass through.

A first use case worth running — hit an echo endpoint and inspect the wrapped response:

use Overtrue\Http\Http; // confirm class from README

$response = Http::get('https://httpbin.org/get', [
    'query' => ['foo' => 'bar'],
    'timeout' => 10,
]);

$status = $response->getStatusCode();
$body   = $response->getBody()->getContents();
$json   = json_decode($body, true);

If a static call feels too magic for your codebase, instantiate the client directly and inject it — the wrapper is stateless enough to be treated as a normal service.

Implementation Patterns

Instance client as a configured service. The wrapper shines when you need one pre-configured client reused across a service class (base URI, auth header, timeout, user agent). Bind it once in your container and inject it; do not scatter Http::get(...) calls with repeated headers across the codebase.

use Overtrue\Http\Client;

$client = new Client([
    'base_uri' => 'https://api.example.com/',
    'timeout'  => 15,
    'headers'  => [
        'Authorization' => 'Bearer '.config('services.api.token'),
        'Accept'        => 'application/json',
    ],
]);

$users = $client->get('users', ['query' => ['page' => 2]]);

Pass Guzzle options through. The wrapper forwards query, json, form_params, body, headers, auth, timeout, connect_timeout, verify, proxy, cookies, and allow_redirects directly to the underlying Guzzle request. This is your real API surface — treat the wrapper's own method list as sugar and Guzzle's docs as the reference.

Response wrapper for JSON APIs. For internal APIs, wrap the raw call in a small method that enforces status checks and returns decoded data, rather than leaking the PSR-7 response up the stack:

public function fetchUsers(): array
{
    $response = $this->client->get('users');

    if ($response->getStatusCode() >= 400) {
        throw new RuntimeException('Upstream error: '.$response->getBody());
    }

    return json_decode((string) $response->getBody(), true);
}

Laravel integration. Because the package predates the built-in Illuminate\Support\Facades\Http (7.x+) and mirrors it closely, the sensible pattern in a modern Laravel app is either (a) skip the package entirely and use the framework facade, or (b) register the client as a singleton in a service provider and inject it where you need instance-level config:

$this->app->singleton(Client::class, fn () => new Client([
    'base_uri' => config('services.upstream.base_uri'),
    'timeout'  => 10,
]));

Middleware / handler stack. If you need retries, logging, or tracing, reach for Guzzle's handler stack via the underlying client. The wrapper does not abstract this away, so you keep full control — but you also need to know where the wrapper exposes the Guzzle client.

Non-Laravel projects. This is the honest home turf for the package: small PHP services, CLI tools, legacy apps where you want Http::get(...) ergonomics without pulling in the full framework.

Gotchas and Tips

  • Stale maintenance is the headline risk. The last tagged release is March 2022. Before adopting, check for open issues around current Guzzle/PHP versions and confirm the composer.json constraints allow your Guzzle major. If they don't, you're pinning an old Guzzle — usually a non-starter.
  • It is redundant in modern Laravel. Laravel's Http facade covers everything this package does and is maintained with the framework. Adopt overtrue/http only for non-Laravel contexts or legacy codebases already using it.
  • Know your exceptions. Guzzle throws GuzzleHttp\Exception\ConnectException, RequestException, and ClientException on network/4xx-5xx failures depending on the http_errors option. Confirm what the wrapper sets by default — if http_errors is enabled, a 500 throws instead of returning a response. That surprise is the most common "why didn't my response come back" bug.
  • Body streams are one-shot. getBody()->getContents() consumes the stream. If you echo it once for logging and again for parsing, the second read returns empty. Cast to (string) $response->getBody() to rewind, or read once and store the string.
  • Don't disable TLS verification outside tests. 'verify' => false is tempting when debugging internal endpoints; keep it out of production config and fix the CA bundle instead.
  • json vs form_params is a real trap. Using form_params for a JSON API silently sends application/x-www-form-urlencoded and upstream may respond with a confusing 415 or 400. When in doubt, set the Content-Type header alongside json.
  • Timeouts are per-request, not global. Default Guzzle timeouts are unbounded or very large depending on version. Always set timeout and often connect_timeout in the client config — otherwise one hung upstream can pin a queue worker indefinitely.
  • Static calls are not mock-friendly. If you're writing tests, prefer instance-based injection so you can substitute a fake client. Static facades make it easy to write code and painful to test.
  • Extension point = Guzzle. Anything the wrapper doesn't expose (async via Pool, retries, streaming downloads) is reachable through the underlying client or by dropping the wrapper and using Guzzle directly. Given the package size, "drop the wrapper" is a legitimate refactor path if you find yourself fighting it.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
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