Skip to content

Commit

Permalink
Add response trailers
Browse files Browse the repository at this point in the history
  • Loading branch information
rauanmayemir committed Sep 10, 2024
1 parent e041c42 commit af71e16
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 3 deletions.
73 changes: 73 additions & 0 deletions src/ResponseTrailers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

declare(strict_types=1);

namespace Spiral\RoadRunner\GRPC;

use Spiral\RoadRunner\GRPC\Internal\Json;

/**
* @psalm-type THeaderKey = non-empty-string
* @psalm-type THeaderValue = string
* @implements \IteratorAggregate<THeaderKey, string>
*/
final class ResponseTrailers implements \IteratorAggregate, \Countable
{
/**
* @var array<THeaderKey, THeaderValue>
*/
private array $trailers = [];

/**
* @param iterable<THeaderKey, THeaderValue> $trailers
*/
public function __construct(iterable $trailers = [])
{
foreach ($trailers as $key => $value) {
$this->set($key, $value);
}
}

/**
* @param THeaderKey $key
* @param THeaderValue $value
*/
public function set(string $key, string $value): void
{
$this->trailers[$key] = $value;
}

/**
* @param THeaderKey $key
* @param string|null $default
* @return THeaderValue|null
*/
public function get(string $key, string $default = null): ?string
{
return $this->trailers[$key] ?? $default;
}

public function getIterator(): \Traversable
{
return new \ArrayIterator($this->trailers);
}

public function count(): int
{
return \count($this->trailers);
}

/**
* @throws \JsonException
*/
public function packTrailers(): string
{
// If an empty array is serialized, it is cast to the string "[]"
// instead of object string "{}"
if ($this->trailers === []) {
return '{}';
}

return Json::encode($this->trailers);
}
}
16 changes: 13 additions & 3 deletions src/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,19 +74,28 @@ public function serve(WorkerInterface $worker = null, callable $finalize = null)
}

$responseHeaders = new ResponseHeaders();
$responseTrailers = new ResponseTrailers();

try {
$call = CallContext::decode($request->header);

$context = (new Context($call->context))
->withValue(ResponseHeaders::class, $responseHeaders);
$context = new Context(array_merge(
$call->context,
[
ResponseHeaders::class => $responseHeaders,
ResponseTrailers::class => $responseTrailers
]
));

$response = $this->invoke($call->service, $call->method, $context, $request->body);

$this->workerSend(
worker: $worker,
body: $response,
headers: $responseHeaders->packHeaders()
headers: Json::encode([
'headers' => $responseHeaders->packHeaders(),
'trailers' => $responseTrailers->packTrailers(),
]),
);
} catch (GRPCExceptionInterface $e) {
$this->workerSend(
Expand All @@ -95,6 +104,7 @@ public function serve(WorkerInterface $worker = null, callable $finalize = null)
headers: Json::encode([
'error' => $this->createGrpcError($e),
'headers' => $responseHeaders->packHeaders(),
'trailers' => $responseTrailers->packTrailers(),
]),
);
} catch (\Throwable $e) {
Expand Down

0 comments on commit af71e16

Please sign in to comment.