-
-
Notifications
You must be signed in to change notification settings - Fork 118
Open
Description
Hello,
Saloon 3.14.0 / PHP 8.3.10 / Laravel 12.19 / Windows 10
I have a connector with a method UploadFile where I stream a large file using fopen to save memory:
class UploadFile extends Request implements HasBody
{
use HasMultipartBody;
public function __construct (
private string $path,
// ...
) {}
protected function defaultBody (): array
{
return [
new MultipartValue(name: 'file', value: fopen($this->path, 'r'), filename: basename($this->path)),
// ...
];
}
}
I also have my custom trait for logging requests/responses:
trait LogsRequestsAndResponses
{
const int MAX_LOGGED_BODY_SIZE = 10;
public static function bootLogsRequestsAndResponses (PendingRequest $pendingRequest): void
{
$connector = $pendingRequest->getConnector();
$log_channel = $connector->log_channel ?? 'single';
$request_id = Str::random();
$connector->debugRequest(function (PendingRequest $pendingRequest, RequestInterface $psrRequest) use ($log_channel, $request_id) {
$log_data = [
'url' => $pendingRequest->getUrl(),
'method' => $pendingRequest->getMethod(),
'headers' => $pendingRequest->headers()->all(),
'body_size' => $psrRequest->getBody()->getSize(),
];
$log_data['body'] = $log_data['body_size'] <= self::MAX_LOGGED_BODY_SIZE
? (string)$pendingRequest->body()
: '<request body truncated>';
Log::channel($log_channel)->debug("request | id {$request_id} | ", $log_data);
});
$connector->debugResponse(function (Response $response, ResponseInterface $psrResponse) use ($log_channel, $request_id) {
$log_data = [
'status' => $response->status() . ' ' . $psrResponse->getReasonPhrase(),
'headers' => $response->headers()->all(),
'body_size' => $psrResponse->getBody()->getSize(),
];
$log_data['body'] = $log_data['body_size'] <= self::MAX_LOGGED_BODY_SIZE
? (string)$response->body()
: '<response body truncated>';
Log::channel($log_channel)->debug("response | id {$request_id} | ", $log_data);
});
}
}
I use the trait on connectors like this:
class MymeetConnector extends Connector
{
use AcceptsJson;
use LogsRequestsAndResponses;
// ...
When I send the request with this trait attached to the connector, it fails with the exception "Invalid resource type: resource (closed)":
[2025-07-08 14:32:17] local.ERROR: Invalid resource type: resource (closed) {"exception":"[object] (InvalidArgumentException(code: 0): Invalid resource type: resource (closed) at C:\\nastroim\\pipka\\vendor\\guzzlehttp\\psr7\\src\\Utils.php:355)
[stacktrace]
#0 C:\\nastroim\\pipka\\vendor\\guzzlehttp\\psr7\\src\\MultipartStream.php(94): GuzzleHttp\\Psr7\\Utils::streamFor()
#1 C:\\nastroim\\pipka\\vendor\\guzzlehttp\\psr7\\src\\MultipartStream.php(77): GuzzleHttp\\Psr7\\MultipartStream->addElement()
#2 C:\\nastroim\\pipka\\vendor\\guzzlehttp\\psr7\\src\\MultipartStream.php(38): GuzzleHttp\\Psr7\\MultipartStream->createStream()
#3 C:\\nastroim\\pipka\\vendor\\saloonphp\\saloon\\src\\Http\\Senders\\Factories\\GuzzleMultipartBodyFactory.php(31): GuzzleHttp\\Psr7\\MultipartStream->__construct()
#4 C:\\nastroim\\pipka\\vendor\\saloonphp\\saloon\\src\\Repositories\\Body\\MultipartBodyRepository.php(223): Saloon\\Http\\Senders\\Factories\\GuzzleMultipartBodyFactory->create()
#5 C:\\nastroim\\pipka\\vendor\\saloonphp\\saloon\\src\\Traits\\PendingRequest\\ManagesPsrRequests.php(55): Saloon\\Repositories\\Body\\MultipartBodyRepository->toStream()
#6 C:\\nastroim\\pipka\\vendor\\saloonphp\\saloon\\src\\Http\\Senders\\GuzzleSender.php(97): Saloon\\Http\\PendingRequest->createPsrRequest()
#7 C:\\nastroim\\pipka\\vendor\\saloonphp\\saloon\\src\\Traits\\Connector\\SendsRequests.php(72): Saloon\\Http\\Senders\\GuzzleSender->send()
#8 C:\\nastroim\\pipka\\app\\Console\\Commands\\TestCommand.php(73): Saloon\\Http\\Connector->send()
#9 C:\\nastroim\\pipka\\vendor\\laravel\\framework\\src\\Illuminate\\Container\\BoundMethod.php(36): App\\Console\\Commands\\TestCommand->handle()
#10 C:\\nastroim\\pipka\\vendor\\laravel\\framework\\src\\Illuminate\\Container\\Util.php(43): Illuminate\\Container\\BoundMethod::Illuminate\\Container\\{closure}()
#11 C:\\nastroim\\pipka\\vendor\\laravel\\framework\\src\\Illuminate\\Container\\BoundMethod.php(96): Illuminate\\Container\\Util::unwrapIfClosure()
#12 C:\\nastroim\\pipka\\vendor\\laravel\\framework\\src\\Illuminate\\Container\\BoundMethod.php(35): Illuminate\\Container\\BoundMethod::callBoundMethod()
#13 C:\\nastroim\\pipka\\vendor\\laravel\\framework\\src\\Illuminate\\Container\\Container.php(754): Illuminate\\Container\\BoundMethod::call()
#14 C:\\nastroim\\pipka\\vendor\\laravel\\framework\\src\\Illuminate\\Console\\Command.php(209): Illuminate\\Container\\Container->call()
#15 C:\\nastroim\\pipka\\vendor\\symfony\\console\\Command\\Command.php(318): Illuminate\\Console\\Command->execute()
#16 C:\\nastroim\\pipka\\vendor\\laravel\\framework\\src\\Illuminate\\Console\\Command.php(178): Symfony\\Component\\Console\\Command\\Command->run()
#17 C:\\nastroim\\pipka\\vendor\\symfony\\console\\Application.php(1092): Illuminate\\Console\\Command->run()
#18 C:\\nastroim\\pipka\\vendor\\symfony\\console\\Application.php(341): Symfony\\Component\\Console\\Application->doRunCommand()
#19 C:\\nastroim\\pipka\\vendor\\symfony\\console\\Application.php(192): Symfony\\Component\\Console\\Application->doRun()
#20 C:\\nastroim\\pipka\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Console\\Kernel.php(197): Symfony\\Component\\Console\\Application->run()
#21 C:\\nastroim\\pipka\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Application.php(1234): Illuminate\\Foundation\\Console\\Kernel->handle()
#22 C:\\nastroim\\pipka\\artisan(16): Illuminate\\Foundation\\Application->handleCommand()
#23 {main}
"}
When the trait is off, the uploading goes fine.
Can you suggest what can be wrong with my trait? It's pretty basic and I use it with other connectors/requests for logging. Thanks in advance!
Metadata
Metadata
Assignees
Labels
No labels