Skip to content

Commit 63e3f24

Browse files
committed
Http: Review message classes
- Move `Stream` methods `copyToString()` and `copyToStream()` to `HttpUtil`, renaming them to `getStreamContents()` and `copyStream()`
1 parent 4645e93 commit 63e3f24

15 files changed

+313
-313
lines changed

src/Toolkit/Curler/CurlerFile.php

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
use Salient\Http\Message\StreamPart;
66
use Salient\Utility\File;
7-
use InvalidArgumentException;
87

98
/**
109
* A file to upload to an HTTP endpoint
@@ -24,22 +23,15 @@ public function __construct(
2423
string $filename,
2524
?string $uploadFilename = null,
2625
?string $mediaType = null,
27-
?string $fallbackFilename = null,
26+
?string $asciiFilename = null,
2827
?string $name = null
2928
) {
30-
if (!is_file($filename)) {
31-
throw new InvalidArgumentException(sprintf(
32-
'File not found: %s',
33-
$filename,
34-
));
35-
}
36-
3729
parent::__construct(
3830
File::open($filename, 'r'),
3931
$name,
4032
$uploadFilename ?? basename($filename),
41-
self::getFileMediaType($filename, $mediaType),
42-
$fallbackFilename,
33+
self::filterFileMediaType($mediaType, $filename),
34+
$asciiFilename,
4335
);
4436
}
4537
}

src/Toolkit/Http/HttpUtil.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Salient\Http;
44

55
use Psr\Http\Message\RequestInterface as PsrRequestInterface;
6+
use Psr\Http\Message\StreamInterface as PsrStreamInterface;
67
use Psr\Http\Message\UriInterface as PsrUriInterface;
78
use Salient\Contract\Core\DateFormatterInterface;
89
use Salient\Contract\Http\Message\MultipartStreamInterface;
@@ -302,4 +303,39 @@ public static function getNameValueGenerator(iterable $items): Generator
302303
yield $item['name'] => $item['value'];
303304
}
304305
}
306+
307+
/**
308+
* Get the contents of a stream
309+
*/
310+
public static function getStreamContents(PsrStreamInterface $from): string
311+
{
312+
$buffer = '';
313+
while (!$from->eof()) {
314+
$data = $from->read(1048576);
315+
if ($data === '') {
316+
break;
317+
}
318+
$buffer .= $data;
319+
}
320+
return $buffer;
321+
}
322+
323+
/**
324+
* Copy the contents of one stream to another
325+
*/
326+
public static function copyStream(PsrStreamInterface $from, PsrStreamInterface $to): void
327+
{
328+
$buffer = '';
329+
while (!$from->eof()) {
330+
$data = $from->read(8192);
331+
if ($data === '') {
332+
break;
333+
}
334+
$buffer .= $data;
335+
$buffer = substr($buffer, $to->write($buffer));
336+
}
337+
while ($buffer !== '') {
338+
$buffer = substr($buffer, $to->write($buffer));
339+
}
340+
}
305341
}

src/Toolkit/Http/Message/AbstractMessage.php

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
use Salient\Core\Concern\ImmutableTrait;
1111
use Salient\Http\HasInnerHeadersTrait;
1212
use Salient\Http\Headers;
13-
use Salient\Utility\Exception\InvalidArgumentTypeException;
1413
use Salient\Utility\Arr;
1514
use Salient\Utility\Regex;
1615
use InvalidArgumentException;
@@ -24,6 +23,7 @@
2423
*/
2524
abstract class AbstractMessage implements MessageInterface
2625
{
26+
use HasBody;
2727
use HasInnerHeadersTrait;
2828
use ImmutableTrait;
2929

@@ -96,31 +96,6 @@ private function filterHeaders($headers): HeadersInterface
9696
: new Headers($headers ?? []);
9797
}
9898

99-
/**
100-
* @param PsrStreamInterface|resource|string|null $body
101-
*/
102-
private function filterBody($body): PsrStreamInterface
103-
{
104-
if ($body instanceof PsrStreamInterface) {
105-
return $body;
106-
}
107-
108-
if (is_string($body) || $body === null) {
109-
return Stream::fromString((string) $body);
110-
}
111-
112-
try {
113-
return new Stream($body);
114-
} catch (InvalidArgumentException $ex) {
115-
throw new InvalidArgumentTypeException(
116-
1,
117-
'body',
118-
PsrStreamInterface::class . '|resource|string|null',
119-
$body,
120-
);
121-
}
122-
}
123-
12499
/**
125100
* @inheritDoc
126101
*/
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Salient\Http\Message;
4+
5+
use Psr\Http\Message\StreamInterface as PsrStreamInterface;
6+
use Salient\Utility\Exception\InvalidArgumentTypeException;
7+
use InvalidArgumentException;
8+
9+
/**
10+
* @internal
11+
*/
12+
trait HasBody
13+
{
14+
/**
15+
* @param PsrStreamInterface|resource|string|null $body
16+
*/
17+
private function filterBody($body): PsrStreamInterface
18+
{
19+
if ($body instanceof PsrStreamInterface) {
20+
return $body;
21+
}
22+
23+
if (is_string($body) || $body === null) {
24+
return Stream::fromString((string) $body);
25+
}
26+
27+
try {
28+
return new Stream($body);
29+
} catch (InvalidArgumentException $ex) {
30+
throw new InvalidArgumentTypeException(
31+
1,
32+
'body',
33+
PsrStreamInterface::class . '|resource|string|null',
34+
$body,
35+
);
36+
}
37+
}
38+
}

