본문으로 건너뛰기
버전: 10.x
Laravel 10.x · 한국어 문서https://laravel.com/docs/10.x/http-client

HTTP Client

Introduction​

Laravel은 Guzzle HTTP client를 감싸서, 간단하고 직관적인 API를 제공합니다. 이를 통해 다른 웹 애플리케이션과 신속하게 HTTP 요청을 주고받을 수 있습니다. Laravel의 Guzzle 래퍼는 가장 자주 사용되는 사례에 초점을 맞췄으며, 개발자 경험을 극대화했습니다.

시작하기 전에, 애플리케이션의 의존성으로 Guzzle 패키지를 설치했는지 확인해야 합니다. 기본적으로 Laravel에서는 이 의존성을 자동으로 포함합니다. 만약 Guzzle 패키지를 삭제했다면, 아래 Composer 명령어로 다시 설치할 수 있습니다:

composer require guzzlehttp/guzzle

Making Requests​

Http 파사드가 제공하는 head, get, post, put, patch, delete 메서드를 통해 HTTP 요청을 보낼 수 있습니다. 먼저, 다른 URL로 기본적인 GET 요청을 보내는 방법을 살펴보겠습니다:

use Illuminate\Support\Facades\Http;

$response = Http::get('http://example.com');

get 메서드는 Illuminate\Http\Client\Response 인스턴스를 반환합니다. 이 객체는 다양한 메서드를 제공하여 응답을 쉽게 확인할 수 있도록 돕습니다:

$response->body() : string;
$response->json($key = null, $default = null) : array|mixed;
$response->object() : object;
$response->collect($key = null) : Illuminate\Support\Collection;
$response->status() : int;
$response->successful() : bool;
$response->redirect(): bool;
$response->failed() : bool;
$response->clientError() : bool;
$response->header($header) : string;
$response->headers() : array;

Illuminate\Http\Client\Response 객체는 PHP의 ArrayAccess 인터페이스도 구현하고 있어서, 응답으로 반환된 JSON 데이터를 배열처럼 바로 접근할 수 있습니다:

return Http::get('http://example.com/users/1')['name'];

위의 다양한 응답 메서드 외에도, 특정 상태 코드를 반환했는지 확인할 수 있는 메서드들도 사용할 수 있습니다:

$response->ok() : bool; // 200 OK
$response->created() : bool; // 201 Created
$response->accepted() : bool; // 202 Accepted
$response->noContent() : bool; // 204 No Content
$response->movedPermanently() : bool; // 301 Moved Permanently
$response->found() : bool; // 302 Found
$response->badRequest() : bool; // 400 Bad Request
$response->unauthorized() : bool; // 401 Unauthorized
$response->paymentRequired() : bool; // 402 Payment Required
$response->forbidden() : bool; // 403 Forbidden
$response->notFound() : bool; // 404 Not Found
$response->requestTimeout() : bool; // 408 Request Timeout
$response->conflict() : bool; // 409 Conflict
$response->unprocessableEntity() : bool; // 422 Unprocessable Entity
$response->tooManyRequests() : bool; // 429 Too Many Requests
$response->serverError() : bool; // 500 Internal Server Error

URI Templates​

HTTP 클라이언트는 URI template specification를 활용하여 요청 URL을 동적으로 구성할 수 있도록 지원합니다. URI 템플릿에서 변수로 사용될 URL 파라미터는 withUrlParameters 메서드를 이용해 정의합니다:

Http::withUrlParameters([
'endpoint' => 'https://laravel.com',
'page' => 'docs',
'version' => '9.x',
'topic' => 'validation',
])->get('{+endpoint}/{page}/{version}/{topic}');

Dumping Requests​

요청이 실제로 전송되기 전에 해당 요청 인스턴스를 덤프하고(즉시 출력) 스크립트 실행을 중단하고 싶을 때는 dd 메서드를 요청 정의의 시작 부분에 추가하면 됩니다:

return Http::dd()->get('http://example.com');

Request Data​

