Skip to content

Commit

Permalink
Add Laravel HTTP Client macros to consume JSON:API documents
Browse files Browse the repository at this point in the history
  • Loading branch information
JaZo committed Feb 22, 2022
1 parent 60c5936 commit b240e42
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 0 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,26 @@ class RecipeController extends Controller

Take a look at [swisnl/json-api-client](https://github.com/swisnl/json-api-client) for more usage information.

### Laravel HTTP Client

You can also use the built-in [HTTP Client](https://laravel.com/docs/http-client) of Laravel if you prefer. Please note this requires Laravel 7+.

``` php
use Illuminate\Support\Facades\Http;
use Swis\JsonApi\Client\Facades\DocumentFactoryFacade;
use Swis\JsonApi\Client\Item;

$recipe = (new Item())
->setType('recipes')
->fill([
'title' => 'Frankfurter salad with mustard dressing',
]);

$document = Http::asJsonApi() // Sets the Content-Type and Accept headers to 'application/vnd.api+json'.
->post('https://cms.contentacms.io/api/recipes', DocumentFactoryFacade::make($recipe))
->jsonApi(); // Parses the response into a JSON:API document.
```


## Service Provider

Expand Down
31 changes: 31 additions & 0 deletions src/Providers/ServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@

namespace Swis\JsonApi\Client\Providers;

use Illuminate\Http\Client\PendingRequest;
use Illuminate\Http\Client\Response;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\ServiceProvider as BaseServiceProvider;
use Swis\JsonApi\Client\Client;
use Swis\JsonApi\Client\DocumentClient;
use Swis\JsonApi\Client\Facades\ResponseParserFacade;
use Swis\JsonApi\Client\Interfaces\ClientInterface;
use Swis\JsonApi\Client\Interfaces\DocumentClientInterface;
use Swis\JsonApi\Client\Interfaces\DocumentInterface;
use Swis\JsonApi\Client\Interfaces\DocumentParserInterface;
use Swis\JsonApi\Client\Interfaces\ResponseParserInterface;
use Swis\JsonApi\Client\Interfaces\TypeMapperInterface;
Expand All @@ -28,6 +33,8 @@ public function register()
$this->registerSharedTypeMapper();
$this->registerParsers();
$this->registerClients();

$this->registerLaravelHttpClientMacros();
}

public function boot()
Expand Down Expand Up @@ -65,4 +72,28 @@ static function (ClientInterface $client) {
$this->app->bind(ClientInterface::class, Client::class);
$this->app->bind(DocumentClientInterface::class, DocumentClient::class);
}

protected function registerLaravelHttpClientMacros(): void
{
if (!class_exists(Http::class)) {
// N.B. The HTTP Client was introduced in Laravel 7.
return;
}

if (!PendingRequest::hasMacro('asJsonApi')) {
PendingRequest::macro('asJsonApi', function (): PendingRequest {
/* @var \Illuminate\Http\Client\PendingRequest $this */
return $this->bodyFormat('json')
->contentType('application/vnd.api+json')
->accept('application/vnd.api+json');
});
}

if (!Response::hasMacro('jsonApi')) {
Response::macro('jsonApi', function (): DocumentInterface {
/* @var \Illuminate\Http\Client\Response $this */
return ResponseParserFacade::parse($this->toPsrResponse());
});
}
}
}
55 changes: 55 additions & 0 deletions tests/Providers/ServiceProviderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

declare(strict_types=1);

namespace Swis\JsonApi\Client\Tests\Providers;

use Illuminate\Http\Client\Request;
use Illuminate\Support\Facades\Http;
use Swis\JsonApi\Client\Document;
use Swis\JsonApi\Client\Tests\AbstractTest;

class ServiceProviderTest extends AbstractTest
{
protected function setUp(): void
{
if (!class_exists(Http::class)) {
$this->markTestSkipped('The Laravel HTTP Client is not available.');
}

parent::setUp();
}

/**
* @test
*/
public function itRegistersHttpFacadeMacroForRequest(): void
{
// arrange
Http::fake();

// act
Http::asJsonApi()->get('https://example.com');

// assert
Http::assertSent(static function (Request $request) {
return $request->hasHeader('Content-Type', 'application/vnd.api+json') &&
$request->hasHeader('Accept', 'application/vnd.api+json');
});
}

/**
* @test
*/
public function itRegistersHttpFacadeMacroForResponse(): void
{
// arrange
Http::fake();

// act
$data = Http::get('https://example.com')->jsonApi();

// assert
$this->assertInstanceOf(Document::class, $data);
}
}

0 comments on commit b240e42

Please sign in to comment.