Skip to content

Commit

Permalink
New version
Browse files Browse the repository at this point in the history
Changed custom Reader interface for `castor/io` ones
  • Loading branch information
mnavarrocarter committed Apr 29, 2021
1 parent 2b6530c commit 55e34b8
Show file tree
Hide file tree
Showing 22 changed files with 124 additions and 223 deletions.
42 changes: 25 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ as a second argument:
```php
<?php

use function MNC\Http\buffer;
use function MNC\Http\fetch;
use Castor\Io\Eof;

$response = fetch('https://some-domain.example/some-form', [
'method' => 'POST',
Expand All @@ -53,8 +53,14 @@ $response = fetch('https://some-domain.example/some-form', [
'body' => json_encode(['data' => 'value'])
]);

// Emit the response to stdout
while (($chunk = $response->body()->read()) !== null) {
// Emit the response to stdout in chunks
while (true) {
$chunk = '';
try {
$response->body()->read(4096, $chunk);
} catch (Eof $e) {
break;
}
echo $chunk;
}
```
Expand Down Expand Up @@ -86,7 +92,9 @@ echo $response->status()->reasonPhrase(); // OK
echo $response->headers()->has('content-type'); // true
echo $response->headers()->contains('content-type', 'html'); // true
echo $response->headers()->get('content-type'); // text/html;charset=utf-8
echo $response->body()->read(); // Outputs some bytes from the response body
$bytes = '';
echo $response->body()->read(4096, $bytes); // Allocates reader data into $bytes
echo $bytes; // Outputs some bytes from the response body
```

### Exception Handling
Expand All @@ -112,23 +120,23 @@ you most likely will be reacting in different ways to each one of them.
### Body Buffering

When you call the `MNC\Http\Response::body()` method you get an instance of
`MNC\Http\Io\Reader`, which is a very simple interface inspired in golang's
`Castor\Io\Reader`, which is a very simple interface inspired in golang's
`io.Reader`. This interface allows you to read a chunk of bytes until you reach
`EOF` in the data source.

Often times, you don't want to read byte per byte, but get the whole contents
of the body as a string at once. This library provides the `buffer` function
of the body as a string at once. This library provides the `readAll` function
as a convenience for that:

```php
<?php

use function MNC\Http\buffer;
use function Castor\Io\readAll;
use function MNC\Http\fetch;

$response = fetch('https://mnavarro.dev');

echo buffer($response->body()); // Buffers all the contents in memory and emits them.
echo readAll($response->body()); // Buffers all the contents in memory and emits them.
````

Buffering is a very good convenience, but it needs to be used with care, since it could
Expand All @@ -148,15 +156,15 @@ in content types like `text/plain`. However, there is big gain in user experienc
when we provide helpers like these in our apis.

This library provides an approach a bit more safe. If the response headers contain the
`application/json` content type, the `MNC\Http\Io\Reader` object of the body is internally
`application/json` content type, the ``Castor\Io\Reader`` object of the body is internally
decorated with a `MNC\Http\Encoding\Json` object. This object implements both the
`Reader` and `JsonDecoder` interfaces. Checking for the former is the safest way of
handling json payloads:
`Reader` interface. Checking for the former is the safest way of handling json
payloads:

```php
<?php

use MNC\Http\Encoding\JsonDecoder;
use MNC\Http\Encoding\Json;
use function MNC\Http\fetch;

$response = fetch('https://api.github.com/users/mnavarrocarter', [
Expand All @@ -167,7 +175,7 @@ $response = fetch('https://api.github.com/users/mnavarrocarter', [

$body = $response->body();

if ($body instanceof JsonDecoder) {
if ($body instanceof Json) {
var_dump($body->decode()); // Dumps the json as an array
} else {
// The response body is not json encoded
Expand Down Expand Up @@ -236,7 +244,7 @@ api, using the token internally.
```php
<?php

use MNC\Http\Encoding\JsonDecoder;
use MNC\Http\Encoding\Json;
use function MNC\Http\fetch;

$authenticate = static function (string $token) {
Expand All @@ -253,7 +261,7 @@ $authenticate = static function (string $token) {
]);

