Skip to content

Commit c41e144

Browse files
committed
Add ResourceStream encoder and decoder
Introduce encoding support for phpro/resource-stream, bridging ResourceStream with the PSR-7 HTTP layer. The encoder converts a ResourceStream to a PSR-7 request body, the decoder wraps a PSR-7 response body into a ResourceStream.
1 parent fff383f commit c41e144

6 files changed

Lines changed: 149 additions & 7 deletions

File tree

composer.json

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@
1717
"require": {
1818
"php": "~8.4.0 || ~8.5.0",
1919
"ext-json": "*",
20+
"cardinalby/content-disposition": "^1.1",
21+
"league/uri": "^7.3",
22+
"php-http/client-common": "^2.7",
23+
"php-http/discovery": "^1.19",
24+
"php-http/httplug": "^2.4",
25+
"php-http/logger-plugin": "^1.3",
26+
"php-http/message": "^1.16 || ^2.0",
2027
"php-standard-library/foundation": "^6.1",
2128
"php-standard-library/fun": "^6.1",
2229
"php-standard-library/hash": "^6.1",
@@ -25,13 +32,7 @@
2532
"php-standard-library/regex": "^6.1",
2633
"php-standard-library/result": "^6.1",
2734
"php-standard-library/type": "^6.1",
28-
"cardinalby/content-disposition": "^1.1",
29-
"league/uri": "^7.3",
30-
"php-http/client-common": "^2.7",
31-
"php-http/discovery": "^1.19",
32-
"php-http/httplug": "^2.4",
33-
"php-http/logger-plugin": "^1.3",
34-
"php-http/message": "^1.16 || ^2.0",
35+
"phpro/resource-stream": "^1.3",
3536
"psr/http-client-implementation": "^1.0",
3637
"psr/http-factory": "^1.0",
3738
"psr/http-factory-implementation": "^1.0",

docs/transports.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ This package contains some frequently used encoders / decoders for you:
4040
| `StreamDecoder` | `DecoderInterface<StreamInterface>` | Returns the PSR-7 Stream as response result |
4141
| `RawEncoder` | `EncoderInterface<string>` | Adds raw string as request body |
4242
| `RawDecoder` | `DecoderInterface<string>` | Returns the raw PSR-7 body string as response result |
43+
| `ResourceStreamEncoder` | `EncoderInterface<ResourceStream>` | Adds `phpro/resource-stream` as request body |
44+
| `ResourceStreamDecoder` | `DecoderInterface<ResourceStream>` | Returns `phpro/resource-stream` from response body |
4345
| `ResponseDecoder` | `DecoderInterface<ResponseInterface>` | Returns the received PSR-7 response as result |
4446

4547
## Built-in transport presets:
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Phpro\HttpTools\Encoding\ResourceStream;
6+
7+
use Phpro\HttpTools\Encoding\DecoderInterface;
8+
use Phpro\ResourceStream\Factory\Psr7Stream;
9+
use Phpro\ResourceStream\ResourceStream;
10+
use Psr\Http\Message\ResponseInterface;
11+
12+
/**
13+
* @implements DecoderInterface<ResourceStream<resource>>
14+
*/
15+
final class ResourceStreamDecoder implements DecoderInterface
16+
{
17+
public static function createWithAutodiscoveredPsrFactories(): self
18+
{
19+
return new self();
20+
}
21+
22+
public function __invoke(ResponseInterface $response): ResourceStream
23+
{
24+
return Psr7Stream::createFromResponse($response);
25+
}
26+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Phpro\HttpTools\Encoding\ResourceStream;
6+
7+
use Http\Discovery\Psr17FactoryDiscovery;
8+
use Phpro\HttpTools\Encoding\EncoderInterface;
9+
use Phpro\ResourceStream\ResourceStream;
10+
use Psr\Http\Message\RequestInterface;
11+
use Psr\Http\Message\StreamFactoryInterface;
12+
13+
/**
14+
* @implements EncoderInterface<ResourceStream<resource>>
15+
*/
16+
final class ResourceStreamEncoder implements EncoderInterface
17+
{
18+
public function __construct(
19+
private StreamFactoryInterface $streamFactory,
20+
) {
21+
}
22+
23+
public static function createWithAutodiscoveredPsrFactories(): self
24+
{
25+
return new self(
26+
Psr17FactoryDiscovery::findStreamFactory(),
27+
);
28+
}
29+
30+
public function __invoke(RequestInterface $request, $data): RequestInterface
31+
{
32+
return $request->withBody(
33+
$this->streamFactory->createStreamFromResource($data->unwrap()),
34+
);
35+
}
36+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Phpro\HttpTools\Tests\Unit\Encoding\ResourceStream;
6+
7+
use Phpro\HttpTools\Encoding\ResourceStream\ResourceStreamDecoder;
8+
use Phpro\HttpTools\Test\UseHttpFactories;
9+
use Phpro\ResourceStream\ResourceStream;
10+
use PHPUnit\Framework\Attributes\Test;
11+
use PHPUnit\Framework\TestCase;
12+
13+
final class ResourceStreamDecoderTest extends TestCase
14+
{
15+
use UseHttpFactories;
16+
17+
#[Test]
18+
public function it_can_decode_response_to_resource_stream(): void
19+
{
20+
$decoder = ResourceStreamDecoder::createWithAutodiscoveredPsrFactories();
21+
$response = $this->createResponse()
22+
->withBody($this->createStream($content = '{"hello": "world"}'));
23+
24+
$decoded = $decoder($response);
25+
26+
self::assertInstanceOf(ResourceStream::class, $decoded);
27+
self::assertSame($content, $decoded->getContents());
28+
}
29+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Phpro\HttpTools\Tests\Unit\Encoding\ResourceStream;
6+
7+
use Phpro\HttpTools\Encoding\ResourceStream\ResourceStreamEncoder;
8+
use Phpro\HttpTools\Test\UseHttpFactories;
9+
use Phpro\ResourceStream\Factory\MemoryStream;
10+
use PHPUnit\Framework\Attributes\Test;
11+
use PHPUnit\Framework\TestCase;
12+
13+
final class ResourceStreamEncoderTest extends TestCase
14+
{
15+
use UseHttpFactories;
16+
17+
#[Test]
18+
public function it_can_encode_resource_stream(): void
19+
{
20+
$resourceStream = MemoryStream::create();
21+
$resourceStream->write($content = 'Hello world');
22+
$resourceStream->rewind();
23+
24+
$encoder = ResourceStreamEncoder::createWithAutodiscoveredPsrFactories();
25+
$request = $this->createRequest('POST', '/hello');
26+
27+
$actual = $encoder($request, $resourceStream);
28+
29+
self::assertSame($request->getMethod(), $actual->getMethod());
30+
self::assertSame($request->getUri(), $actual->getUri());
31+
self::assertSame($content, (string) $actual->getBody());
32+
self::assertFalse($actual->hasHeader('Content-Type'));
33+
}
34+
35+
#[Test]
36+
public function it_can_encode_resource_stream_without_rewinding(): void
37+
{
38+
$resourceStream = MemoryStream::create();
39+
$resourceStream->write($content = 'Hello world');
40+
41+
$encoder = ResourceStreamEncoder::createWithAutodiscoveredPsrFactories();
42+
$request = $this->createRequest('POST', '/hello');
43+
44+
$actual = $encoder($request, $resourceStream);
45+
46+
self::assertSame($content, (string) $actual->getBody());
47+
}
48+
}

0 commit comments

Comments
 (0)