HTTP requests are classes

Let's say you want to make an HTTP query from a Laravel application. It will probably look something like this:

<?php

// Bunch of imports...

class TestServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->when(TestController::class)
            ->needs(Client::class)
            ->give(function () {
                return new Client([
                    'base_uri' => 'https://rust-lang.org',
                ]);
            });
    }
}

class TestController extends Controller
{
    protected Client $client;

    public function __construct(Client $client)
    {
        $this->client = $client;
    }

    public function test()
    {
        return (string) $this->client->request('GET', 'learn')
            ->getBody();
    }
}

At first, it seems normal: we use dependency injection to prepare an HTTP client instance instead of configuring it every time we want to send a request.

However, this HTTP client isn't bounded by anything at all.

Instead, we can write something like...

<?php

// Other imports...
use Ivan770\HttpClient\Request\Request;

class LearnRequest extends Request
{
    protected $resource = "https://rust-lang.org/learn";
}

class TestController extends Controller
{
    public function test(LearnRequest $learnRequest)
    {
        return $learnRequest->get();
    }
}

As you can see, we moved all details about the HTTP request into the separate class, and all we have to do to receive a response is to call the get method.

This method automatically converts a raw HTTP response to Illuminate\Support\Collection (if it's possible), or returns a Symfony response class instance otherwise (you can also use the getRawContent method to retrieve it).

But that example was fairly simple - no headers, authentication, etc. What about something a bit more complicated?

<?php

// Other imports...
use Ivan770\HttpClient\HttpClient;
use Ivan770\HttpClient\Request\Request;

class LearnRequest extends Request
{
    protected $resource = "https://httpbin.org/post";

    protected $method = "POST";

    protected function defaultAttach(HttpClient $client)
    {
        // https://github.com/ivan770/laravel-httpclient/blob/master/src/HttpClient.php
        $client->authBearer("MyCoolToken")
            ->headers([
                "hello" => "world"
            ]);
    }
}

class TestController extends Controller
{
    public function test(LearnRequest $learnRequest)
    {
        return $learnRequest->get();
    }
}

And how is that different from just creating a new HTTP client instance every time you want to send a request?

With LearnRequest encapsulating all HTTP request details, you only have to call the get method to retrieve a response information, without worrying about the request specifics.

Of course, you may need to pass some local information to an HTTP request before sending it. For example, we can add a Bearer token to the request before running it:

<?php

// Other imports...
use Ivan770\HttpClient\HttpClient;
use Ivan770\HttpClient\Request\Request;

class LearnRequest extends Request
{
    protected $resource = "https://httpbin.org/post";

    protected $method = "POST";

    protected function defaultAttach(HttpClient $client)
    {
        $client->headers([
            "hello" => "world"
        ]);
    }
}

class TestController extends Controller
{
    public function test(LearnRequest $learnRequest)
    {
        return $learnRequest->authBearer("TestToken")
            ->get();
    }
}

You can also add custom methods to your HTTP request classes to encapsulate authentication token management, headers, etc.