POST, PUT, PATCH 요청을 보내면서 추가적인 데이터 전송이 필요한 경우가 많습니다. 이러한 메서드들은 두 번째 인수로 데이터 배열을 받을 수 있습니다. 기본적으로 데이터는 application/json content-type으로 전송됩니다:

use Illuminate\Support\Facades\Http;

$response = Http::post('http://example.com/users', [
'name' => 'Steve',
'role' => 'Network Administrator',
]);

GET Request Query Parameters​

GET 요청을 보낼 때는, 쿼리 스트링을 URL에 직접 추가하거나, get 메서드의 두 번째 인수로 key / value 쌍 배열을 전달할 수 있습니다:

$response = Http::get('http://example.com/users', [
'name' => 'Taylor',
'page' => 1,
]);

또는, withQueryParameters 메서드를 사용할 수도 있습니다:

Http::retry(3, 100)->withQueryParameters([
'name' => 'Taylor',
'page' => 1,
])->get('http://example.com/users')

Sending Form URL Encoded Requests​

application/x-www-form-urlencoded content-type으로 데이터를 전송하려면, 요청 전송 전에 asForm 메서드를 호출해야 합니다:

$response = Http::asForm()->post('http://example.com/users', [
'name' => 'Sara',
'role' => 'Privacy Consultant',
]);

Sending a Raw Request Body​

요청 시, 원시(raw) 데이터 본문을 직접 지정하고 싶을 때는 withBody 메서드를 사용할 수 있습니다. 두 번째 인수로 content-type을 지정할 수 있습니다:

$response = Http::withBody(
base64_encode($photo), 'image/jpeg'
)->post('http://example.com/photo');

Multi-Part Requests​

파일을 멀티파트로 전송하려면, 요청 전에 attach 메서드를 사용해야 합니다. 이 메서드는 파일 이름과 파일 내용을 인수로 받으며, 필요하다면 세 번째 인수로 파일 이름, 네 번째 인수로 파일과 관련된 헤더를 추가할 수 있습니다:

$response = Http::attach(
'attachment', file_get_contents('photo.jpg'), 'photo.jpg', ['Content-Type' => 'image/jpeg']
)->post('http://example.com/attachments');

파일의 원시 데이터를 전달하는 대신, 스트림 리소스를 사용할 수도 있습니다:

$photo = fopen('photo.jpg', 'r');

$response = Http::attach(
'attachment', $photo, 'photo.jpg'
)->post('http://example.com/attachments');

Headers​

요청에 헤더를 추가하려면 withHeaders 메서드를 사용합니다. 이 withHeaders 메서드는 key / value 쌍 배열을 인수로 받습니다:

$response = Http::withHeaders([
'X-First' => 'foo',
'X-Second' => 'bar'
])->post('http://example.com/users', [
'name' => 'Taylor',
]);

요청에 대해 응답으로 기대하는 content-type을 지정하고 싶다면 accept 메서드를 사용할 수 있습니다:

$response = Http::accept('application/json')->get('http://example.com/users');

자주 사용하는 경우, acceptJson 메서드를 사용해 application/json content-type을 간편하게 지정할 수 있습니다:

$response = Http::acceptJson()->get('http://example.com/users');

withHeaders 메서드는 새로운 헤더를 기존 요청 헤더에 병합합니다. 만약 모든 헤더를 완전히 교체하고 싶다면 replaceHeaders 메서드를 사용할 수 있습니다:

$response = Http::withHeaders([
'X-Original' => 'foo',
])->replaceHeaders([
'X-Replacement' => 'bar',
])->post('http://example.com/users', [
'name' => 'Taylor',
]);

Authentication​

베이직 인증과 다이제스트 인증(Basic, Digest)은 각각 withBasicAuth, withDigestAuth 메서드로 지정할 수 있습니다:

// Basic authentication...
$response = Http::withBasicAuth('[email protected]', 'secret')->post(/* ... */);

// Digest authentication...
$response = Http::withDigestAuth('[email protected]', 'secret')->post(/* ... */);

Bearer Tokens​

