Skip to content

Commit 27a1835

Browse files
authored
Merge pull request #51 from veewee/content-type-aware-payload
Add ContentTypeAwarePayload and ContentTypeAwareEncoder
2 parents 0a83c7d + 60402f5 commit 27a1835

4 files changed

Lines changed: 109 additions & 7 deletions

File tree

docs/transports.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,21 @@ This package contains some frequently used encoders / decoders for you:
2929

3030
| Class | EncodingType<DataType> | Action |
3131
|-------------------------|---------------------------------------|-------------------------------------------------------------------------------------|
32-
| `EmptyBodyEncoder` | `EncoderInterface<null>` | Creates empty request body |
3332
| `BinaryFileDecoder` | `DecoderInterface<BinaryFile>` | Parses file information from the HTTP response and returns a `BinaryFile` DTO |
34-
| `FormUrlencodedEncoder` | `EncoderInterface<?array>` | Adds form urlencoded body and headers to request |
33+
| `ContentTypeAwareEncoder` | `EncoderInterface<ContentTypeAwarePayload<T>>` | Decorator that wraps any encoder and sets the Content-Type header from the payload |
34+
| `EmptyBodyEncoder` | `EncoderInterface<null>` | Creates empty request body |
3535
| `FormUrlencodedDecoder` | `DecoderInterface<array>` | Converts form urlencoded response body to array |
36-
| `JsonEncoder` | `EncoderInterface<?array>` | Adds json body and headers to request |
36+
| `FormUrlencodedEncoder` | `EncoderInterface<?array>` | Adds form urlencoded body and headers to request |
3737
| `JsonDecoder` | `DecoderInterface<array>` | Converts json response body to array |
38+
| `JsonEncoder` | `EncoderInterface<?array>` | Adds json body and headers to request |
3839
| `MultiPartEncoder` | `EncoderInterface<AbstractMultipartPart>` | Adds symfony/mime `AbstractMultipartPart`as HTTP body. Handy for form data + files. |
39-
| `StreamEncoder` | `EncoderInterface<StreamInterface>` | Adds PSR-7 Stream as request body |
40-
| `StreamDecoder` | `DecoderInterface<StreamInterface>` | Returns the PSR-7 Stream as response result |
41-
| `RawEncoder` | `EncoderInterface<string>` | Adds raw string as request body |
4240
| `RawDecoder` | `DecoderInterface<string>` | Returns the raw PSR-7 body string as response result |
43-
| `ResourceStreamEncoder` | `EncoderInterface<ResourceStream>` | Adds `phpro/resource-stream` as request body |
41+
| `RawEncoder` | `EncoderInterface<string>` | Adds raw string as request body |
4442
| `ResourceStreamDecoder` | `DecoderInterface<ResourceStream>` | Returns `phpro/resource-stream` from response body |
43+
| `ResourceStreamEncoder` | `EncoderInterface<ResourceStream>` | Adds `phpro/resource-stream` as request body |
4544
| `ResponseDecoder` | `DecoderInterface<ResponseInterface>` | Returns the received PSR-7 response as result |
45+
| `StreamDecoder` | `DecoderInterface<StreamInterface>` | Returns the PSR-7 Stream as response result |
46+
| `StreamEncoder` | `EncoderInterface<StreamInterface>` | Adds PSR-7 Stream as request body |
4647

4748
## Built-in transport presets:
4849

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Phpro\HttpTools\Encoding\ContentType;
6+
7+
use Phpro\HttpTools\Encoding\EncoderInterface;
8+
use Psr\Http\Message\RequestInterface;
9+
10+
/**
11+
* @template T
12+
*
13+
* @implements EncoderInterface<ContentTypeAwarePayload<T>>
14+
*/
15+
final class ContentTypeAwareEncoder implements EncoderInterface
16+
{
17+
/**
18+
* @param EncoderInterface<T> $encoder
19+
*/
20+
public function __construct(
21+
private EncoderInterface $encoder,
22+
) {
23+
}
24+
25+
/**
26+
* @param ContentTypeAwarePayload<T> $data
27+
*/
28+
public function __invoke(RequestInterface $request, $data): RequestInterface
29+
{
30+
$request = ($this->encoder)($request, $data->payload);
31+
32+
return $request->withHeader('Content-Type', $data->contentType);
33+
}
34+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Phpro\HttpTools\Encoding\ContentType;
6+
7+
/**
8+
* @template T
9+
*/
10+
final readonly class ContentTypeAwarePayload
11+
{
12+
/**
13+
* @param T $payload
14+
*/
15+
public function __construct(
16+
public string $contentType,
17+
public mixed $payload,
18+
) {
19+
}
20+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Phpro\HttpTools\Tests\Unit\Encoding\ContentType;
6+
7+
use Phpro\HttpTools\Encoding\ContentType\ContentTypeAwareEncoder;
8+
use Phpro\HttpTools\Encoding\ContentType\ContentTypeAwarePayload;
9+
use Phpro\HttpTools\Encoding\Raw\RawEncoder;
10+
use Phpro\HttpTools\Test\UseHttpFactories;
11+
use PHPUnit\Framework\Attributes\Test;
12+
use PHPUnit\Framework\TestCase;
13+
14+
final class ContentTypeAwareEncoderTest extends TestCase
15+
{
16+
use UseHttpFactories;
17+
18+
#[Test]
19+
public function it_can_encode_with_content_type(): void
20+
{
21+
$encoder = new ContentTypeAwareEncoder(
22+
RawEncoder::createWithAutodiscoveredPsrFactories()
23+
);
24+
$request = $this->createRequest('POST', '/hello');
25+
$payload = new ContentTypeAwarePayload('application/pdf', 'raw-content');
26+
27+
$actual = $encoder($request, $payload);
28+
29+
self::assertSame('raw-content', (string) $actual->getBody());
30+
self::assertSame('application/pdf', $actual->getHeaderLine('Content-Type'));
31+
}
32+
33+
#[Test]
34+
public function it_overrides_content_type_set_by_inner_encoder(): void
35+
{
36+
$encoder = new ContentTypeAwareEncoder(
37+
RawEncoder::createWithAutodiscoveredPsrFactories()
38+
);
39+
$request = $this->createRequest('POST', '/hello')
40+
->withHeader('Content-Type', 'text/plain');
41+
$payload = new ContentTypeAwarePayload('application/xml', 'raw-content');
42+
43+
$actual = $encoder($request, $payload);
44+
45+
self::assertSame('application/xml', $actual->getHeaderLine('Content-Type'));
46+
}
47+
}

0 commit comments

Comments
 (0)