diff --git a/src/Illuminate/Http/Client/PendingRequest.php b/src/Illuminate/Http/Client/PendingRequest.php index 246ac950797a..a3a022c352f3 100644 --- a/src/Illuminate/Http/Client/PendingRequest.php +++ b/src/Illuminate/Http/Client/PendingRequest.php @@ -889,7 +889,7 @@ public function send(string $method, string $url, array $options = []) return retry($this->tries ?? 1, function ($attempt) use ($method, $url, $options, &$shouldRetry) { try { - return tap(new Response($this->sendRequest($method, $url, $options)), function ($response) use ($attempt, &$shouldRetry) { + return tap($this->newResponse($this->sendRequest($method, $url, $options)), function ($response) use ($attempt, &$shouldRetry) { $this->populateResponse($response); $this->dispatchResponseReceivedEvent($response); @@ -1001,13 +1001,13 @@ protected function makePromise(string $method, string $url, array $options = []) { return $this->promise = $this->sendRequest($method, $url, $options) ->then(function (MessageInterface $message) { - return tap(new Response($message), function ($response) { + return tap($this->newResponse($message), function ($response) { $this->populateResponse($response); $this->dispatchResponseReceivedEvent($response); }); }) ->otherwise(function (TransferException $e) { - return $e instanceof RequestException && $e->hasResponse() ? $this->populateResponse(new Response($e->getResponse())) : $e; + return $e instanceof RequestException && $e->hasResponse() ? $this->populateResponse($this->newResponse($e->getResponse())) : $e; }); } @@ -1193,7 +1193,7 @@ public function buildRecorderHandler() return $promise->then(function ($response) use ($request, $options) { $this->factory?->recordRequestResponsePair( (new Request($request))->withData($options['laravel_data']), - new Response($response) + $this->newResponse($response) ); return $response; @@ -1298,6 +1298,17 @@ public function mergeOptions(...$options) ); } + /** + * Create a new response instance using the given PSR response. + * + * @param \Psr\Http\Message\MessageInterface $response + * @return Response + */ + protected function newResponse($response) + { + return new Response($response); + } + /** * Register a stub callable that will intercept requests and be able to return stub responses. * diff --git a/tests/Http/HttpClientTest.php b/tests/Http/HttpClientTest.php index b8b4ca22554b..6d8ab2867ee4 100644 --- a/tests/Http/HttpClientTest.php +++ b/tests/Http/HttpClientTest.php @@ -2523,4 +2523,48 @@ public function testItCanAddResponseMiddleware() $this->assertSame('Bar', $responses[0]->header('X-Foo')); $this->assertSame('', $responses[1]->header('X-Foo')); } + + public function testItReturnsResponse(): void + { + $this->factory->fake([ + '*' => $this->factory::response('expected content'), + ]); + + $response = $this->factory->get('http://laravel.com'); + + $this->assertInstanceOf(Response::class, $response); + $this->assertSame('expected content', $response->body()); + } + + public function testItCanReturnCustomResponseClass(): void + { + $factory = new CustomFactory; + + $factory->fake([ + '*' => $factory::response('expected content'), + ]); + + $response = $factory->get('http://laravel.fake'); + + $this->assertInstanceOf(TestResponse::class, $response); + $this->assertSame('expected content', $response->body()); + } +} + +class CustomFactory extends Factory +{ + protected function newPendingRequest() + { + return new class extends PendingRequest + { + protected function newResponse($response) + { + return new TestResponse($response); + } + }; + } +} + +class TestResponse extends Response +{ }