요청의 Authorization 헤더에 Bearer 토큰을 빠르게 추가하려면 withToken 메서드를 사용합니다:

$response = Http::withToken('token')->post(/* ... */);

Timeout​

응답을 기다리는 최대 초(second) 수를 지정하려면 timeout 메서드를 사용하면 됩니다. 기본적으로 HTTP 클라이언트는 30초 후 타임아웃됩니다:

$response = Http::timeout(3)->get(/* ... */);

지정한 타임아웃을 초과하는 경우 Illuminate\Http\Client\ConnectionException 예외가 발생합니다.

서버 연결 시도에 대해 별도의 최대 대기 초를 지정하고 싶다면, connectTimeout 메서드를 사용할 수 있습니다:

$response = Http::connectTimeout(3)->get(/* ... */);

Retries​

클라이언트 오류 또는 서버 오류가 발생하면 HTTP 클라이언트가 자동으로 요청을 재시도하도록 retry 메서드를 사용할 수 있습니다. 이 retry 메서드는 요청을 시도할 최대 횟수와, 각 시도 사이 대기 시간을 밀리초(ms) 단위로 받습니다:

$response = Http::retry(3, 100)->post(/* ... */);

재시도 사이 대기 밀리초를 직접 계산하고 싶다면, retry 메서드의 두 번째 인수로 클로저를 전달하면 됩니다:

use Exception;

$response = Http::retry(3, function (int $attempt, Exception $exception) {
return $attempt * 100;
})->post(/* ... */);

편리하게, retry 메서드의 첫 번째 인수에 배열을 전달할 수도 있습니다. 이 배열은 각 시도 사이에 대기할 밀리초를 결정하는데 사용됩니다:

$response = Http::retry([100, 200])->post(/* ... */);

필요하다면, retry 메서드의 세 번째 인수로 실제로 재시도를 해야 하는지 판단하는 콜러블을 전달할 수 있습니다. 예를 들어, 처음 요청에서 ConnectionException만 발생할 때만 재시도하고 싶을 때 사용할 수 있습니다:

use Exception;
use Illuminate\Http\Client\PendingRequest;

$response = Http::retry(3, 100, function (Exception $exception, PendingRequest $request) {
return $exception instanceof ConnectionException;
})->post(/* ... */);

요청이 실패할 경우, 다음 시도 전에 요청 객체를 변경하고 싶을 때도 있습니다. retry 메서드에 전달한 콜러블에 제공되는 요청 인수를 수정하면 됩니다. 예를 들어, 첫 번째 요청이 인증 오류(401)였다면 새로운 토큰을 받아서 재시도할 수도 있습니다:

use Exception;
use Illuminate\Http\Client\PendingRequest;
use Illuminate\Http\Client\RequestException;

$response = Http::withToken($this->getToken())->retry(2, 0, function (Exception $exception, PendingRequest $request) {
if (! $exception instanceof RequestException || $exception->response->status() !== 401) {
return false;
}

$request->withToken($this->getNewToken());

return true;
})->post(/* ... */);

모든 요청이 실패할 경우, Illuminate\Http\Client\RequestException 예외가 발생합니다. 이 동작을 비활성화하려면 throw 인수를 false로 지정하세요. 이 경우 모든 재시도 후 마지막 응답 객체가 반환됩니다:

$response = Http::retry(3, 100, throw: false)->post(/* ... */);

모든 요청이 네트워크 연결 문제로 실패하면, throw 인수를 false로 설정해도 Illuminate\Http\Client\ConnectionException 예외는 여전히 발생합니다.

Error Handling​

Guzzle의 기본 동작과 달리, Laravel HTTP 클라이언트 래퍼는 클라이언트/서버 에러(400·500번대 상태) 발생 시 예외를 자동으로 던지지 않습니다. 이러한 오류가 반환됐는지 확인하려면 successful, clientError, serverError 등의 메서드를 사용할 수 있습니다:

// Determine if the status code is >= 200 and < 300...
$response->successful();

