Skip to content

Commit f21e6ad

Browse files
committed
Add CookieSendMiddleware
1 parent a0ca183 commit f21e6ad

File tree

3 files changed

+244
-0
lines changed

3 files changed

+244
-0
lines changed

src/CookieSendMiddleware.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace HttpSoft\Cookie;
6+
7+
use Psr\Http\Message\ResponseInterface;
8+
use Psr\Http\Message\ServerRequestInterface;
9+
use Psr\Http\Server\MiddlewareInterface;
10+
use Psr\Http\Server\RequestHandlerInterface;
11+
12+
final class CookieSendMiddleware implements MiddlewareInterface
13+
{
14+
/**
15+
* @var CookieManagerInterface
16+
*/
17+
private CookieManagerInterface $cookies;
18+
19+
/**
20+
* @var bool
21+
*/
22+
private bool $removeResponseCookies;
23+
24+
/**
25+
* @param CookieManagerInterface $cookies object with cookies to set in response.
26+
* @param bool $removeResponseCookies whether to remove previously set cookies from the response.
27+
*/
28+
public function __construct(CookieManagerInterface $cookies, bool $removeResponseCookies = true)
29+
{
30+
$this->cookies = $cookies;
31+
$this->removeResponseCookies = $removeResponseCookies;
32+
}
33+
34+
/**
35+
* @param ServerRequestInterface $request
36+
* @param RequestHandlerInterface $handler
37+
* @return ResponseInterface
38+
*/
39+
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
40+
{
41+
$response = $handler->handle($request);
42+
return $this->cookies->send($response, $this->removeResponseCookies);
43+
}
44+
}

