Skip to content

Commit 7397579

Browse files
committed
Feature: add Bridge\Psr7Response for Nette UI integration
Add a dedicated response class implementing Nette\Application\IResponse that wraps a PSR-7 ResponseInterface. This enables cleaner integration in Nette presenters: $this->sendResponse(new Psr7Response($psr7)); Closes #26
1 parent cafc595 commit 7397579

File tree

2 files changed

+155
-0
lines changed

2 files changed

+155
-0
lines changed

src/Bridge/Psr7Response.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Contributte\Psr7\Bridge;
4+
5+
use Nette\Application\Response as ApplicationResponse;
6+
use Nette\Http\IRequest;
7+
use Nette\Http\IResponse;
8+
use Psr\Http\Message\ResponseInterface;
9+
10+
class Psr7Response implements ApplicationResponse
11+
{
12+
13+
public function __construct(
14+
private ResponseInterface $response,
15+
)
16+
{
17+
}
18+
19+
public function getResponse(): ResponseInterface
20+
{
21+
return $this->response;
22+
}
23+
24+
public function send(IRequest $httpRequest, IResponse $httpResponse): void
25+
{
26+
$this->sendStatus($httpResponse);
27+
$this->sendHeaders($httpResponse);
28+
$this->sendBody();
29+
}
30+
31+
protected function sendStatus(IResponse $httpResponse): void
32+
{
33+
$httpResponse->setCode($this->response->getStatusCode(), $this->response->getReasonPhrase());
34+
}
35+
36+
protected function sendHeaders(IResponse $httpResponse): void
37+
{
38+
foreach ($this->response->getHeaders() as $name => $values) {
39+
foreach ($values as $value) {
40+
$httpResponse->setHeader($name, $value);
41+
}
42+
}
43+
}
44+
45+
protected function sendBody(): void
46+
{
47+
$stream = $this->response->getBody();
48+
$stream->rewind();
49+
50+
while (!$stream->eof()) {
51+
echo $stream->read(8192);
52+
}
53+
}
54+
55+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Tests\Cases\Bridge;
4+
5+
use Contributte\Psr7\Bridge\Psr7Response;
6+
use Contributte\Psr7\Psr7Response as Psr7MessageResponse;
7+
use Contributte\Tester\Utils\Httpkit;
8+
use Nette\Http\Request;
9+
use Nette\Http\Response;
10+
use Nette\Http\UrlScript;
11+
use Psr\Http\Message\ResponseInterface;
12+
use Tester\Assert;
13+
use Tester\TestCase;
14+
15+
require_once __DIR__ . '/../../bootstrap.php';
16+
17+
class Psr7ResponseTest extends TestCase
18+
{
19+
20+
public function testGetResponse(): void
21+
{
22+
$psr7Response = Psr7MessageResponse::fromGlobals();
23+
$response = new Psr7Response($psr7Response);
24+
25+
Assert::type(ResponseInterface::class, $response->getResponse());
26+
Assert::same($psr7Response, $response->getResponse());
27+
}
28+
29+
public function testSend(): void
30+
{
31+
$psr7Response = Psr7MessageResponse::fromGlobals()
32+
->withStatus(201)
33+
->withHeader('X-Custom', 'test-value')
34+
->withHeader('Content-Type', 'application/json');
35+
36+
$psr7Response->getBody()->write('{"foo":"bar"}');
37+
38+
$response = new Psr7Response($psr7Response);
39+
40+
$httpRequest = new Request(new UrlScript('https://example.com'));
41+
$httpResponse = new Response();
42+
43+
Httpkit::wrap(function () use ($response, $httpRequest, $httpResponse): void {
44+
ob_start();
45+
$response->send($httpRequest, $httpResponse);
46+
$output = ob_get_clean();
47+
48+
Assert::equal('{"foo":"bar"}', $output);
49+
});
50+
51+
Assert::equal(201, $httpResponse->getCode());
52+
}
53+
54+
public function testSendWithEmptyBody(): void
55+
{
56+
$psr7Response = Psr7MessageResponse::fromGlobals()
57+
->withStatus(204);
58+
59+
$response = new Psr7Response($psr7Response);
60+
61+
$httpRequest = new Request(new UrlScript('https://example.com'));
62+
$httpResponse = new Response();
63+
64+
Httpkit::wrap(function () use ($response, $httpRequest, $httpResponse): void {
65+
ob_start();
66+
$response->send($httpRequest, $httpResponse);
67+
$output = ob_get_clean();
68+
69+
Assert::equal('', $output);
70+
});
71+
72+
Assert::equal(204, $httpResponse->getCode());
73+
}
74+
75+
public function testSendWithMultipleHeaders(): void
76+
{
77+
$psr7Response = Psr7MessageResponse::fromGlobals()
78+
->withStatus(200)
79+
->withHeader('X-First', 'first')
80+
->withHeader('X-Second', 'second');
81+
82+
$psr7Response->getBody()->write('content');
83+
84+
$response = new Psr7Response($psr7Response);
85+
86+
$httpRequest = new Request(new UrlScript('https://example.com'));
87+
$httpResponse = new Response();
88+
89+
Httpkit::wrap(function () use ($response, $httpRequest, $httpResponse): void {
90+
ob_start();
91+
$response->send($httpRequest, $httpResponse);
92+
ob_end_clean();
93+
});
94+
95+
Assert::equal(200, $httpResponse->getCode());
96+
}
97+
98+
}
99+
100+
(new Psr7ResponseTest())->run();

0 commit comments

Comments
 (0)