|
652 | 652 |
|
653 | 653 | $this->http->requestObject($payload); |
654 | 654 | }); |
| 655 | + |
| 656 | +test('transporter exception includes response body for non-json client errors', function () { |
| 657 | + $payload = Payload::list('models'); |
| 658 | + |
| 659 | + $baseUri = BaseUri::from('api.openai.com'); |
| 660 | + $headers = Headers::withAuthorization(ApiKey::from('foo')); |
| 661 | + $queryParams = QueryParams::create(); |
| 662 | + |
| 663 | + $responseBody = 'Bad Request: Invalid model parameter provided'; |
| 664 | + |
| 665 | + $this->client |
| 666 | + ->shouldReceive('sendRequest') |
| 667 | + ->once() |
| 668 | + ->andThrow(new \GuzzleHttp\Exception\ClientException( |
| 669 | + message: 'Client error: 400 Bad Request', |
| 670 | + request: $payload->toRequest($baseUri, $headers, $queryParams), |
| 671 | + response: new Response(400, ['Content-Type' => 'text/plain'], $responseBody) |
| 672 | + )); |
| 673 | + |
| 674 | + expect(fn () => $this->http->requestObject($payload))->toThrow(function (TransporterException $e) use ($responseBody) { |
| 675 | + expect($e->getMessage())->toContain($responseBody) |
| 676 | + ->and($e->getResponseBody())->toBe($responseBody) |
| 677 | + ->and($e->getStatusCode())->toBe(400) |
| 678 | + ->and($e->getResponse())->not->toBeNull(); |
| 679 | + }); |
| 680 | +}); |
| 681 | + |
| 682 | +test('transporter exception includes response body for html error responses', function () { |
| 683 | + $payload = Payload::list('models'); |
| 684 | + |
| 685 | + $baseUri = BaseUri::from('api.openai.com'); |
| 686 | + $headers = Headers::withAuthorization(ApiKey::from('foo')); |
| 687 | + $queryParams = QueryParams::create(); |
| 688 | + |
| 689 | + $responseBody = '<html><body><h1>502 Bad Gateway</h1></body></html>'; |
| 690 | + |
| 691 | + $this->client |
| 692 | + ->shouldReceive('sendRequest') |
| 693 | + ->once() |
| 694 | + ->andThrow(new \GuzzleHttp\Exception\ClientException( |
| 695 | + message: 'Server error: 502 Bad Gateway', |
| 696 | + request: $payload->toRequest($baseUri, $headers, $queryParams), |
| 697 | + response: new Response(502, ['Content-Type' => 'text/html'], $responseBody) |
| 698 | + )); |
| 699 | + |
| 700 | + expect(fn () => $this->http->requestObject($payload))->toThrow(function (TransporterException $e) use ($responseBody) { |
| 701 | + expect($e->getMessage())->toContain($responseBody) |
| 702 | + ->and($e->getResponseBody())->toBe($responseBody) |
| 703 | + ->and($e->getStatusCode())->toBe(502); |
| 704 | + }); |
| 705 | +}); |
| 706 | + |
| 707 | +test('transporter exception includes openrouter style error response', function () { |
| 708 | + $payload = Payload::list('models'); |
| 709 | + |
| 710 | + $baseUri = BaseUri::from('api.openai.com'); |
| 711 | + $headers = Headers::withAuthorization(ApiKey::from('foo')); |
| 712 | + $queryParams = QueryParams::create(); |
| 713 | + |
| 714 | + $responseBody = json_encode([ |
| 715 | + 'message' => 'Provider returned error', |
| 716 | + 'code' => 400, |
| 717 | + 'metadata' => ['provider' => 'anthropic'], |
| 718 | + ]); |
| 719 | + |
| 720 | + $this->client |
| 721 | + ->shouldReceive('sendRequest') |
| 722 | + ->once() |
| 723 | + ->andThrow(new \GuzzleHttp\Exception\ClientException( |
| 724 | + message: 'Client error: 400 Bad Request', |
| 725 | + request: $payload->toRequest($baseUri, $headers, $queryParams), |
| 726 | + response: new Response(400, ['Content-Type' => 'application/json'], $responseBody) |
| 727 | + )); |
| 728 | + |
| 729 | + expect(fn () => $this->http->requestObject($payload))->toThrow(function (TransporterException $e) use ($responseBody) { |
| 730 | + expect($e->getMessage())->toContain('Provider returned error') |
| 731 | + ->and($e->getResponseBody())->toBe($responseBody) |
| 732 | + ->and($e->getStatusCode())->toBe(400); |
| 733 | + }); |
| 734 | +}); |
| 735 | + |
| 736 | +test('transporter exception getters work without response', function () { |
| 737 | + $payload = Payload::list('models'); |
| 738 | + |
| 739 | + $baseUri = BaseUri::from('api.openai.com'); |
| 740 | + $headers = Headers::withAuthorization(ApiKey::from('foo')); |
| 741 | + $queryParams = QueryParams::create(); |
| 742 | + |
| 743 | + $this->client |
| 744 | + ->shouldReceive('sendRequest') |
| 745 | + ->once() |
| 746 | + ->andThrow(new ConnectException('Could not resolve host.', $payload->toRequest($baseUri, $headers, $queryParams))); |
| 747 | + |
| 748 | + expect(fn () => $this->http->requestObject($payload))->toThrow(function (TransporterException $e) { |
| 749 | + expect($e->getMessage())->toBe('Could not resolve host.') |
| 750 | + ->and($e->getResponseBody())->toBeNull() |
| 751 | + ->and($e->getStatusCode())->toBe(0) |
| 752 | + ->and($e->getResponse())->toBeNull(); |
| 753 | + }); |
| 754 | +}); |
0 commit comments