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

vinelab/http

Vinelab HTTP is a lightweight Laravel HTTP client that simplifies sending GET, POST, PUT, PATCH, and DELETE requests, handling headers, query parameters, JSON payloads, authentication, and response parsing through a fluent, expressive API.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install the package:

    composer require vinelab/http
    
  2. Register the service provider (this package predates Laravel package auto-discovery, so add it manually to config/app.php):

    'providers' => [
        // ...
        Vinelab\Http\ClientServiceProvider::class,
    ],
    
  3. Optionally publish the config:

    php artisan vendor:publish --provider="Vinelab\Http\ClientServiceProvider"
    

    This produces config/http.php, where you set defaults like user agent, timeouts, and redirect behaviour.

  4. First request — resolve the client from the container and call a verb:

    use Vinelab\Http\Client;
    
    $client   = app(Client::class);
    $response = $client->get('https://api.example.com/users');
    
    if ($response->statusCode() === 200) {
        $users = $response->json(); // already-decoded array
    }
    

Where to look first: src/Client.php for the request verbs and how parameters are encoded, src/Response.php for the accessor methods (json(), xml(), body(), statusCode()), and config/http.php once published. The response accessors are the whole surface area of the package — read them before writing anything clever.

Best first use case: a thin wrapper around one third-party JSON API in a legacy (Laravel 5.x–5.6 era) application. That is where it fits and where $response->json() saves you a line of boilerplate versus plain Guzzle.

Implementation Patterns

Constructor-inject the client into a service class. The container resolves it automatically, which keeps your code testable and hides the client:

class GitHubApi
{
    public function __construct(private Client $client) {}

    public function repos(string $org): array
    {
        $response = $this->client->get("https://api.github.com/orgs/{$org}/repos");

        return $response->statusCode() === 200 ? $response->json() : [];
    }
}

JSON requests are implicit. Pass an associative array as the params argument and the package encodes it as JSON and sets the content type for you:

$response = $client->post('https://api.example.com/orders', [
    'sku'      => 'ABC-1',
    'quantity' => 2,
]);

For raw bodies (XML, form-encoded strings, pre-serialized JSON) pass a string instead and set the content type through the options/headers argument.

XML round-trip. Pass an XML string and read it back with xml(), which returns a SimpleXMLElement:

$response = $client->post('https://legacy.example.com/soap', $xmlPayload);
$node     = $response->xml()->result->status; // cast to string when comparing

Centralize auth and headers. Rather than repeating tokens on every call, build a small factory or set defaults in config/http.php:

$client = app(Client::class);
$response = $client->get($url, [], [
    'headers' => ['Authorization' => 'Bearer '.config('services.foo.token')],
]);

Status-aware handling. Treat statusCode() as the contract; the convenience of json() is that you don't decode manually, not that errors are handled for you:

$status = $response->statusCode();

return match (true) {
    $status === 200           => $response->json(),
    $status >= 400 && < 500   => throw new ApiClientError($response->body()),
    default                   => throw new ApiServerError($response->body()),
};

Testing. Because the client is container-resolved, bind a fake in your test base class or swap it per test with Mockery:

$this->mock(Client::class, function ($mock) {
    $mock->shouldReceive('get')->andReturn($fakeResponse);
});

Keep a small helper that builds a Response from a fixture body so tests don't hit the network.

Gotchas and Tips

  • Abandoned since 2017. Last release is October 2017 and the Guzzle constraint is old. Expect dependency conflicts on PHP 8 / Laravel 8+. On modern projects use Laravel's Http facade (Illuminate\Support\Facades\Http) instead — it is a strict superset of this package's functionality. Only reach for vinelab/http in projects already pinned to it.
  • Auto-discovery won't fire. You must register ClientServiceProvider by hand; a missing provider shows up as "Target [Vinelab\Http\Client] is not instantiable".
  • No PSR-7 response. Response is a bespoke wrapper, so middleware, Laravel's assertSent helpers, and Guzzle's getBody() idioms don't apply. If you need PSR-7, drop down to Guzzle directly.
  • json() on non-JSON returns null, silently. It does not throw. If an upstream API returns HTML on error (very common with proxies and CDNs), you'll get null and no warning — always check statusCode() before trusting the decoded payload.
  • Connection failures are exceptions, not error responses. The "fault-tolerant" wrapper covers HTTP-level errors, but a DNS failure or refused connection still surfaces as a Guzzle ConnectException. Wrap calls in try/catch (\Exception $e) at the boundary.
  • Set an explicit timeout. The default may allow very long hangs; on a web request that becomes a 504 for your users. Pass ['timeout' => 5, 'connect_timeout' => 2] in the options array.
  • Leave SSL verification on. It's tempting to pass 'verify' => false when hitting staging with a self-signed cert — scope that to a named config value, never to production defaults.
  • XML access needs casting. $response->xml()->status is a SimpleXMLElement; compare as (string) $response->xml()->status or your === checks will mysteriously fail.
  • Debugging raw traffic. When json() returns null, dump $response->body() and $response->statusCode() first. If you need wire-level logs, pass a Guzzle handler option through the options array rather than patching the package.
  • Extension points. The cleanest way to add behaviour (retries, logging, default headers) is to subclass Client, override the verb methods, and rebind Client::class in AppServiceProvider — not to edit files under vendor/.
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