$body = $response->body();
if ($body instanceof JsonDecoder) {
if ($body instanceof Json) {
return $body->decode();
}
return null;
Expand Down Expand Up @@ -285,7 +293,7 @@ api client that I need to use.
```php
<?php

use MNC\Http\Encoding\JsonDecoder;
use MNC\Http\Encoding\Json;
use function MNC\Http\fetch;

// We start with an interface, a well defined contract.
Expand Down Expand Up @@ -325,7 +333,7 @@ final class FetchApiClient implements ApiClient
]);

$body = $response->body();
if ($body instanceof JsonDecoder) {
if ($body instanceof Json) {
return $body->decode();
}
return null;
Expand Down
7 changes: 4 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@
}
},
"require": {
"php": "^7.4|^8.0",
"ext-json": "*"
"php": ">=7.4",
"ext-json": "*",
"castor/io": "^0.2.1"
},
"scripts": {
"lint": "php-cs-fixer fix",
Expand All @@ -42,6 +43,6 @@
"amphp/http-server": "^2.1",
"amphp/http-server-static-content": "^1.0.6",
"mnavarrocarter/amp-http-router": "^0.1.0",
"friendsofphp/php-cs-fixer": "^2.16"
"friendsofphp/php-cs-fixer": "dev-master"
}
}
4 changes: 2 additions & 2 deletions examples/arguments.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

use function MNC\Http\buffer;
use function Castor\Io\readAll;
use function MNC\Http\fetch;

require_once __DIR__ . '/../vendor/autoload.php';
Expand All @@ -14,4 +14,4 @@
'body' => json_encode(['data' => 'value'])
]);

echo buffer($response->body()); // Emits the response
echo readAll($response->body()); // Emits the response
4 changes: 2 additions & 2 deletions examples/buffered.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

require_once __DIR__ . '/../vendor/autoload.php';

use function MNC\Http\buffer;
use function Castor\Io\readAll;
use function MNC\Http\fetch;

$response = fetch('https://mnavarro.dev');

echo buffer($response->body());
echo readAll($response->body());
4 changes: 2 additions & 2 deletions examples/class.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

use MNC\Http\Encoding\JsonDecoder;
use MNC\Http\Encoding\Json;
use function MNC\Http\fetch;

require_once __DIR__ . '/../vendor/autoload.php';
Expand Down Expand Up @@ -42,7 +42,7 @@ public static function authenticate(string $token): FetchApiClient
]);

$body = $response->body();
if ($body instanceof JsonDecoder) {
if ($body instanceof Json) {
return $body->decode();
}
return null;
Expand Down
4 changes: 2 additions & 2 deletions examples/composition.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

use MNC\Http\Encoding\JsonDecoder;
use MNC\Http\Encoding\Json;
use function MNC\Http\fetch;

$authenticated = static function (string $token) {
Expand All @@ -17,7 +17,7 @@
]);

$body = $response->body();
if ($body instanceof JsonDecoder) {
if ($body instanceof Json) {
return $body->decode();
}
return null;
Expand Down
4 changes: 3 additions & 1 deletion examples/info.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@
echo $response->headers()->has('content-type'); // true
echo $response->headers()->contains('content-type', 'html'); // true
echo $response->headers()->get('content-type'); // text/html;charset=utf-8
echo $response->body()->read(); // Outputs some bytes from the response body
$bytes = '';
$response->body()->read(4096, $bytes); // Reads data into $bytes
echo $bytes; // Outputs some bytes from the response body
4 changes: 2 additions & 2 deletions examples/json.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

require_once __DIR__ . '/../vendor/autoload.php';

use MNC\Http\Encoding\JsonDecoder;
use MNC\Http\Encoding\Json;
use function MNC\Http\fetch;

$response = fetch('https://api.github.com/users/mnavarrocarter', [
Expand All @@ -13,6 +13,6 @@

$body = $response->body();

if ($body instanceof JsonDecoder) {
if ($body instanceof Json) {
var_dump($body->decode()); // Dumps the json as an array
}
9 changes: 8 additions & 1 deletion examples/simple.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
<?php

use Castor\Io\Eof;
use function MNC\Http\fetch;

require_once __DIR__ . '/../vendor/autoload.php';

$response = fetch('https://mnavarro.dev');

while (($chunk = $response->body()->read()) !== null) {
while (true) {
$chunk = '';
try {
$response->body()->read(4096, $chunk);
} catch (Eof $e) {
break;
}
echo $chunk;
}
19 changes: 11 additions & 8 deletions src/Encoding/Json.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@

namespace MNC\Http\Encoding;

use Castor\Io\Error;
use function Castor\Io\readAll;
use Castor\Io\Reader;
use JsonException;
use function MNC\Http\buffer;
use MNC\Http\Io\Reader;
use MNC\Http\Io\ReaderError;

/**
* Class Json.
*/
final class Json implements Reader, JsonDecoder
final class Json implements Reader
{
private Reader $reader;

Expand All @@ -33,15 +33,18 @@ public function __construct(Reader $reader)
* @return array<mixed, mixed>
*
* @throws JsonException
* @throws ReaderError
* @throws Error
*/
public function decode(): array
{
return json_decode(buffer($this->reader), true, 512, JSON_THROW_ON_ERROR);
return json_decode(readAll($this->reader), true, 512, JSON_THROW_ON_ERROR);
}

public function read(int $bytes = self::DEFAULT_CHUNK_SIZE): ?string
/**
* {@inheritDoc}
*/
public function read(int $length, string &$bytes): int
{
return $this->reader->read($bytes);
return $this->reader->read($length, $bytes);
}
}
27 changes: 0 additions & 27 deletions src/Encoding/JsonDecoder.php

This file was deleted.

2 changes: 1 addition & 1 deletion src/Headers.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public function filter(callable $callable): array
{
return array_filter(
$this->headers,
fn (string $value, string $name) => $callable($value, $name),
static fn (string $value, string $name) => $callable($value, $name),
ARRAY_FILTER_USE_BOTH
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/HttpResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

namespace MNC\Http;

use Castor\Io\Reader;
use MNC\Http\Encoding\Json;
use MNC\Http\Io\Reader;

/**
* Class Response.
Expand Down
27 changes: 0 additions & 27 deletions src/Io/Reader.php

This file was deleted.

19 changes: 0 additions & 19 deletions src/Io/ReaderError.php

This file was deleted.

Loading

0 comments on commit 55e34b8

Please sign in to comment.