tests/CookieSendMiddlewareTest.php

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace HttpSoft\Tests\Cookie;
6+
7+
use HttpSoft\Cookie\Cookie;
8+
use HttpSoft\Cookie\CookieInterface;
9+
use HttpSoft\Cookie\CookieManager;
10+
use HttpSoft\Cookie\CookieSendMiddleware;
11+
use HttpSoft\Message\Response;
12+
use HttpSoft\Message\ServerRequest;
13+
use HttpSoft\Tests\Cookie\TestAsset\WrapResponseRequestHandler;
14+
use PHPUnit\Framework\TestCase;
15+
use Psr\Http\Message\ResponseInterface;
16+
17+
use function count;
18+
19+
class CookieSendMiddlewareTest extends TestCase
20+
{
21+
/**
22+
* @var array
23+
*/
24+
private array $cookies;
25+
26+
/**
27+
* @var ServerRequest
28+
*/
29+
private ServerRequest $request;
30+
31+
/**
32+
* @var CookieInterface
33+
*/
34+
private CookieInterface $first;
35+
36+
/**
37+
* @var CookieInterface
38+
*/
39+
private CookieInterface $second;
40+
41+
public function setUp(): void
42+
{
43+
$this->first = new Cookie('first', 'value');
44+
$this->second = new Cookie('second', '1234');
45+
$this->cookies = [
46+
$this->first->getName() => $this->first,
47+
$this->second->getName() => $this->second,
48+
];
49+
$this->request = new ServerRequest();
50+
}
51+
52+
public function testProcess(): void
53+
{
54+
$emptyResponse = new Response();
55+
$manager = new CookieManager($this->cookies);
56+
$handler = new WrapResponseRequestHandler($emptyResponse);
57+
58+
$middleware = new CookieSendMiddleware($manager);
59+
$response = $middleware->process($this->request, $handler);
60+
61+
$this->assertNotSame($emptyResponse, $response);
62+
$this->assertInstanceOf(ResponseInterface::class, $response);
63+
$this->assertSame([(string) $this->first, (string) $this->second], $response->getHeader('set-cookie'));
64+
}
65+
66+
public function testProcessWithEmptyCookies(): void
67+
{
68+
$emptyResponse = new Response();
69+
$manager = new CookieManager();
70+
$handler = new WrapResponseRequestHandler($emptyResponse);
71+
72+
$middleware = new CookieSendMiddleware($manager);
73+
$response = $middleware->process($this->request, $handler);
74+
75+
$this->assertInstanceOf(ResponseInterface::class, $response);
76+
$this->assertSame([], $response->getHeader('set-cookie'));
77+
}
78+
79+
public function testProcessRepeatedly(): void
80+
{
81+
$emptyResponse = new Response();
82+
$manager = new CookieManager([$this->first]);
83+
84+
$middleware = new CookieSendMiddleware($manager);
85+
$handler = new WrapResponseRequestHandler($emptyResponse);
86+
87+
$firstResponse = $middleware->process($this->request, $handler);
88+
$this->assertNotSame($emptyResponse, $firstResponse);
89+
$this->assertInstanceOf(ResponseInterface::class, $firstResponse);
90+
$this->assertSame([(string) $this->first], $firstResponse->getHeader('set-cookie'));
91+
92+
$manager->set($this->second);
93+
$this->assertSame($this->cookies, $manager->getAll());
94+
$this->assertSame(count($this->cookies), $manager->count());
95+
$this->assertTrue($manager->has('second'));
96+
$this->assertTrue($manager->has('first'));
97+
98+
$middleware = new CookieSendMiddleware($manager);
99+
$handler = new WrapResponseRequestHandler($firstResponse);
100+
101+
$secondResponse = $middleware->process($this->request, $handler);
102+
$this->assertNotSame($firstResponse, $secondResponse);
103+
$this->assertInstanceOf(ResponseInterface::class, $secondResponse);
104+
$this->assertSame([(string) $this->first, (string) $this->second], $secondResponse->getHeader('set-cookie'));
105+
}
106+
107+
public function testProcessRepeatedlyAndClear(): void
108+
{
109+
$emptyResponse = new Response();
110+
$manager = new CookieManager([$this->first]);
111+
112+
$middleware = new CookieSendMiddleware($manager);
113+
$handler = new WrapResponseRequestHandler($emptyResponse);
114+
115+
$firstResponse = $middleware->process($this->request, $handler);
116+
$this->assertNotSame($emptyResponse, $firstResponse);
117+
$this->assertInstanceOf(ResponseInterface::class, $firstResponse);
118+
$this->assertSame([(string) $this->first], $firstResponse->getHeader('set-cookie'));
119+
120+
$manager->clear();
121+
$this->assertSame([], $manager->getAll());
122+
$this->assertSame(0, $manager->count());
123+
124+
$manager->set($this->second);
125+
$this->assertSame([$this->second->getName() => $this->second], $manager->getAll());
126+
$this->assertSame(count([$this->second]), $manager->count());
127+
$this->assertTrue($manager->has('second'));
128+
$this->assertFalse($manager->has('first'));
129+
130+
$middleware = new CookieSendMiddleware($manager);
131+
$handler = new WrapResponseRequestHandler($firstResponse);
132+
133+
$secondResponse = $middleware->process($this->request, $handler);
134+
$this->assertNotSame($firstResponse, $secondResponse);
135+
$this->assertInstanceOf(ResponseInterface::class, $secondResponse);
136+
$this->assertSame([(string) $this->second], $secondResponse->getHeader('set-cookie'));
137+
}
138+
139+
public function testProcessRepeatedlyWithReplace(): void
140+
{
141+
$baseResponse = (new Response())->withHeader('set-cookie', (string) $this->first);
142+
$manager = new CookieManager([$this->first]);
143+
144+
$middleware = new CookieSendMiddleware($manager);
145+
$handler = new WrapResponseRequestHandler($baseResponse);
146+
147+
$firstResponse = $middleware->process($this->request, $handler);
148+
$this->assertNotSame($baseResponse, $firstResponse);
149+
$this->assertInstanceOf(ResponseInterface::class, $firstResponse);
150+
$this->assertSame([(string) $this->first], $firstResponse->getHeader('set-cookie'));
151+
}
152+
153+
public function testProcessRepeatedlyWithoutReplace(): void
154+
{
155+
$baseResponse = (new Response())->withHeader('set-cookie', (string) $this->first);
156+
$manager = new CookieManager([$this->first]);
157+
158+
$middleware = new CookieSendMiddleware($manager, false);
159+
$handler = new WrapResponseRequestHandler($baseResponse);
160+
161+
$firstResponse = $middleware->process($this->request, $handler);
162+
$this->assertNotSame($baseResponse, $firstResponse);
163+
$this->assertInstanceOf(ResponseInterface::class, $firstResponse);
164+
$this->assertSame([(string) $this->first, (string) $this->first], $firstResponse->getHeader('set-cookie'));
165+
}
166+
}
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 HttpSoft\Tests\Cookie\TestAsset;
6+
7+
use Psr\Http\Message\ResponseInterface;
8+
use Psr\Http\Message\ServerRequestInterface;
9+
use Psr\Http\Server\RequestHandlerInterface;
10+
11+
class WrapResponseRequestHandler implements RequestHandlerInterface
12+
{
13+
/**
14+
* @var ResponseInterface
15+
*/
16+
private ResponseInterface $response;
17+
18+
/**
19+
* @param ResponseInterface $response
20+
*/
21+
public function __construct(ResponseInterface $response)
22+
{
23+
$this->response = $response;
24+
}
25+
26+
/**
27+
* @param ServerRequestInterface $request
28+
* @return ResponseInterface
29+
*/
30+
public function handle(ServerRequestInterface $request): ResponseInterface
31+
{
32+
return $this->response;
33+
}
34+
}

0 commit comments

Comments
 (0)