// Determine if the status code is >= 400...
$response->failed();

// Determine if the response has a 400 level status code...
$response->clientError();

// Determine if the response has a 500 level status code...
$response->serverError();

// Immediately execute the given callback if there was a client or server error...
$response->onError(callable $callback);

Throwing Exceptions​

응답 인스턴스가 있고, 상태 코드가 클라이언트 또는 서버 에러를 나타낸다면 직접 Illuminate\Http\Client\RequestException 예외를 던질 수 있습니다. 이때 throw 또는 throwIf 메서드를 사용할 수 있습니다:

use Illuminate\Http\Client\Response;

$response = Http::post(/* ... */);

// Throw an exception if a client or server error occurred...
$response->throw();

// Throw an exception if an error occurred and the given condition is true...
$response->throwIf($condition);

// Throw an exception if an error occurred and the given closure resolves to true...
$response->throwIf(fn (Response $response) => true);

// Throw an exception if an error occurred and the given condition is false...
$response->throwUnless($condition);

// Throw an exception if an error occurred and the given closure resolves to false...
$response->throwUnless(fn (Response $response) => false);

// Throw an exception if the response has a specific status code...
$response->throwIfStatus(403);

// Throw an exception unless the response has a specific status code...
$response->throwUnlessStatus(200);

return $response['user']['id'];

Illuminate\Http\Client\RequestException 인스턴스에는 공개 $response 속성이 있어 반환된 응답을 확인할 수 있습니다.

throw 메서드는 에러가 없으면 해당 응답 인스턴스를 그대로 반환하므로, throw 메서드에 추가적인 연산을 체이닝할 수도 있습니다:

return Http::post(/* ... */)->throw()->json();

예외가 발생하기 전 추가 로직이 필요하다면, throw 메서드에 클로저를 전달할 수 있습니다. 이 때 예외는 클로저 실행 후 자동으로 던져지므로 내부에서 예외를 명시적으로 다시 던질 필요는 없습니다:

use Illuminate\Http\Client\Response;
use Illuminate\Http\Client\RequestException;

return Http::post(/* ... */)->throw(function (Response $response, RequestException $e) {
// ...
})->json();

Guzzle Middleware​

Laravel의 HTTP 클라이언트는 Guzzle을 기반으로 동작하므로, Guzzle Middleware를 활용하여 아웃바운드 요청을 조작하거나 인바운드 응답을 검사할 수 있습니다. 아웃바운드 요청을 조작하고 싶을 경우 withRequestMiddleware 메서드로 미들웨어를 등록합니다:

use Illuminate\Support\Facades\Http;
use Psr\Http\Message\RequestInterface;

$response = Http::withRequestMiddleware(
function (RequestInterface $request) {
return $request->withHeader('X-Example', 'Value');
}
)->get('http://example.com');

마찬가지로, 들어오는 HTTP 응답을 검사하고 싶을 때는 withResponseMiddleware 메서드로 미들웨어를 등록할 수 있습니다:

use Illuminate\Support\Facades\Http;
use Psr\Http\Message\ResponseInterface;

$response = Http::withResponseMiddleware(
function (ResponseInterface $response) {
$header = $response->getHeader('X-Example');

// ...

return $response;
}
)->get('http://example.com');

Global Middleware​

모든 아웃바운드 요청과 인바운드 응답에 항상 적용할 미들웨어를 등록하고 싶을 때는 globalRequestMiddleware, globalResponseMiddleware 메서드를 사용합니다. 보통 이들은 애플리케이션의 AppServiceProvider의 boot 메서드에서 호출합니다:

use Illuminate\Support\Facades\Http;

Http::globalRequestMiddleware(fn ($request) => $request->withHeader(
'User-Agent', 'Example Application/1.0'
));

Http::globalResponseMiddleware(fn ($response) => $response->withHeader(
'X-Finished-At', now()->toDateTimeString()
));

Guzzle Options​

withOptions 메서드를 사용하면 추가 Guzzle request options을 지정할 수 있습니다. 이 withOptions 메서드는 key / value 쌍 배열을 인수로 받습니다:

$response = Http::withOptions([
'debug' => true,
])->get('http://example.com/users');

Concurrent Requests​

여러 HTTP 요청을 동시에 보낼 필요가 있을 때가 있습니다. 즉, 여러 요청을 순차적으로 처리하지 않고 한 번에 병렬로 전송하고자 하는 경우이며, 이는 느린 HTTP API와 상호작용할 때 큰 성능 향상으로 이어질 수 있습니다.

이러한 경우 pool 메서드를 사용하면 됩니다. pool 메서드는 클로저를 인수로 받아 Illuminate\Http\Client\Pool 인스턴스를 제공하고, 여기에 요청을 추가할 수 있습니다:

use Illuminate\Http\Client\Pool;
use Illuminate\Support\Facades\Http;

$responses = Http::pool(fn (Pool $pool) => [
$pool->get('http://localhost/first'),
$pool->get('http://localhost/second'),
$pool->get('http://localhost/third'),
]);

return $responses[0]->ok() &&
$responses[1]->ok() &&
$responses[2]->ok();

각 응답 인스턴스에 pool에 추가된 순서대로 접근할 수 있습니다. 만약 요청에 이름을 붙이고 싶다면 as 메서드를 사용할 수 있고, 그러면 이름으로 결과에 접근할 수 있습니다:

use Illuminate\Http\Client\Pool;
use Illuminate\Support\Facades\Http;

$responses = Http::pool(fn (Pool $pool) => [
$pool->as('first')->get('http://localhost/first'),
$pool->as('second')->get('http://localhost/second'),
$pool->as('third')->get('http://localhost/third'),
]);

return $responses['first']->ok();

Customizing Concurrent Requests​

pool 메서드는 withHeaders나 middleware 같은 다른 HTTP 클라이언트 메서드와 체이닝이 불가능합니다. pool에 추가한 각 요청에 직접 옵션을 지정해주어야 합니다:

use Illuminate\Http\Client\Pool;
use Illuminate\Support\Facades\Http;

$headers = [
'X-Example' => 'example',
];

$responses = Http::pool(fn (Pool $pool) => [
$pool->withHeaders($headers)->get('http://laravel.test/test'),
$pool->withHeaders($headers)->get('http://laravel.test/test'),
$pool->withHeaders($headers)->get('http://laravel.test/test'),
]);

Macros​

Laravel HTTP 클라이언트를 사용하면 "매크로"를 정의할 수 있습니다. 매크로는 특정 서비스에 대해 자주 사용하는 주소, 헤더 등 공통 설정을 간결하게 묶어서 사용할 수 있게 도와줍니다. 매크로는 애플리케이션의 App\Providers\AppServiceProvider 클래스의 boot 메서드에서 정의합니다:

use Illuminate\Support\Facades\Http;

/**
* Bootstrap any application services.
*/
public function boot(): void
{
Http::macro('github', function () {
return Http::withHeaders([
'X-Example' => 'example',
])->baseUrl('https://github.com');
});
}

이렇게 매크로를 구성하면, 애플리케이션 어디서든 지정한 구성을 가진 pending request를 사용할 수 있습니다:

$response = Http::github()->get('/');

Testing​

Laravel의 여러 서비스는 테스트를 쉽게 할 수 있도록 다양한 기능을 제공합니다. HTTP 클라이언트도 예외는 아니며, Http 파사드의 fake 메서드를 이용하면 요청 시 미리 지정한 더미(dummy) 응답을 반환하도록 가짜처리(stubbing/faking)할 수 있습니다.

Faking Responses​

예를 들어, 모든 요청에 대해 비어있는(내용 없음) 200 상태 코드 응답을 반환하도록 하려면, fake 메서드를 인수 없이 호출하면 됩니다:

use Illuminate\Support\Facades\Http;

Http::fake();

$response = Http::post(/* ... */);

Faking Specific URLs​