src/Toolkit/Http/Message/MessageFactory.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
use Salient\Utility\File;
1919

2020
/**
21-
* A PSR-17 HTTP message factory
21+
* @api
2222
*/
2323
class MessageFactory implements
2424
PsrRequestFactoryInterface,
@@ -47,6 +47,8 @@ public function createResponse(
4747
}
4848

4949
/**
50+
* @inheritDoc
51+
*
5052
* @param mixed[] $serverParams
5153
*/
5254
public function createServerRequest(
@@ -98,7 +100,7 @@ public function createUploadedFile(
98100
$size,
99101
$error,
100102
$clientFilename,
101-
$clientMediaType
103+
$clientMediaType,
102104
);
103105
}
104106

src/Toolkit/Http/Message/MultipartStream.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ public function getContents(): string
190190
{
191191
$this->assertIsOpen();
192192

193-
return Stream::copyToString($this);
193+
return HttpUtil::getStreamContents($this);
194194
}
195195

196196
/**

src/Toolkit/Http/Message/Request.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@
44

55
use Psr\Http\Message\MessageInterface as PsrMessageInterface;
66
use Psr\Http\Message\RequestInterface as PsrRequestInterface;
7-
use Salient\Core\Concern\ImmutableTrait;
87

98
/**
10-
* A PSR-7 request (outgoing, client-side)
9+
* @api
1110
*
1211
* @extends AbstractRequest<PsrRequestInterface>
1312
*/
1413
class Request extends AbstractRequest
1514
{
16-
use ImmutableTrait;
17-
15+
/**
16+
* @api
17+
*/
1818
final public function __construct(
1919
string $method,
2020
$uri,

src/Toolkit/Http/Message/Response.php

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,17 @@
1111
use InvalidArgumentException;
1212

1313
/**
14-
* A PSR-7 response
14+
* @api
1515
*
1616
* @extends AbstractMessage<PsrResponseInterface>
1717
*/
1818
class Response extends AbstractMessage implements ResponseInterface
1919
{
2020
use ImmutableTrait;
2121

22+
/**
23+
* @var array<int,string>
24+
*/
2225
protected const STATUS_CODE = [
2326
100 => 'Continue',
2427
101 => 'Switching Protocols',
@@ -86,6 +89,9 @@ class Response extends AbstractMessage implements ResponseInterface
8689
protected int $StatusCode;
8790
protected ?string $ReasonPhrase;
8891

92+
/**
93+
* @api
94+
*/
8995
final public function __construct(
9096
int $code = 200,
9197
$body = null,
@@ -141,6 +147,34 @@ public function withStatus(int $code, string $reasonPhrase = ''): PsrResponseInt
141147
->with('ReasonPhrase', $this->filterReasonPhrase($code, $reasonPhrase));
142148
}
143149

150+
private function filterStatusCode(int $code): int
151+
{
152+
if ($code < 100 || $code > 599) {
153+
throw new InvalidArgumentException(
154+
sprintf('Invalid HTTP status code: %d', $code),
155+
);
156+
}
157+
return $code;
158+
}
159+
160+
private function filterReasonPhrase(int $code, ?string $reasonPhrase): ?string
161+
{
162+
return Str::coalesce($reasonPhrase, null)
163+
?? static::STATUS_CODE[$code]
164+
?? null;
165+
}
166+
167+
/**
168+
* @inheritDoc
169+
*/
170+
protected function getStartLine(): string
171+
{
172+
return Arr::implode(' ', [
173+
sprintf('HTTP/%s %d', $this->ProtocolVersion, $this->StatusCode),
174+
$this->ReasonPhrase,
175+
]);
176+
}
177+
144178
/**
145179
* @return array{status:int,statusText:string,httpVersion:string,cookies:array<array{name:string,value:string,path?:string,domain?:string,expires?:string,httpOnly?:bool,secure?:bool}>,headers:array<array{name:string,value:string}>,content:array{size:int,mimeType:string,text:string},redirectURL:string,headersSize:int,bodySize:int}
146180
*/
@@ -165,32 +199,4 @@ public function jsonSerialize(): array
165199
'redirectURL' => count($location) === 1 ? $location[0] : '',
166200
] + $response;
167201
}
168-
169-
/**
170-
* @inheritDoc
171-
*/
172-
protected function getStartLine(): string
173-
{
174-
return Arr::implode(' ', [
175-
sprintf('HTTP/%s %d', $this->ProtocolVersion, $this->StatusCode),
176-
$this->ReasonPhrase,
177-
]);
178-
}
179-
180-
private function filterStatusCode(int $code): int
181-
{
182-
if ($code < 100 || $code > 599) {
183-
throw new InvalidArgumentException(
184-
sprintf('Invalid HTTP status code: %d', $code)
185-
);
186-
}
187-
return $code;
188-
}
189-
190-
private function filterReasonPhrase(int $code, ?string $reasonPhrase): ?string
191-
{
192-
return Str::coalesce($reasonPhrase, null)
193-
?? static::STATUS_CODE[$code]
194-
?? null;
195-
}
196202
}

0 commit comments

Comments
 (0)