또는, fake 메서드에 배열을 전달할 수 있습니다. 이 때 배열의 키는 가짜로 만들고자 하는 URL 패턴, 값은 각 엔드포인트별로 반환할 응답 객체입니다. *(별표)는 와일드카드로 사용 가능합니다. 배열에 없는 URL로 요청하면 실제로 HTTP 요청이 전송됩니다. 각 엔드포인트에 대한 스텁 응답은 Http 파사드의 response 메서드로 생성합니다:

Http::fake([
// Stub a JSON response for GitHub endpoints...
'github.com/*' => Http::response(['foo' => 'bar'], 200, $headers),

// Stub a string response for Google endpoints...
'google.com/*' => Http::response('Hello World', 200, $headers),
]);

패턴에 매칭되지 않는 모든 URL을 포괄(fallback)해서 스텁 응답을 반환하고 싶다면, * 하나만 키로 사용하면 됩니다:

Http::fake([
// Stub a JSON response for GitHub endpoints...
'github.com/*' => Http::response(['foo' => 'bar'], 200, ['Headers']),

// Stub a string response for all other endpoints...
'*' => Http::response('Hello World', 200, ['Headers']),
]);

Faking Response Sequences​

특정 URL에 대해 여러 개의 응답을 순서대로 반환해야 할 상황도 있습니다. 이때는 Http::sequence 메서드로 응답 시퀀스를 구성할 수 있습니다:

Http::fake([
// Stub a series of responses for GitHub endpoints...
'github.com/*' => Http::sequence()
->push('Hello World', 200)
->push(['foo' => 'bar'], 200)
->pushStatus(404),
]);

응답 시퀀스의 모든 응답이 소진되면, 이후 요청에서는 예외가 발생합니다. 시퀀스가 모두 비었을 때 대신 반환할 기본 응답이 필요하다면, whenEmpty 메서드를 사용할 수 있습니다:

Http::fake([
// Stub a series of responses for GitHub endpoints...
'github.com/*' => Http::sequence()
->push('Hello World', 200)
->push(['foo' => 'bar'], 200)
->whenEmpty(Http::response()),
]);

특정 URL 패턴 없이 모든 요청에 대해 응답 시퀀스를 가짜로 만들 때는 Http::fakeSequence 메서드를 사용할 수 있습니다:

Http::fakeSequence()
->push('Hello World', 200)
->whenEmpty(Http::response());

Fake Callback​

특정 엔드포인트에 대해 더 복잡한 논리로 어떤 응답을 반환할지 결정해야 할 때는, fake 메서드에 클로저를 전달할 수 있습니다. 이 클로저는 Illuminate\Http\Client\Request 인스턴스와 옵션 배열을 인수로 받으며, 반드시 응답 인스턴스를 반환해야 합니다. 이 안에서 필요한 모든 복잡한 로직을 구현할 수 있습니다:

use Illuminate\Http\Client\Request;

Http::fake(function (Request $request, array $options) {
return Http::response('Hello World', 200);
});

Preventing Stray Requests​

테스트 중에 HTTP 클라이언트로 전송된 모든 요청이 반드시 fake이어야 한다는 것을 보장하고 싶을 때는, preventStrayRequests 메서드를 호출합니다. 이후 fake되지 않은 요청이 발생하면 실제 HTTP 요청 대신 예외가 발생합니다:

use Illuminate\Support\Facades\Http;

Http::preventStrayRequests();

Http::fake([
'github.com/*' => Http::response('ok'),
]);

// An "ok" response is returned...
Http::get('https://github.com/laravel/framework');

// An exception is thrown...
Http::get('https://laravel.com');

Inspecting Requests​

응답을 fake하는 경우, 클라이언트가 올바른 데이터나 헤더로 요청을 전송했는지 확인하고 싶은 경우가 있습니다. 이때 Http::fake를 호출한 후 Http::assertSent 메서드를 호출하면 됩니다.

assertSent 메서드는 Illuminate\Http\Client\Request 인스턴스를 전달받는 클로저를 인수로 받으며, 이 클로저는 요청이 기대에 부합하는지를 나타내는 불리언 값을 반환해야 합니다. 테스트를 통과하려면 주어진 기대에 부합하는 요청이 최소 한 번은 전송되었어야 합니다:

use Illuminate\Http\Client\Request;
use Illuminate\Support\Facades\Http;

Http::fake();

Http::withHeaders([
'X-First' => 'foo',
])->post('http://example.com/users', [
'name' => 'Taylor',
'role' => 'Developer',
]);

Http::assertSent(function (Request $request) {
return $request->hasHeader('X-First', 'foo') &&
$request->url() == 'http://example.com/users' &&
$request['name'] == 'Taylor' &&
$request['role'] == 'Developer';
});

특정 요청이 전송되지 않았음(assertNotSent)을 확인하려면 assertNotSent 메서드를 사용할 수 있습니다:

use Illuminate\Http\Client\Request;
use Illuminate\Support\Facades\Http;

Http::fake();

Http::post('http://example.com/users', [
'name' => 'Taylor',
'role' => 'Developer',
]);

Http::assertNotSent(function (Request $request) {
return $request->url() === 'http://example.com/posts';
});

assertSentCount 메서드로 테스트 중 전송된 요청 수를 검증할 수 있습니다:

Http::fake();

Http::assertSentCount(5);

또는, assertNothingSent 메서드로 아무런 요청도 보내지 않았음을 검증할 수 있습니다:

Http::fake();

Http::assertNothingSent();

Recording Requests / Responses​

recorded 메서드를 사용하면 모든 요청과 그에 대한 응답 목록을 조회할 수 있습니다. 이 recorded 메서드는 Illuminate\Http\Client\Request와 Illuminate\Http\Client\Response 인스턴스 쌍으로 구성된 컬렉션을 반환합니다:

Http::fake([
'https://laravel.com' => Http::response(status: 500),
'https://nova.laravel.com/' => Http::response(),
]);

Http::get('https://laravel.com');
Http::get('https://nova.laravel.com/');

$recorded = Http::recorded();

[$request, $response] = $recorded[0];

또한, recorded 메서드에 Illuminate\Http\Client\Request와 Illuminate\Http\Client\Response 인스턴스를 전달받는 클로저를 전달하여 특정 조건에 맞는 요청/응답 쌍만 필터링할 수도 있습니다:

use Illuminate\Http\Client\Request;
use Illuminate\Http\Client\Response;

Http::fake([
'https://laravel.com' => Http::response(status: 500),
'https://nova.laravel.com/' => Http::response(),
]);

Http::get('https://laravel.com');
Http::get('https://nova.laravel.com/');

$recorded = Http::recorded(function (Request $request, Response $response) {
return $request->url() !== 'https://laravel.com' &&
$response->successful();
});

Events​

Laravel은 HTTP 요청 처리 과정에서 총 3개의 이벤트를 발생시킵니다. 요청이 전송되기 직전에 RequestSending 이벤트가, 요청에 대해 응답이 도착한 후에는 ResponseReceived 이벤트가 발생합니다. 서버로부터 응답을 받지 못한 경우에는 ConnectionFailed 이벤트가 발생합니다.

RequestSending과 ConnectionFailed 이벤트에는 Illuminate\Http\Client\Request 인스턴스를 확인할 수 있는 공개 $request 속성이 있습니다. 마찬가지로 ResponseReceived 이벤트에는 $request와 함께, Illuminate\Http\Client\Response 인스턴스를 확인할 수 있는 $response 속성도 있습니다. 이러한 이벤트에 리스너를 등록하려면, App\Providers\EventServiceProvider의 이벤트 매핑에 아래와 같이 추가하세요:

/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
'Illuminate\Http\Client\Events\RequestSending' => [
'App\Listeners\LogRequestSending',
],
'Illuminate\Http\Client\Events\ResponseReceived' => [
'App\Listeners\LogResponseReceived',
],
'Illuminate\Http\Client\Events\ConnectionFailed' => [
'App\Listeners\LogConnectionFailed',
],
];