Skip to content

Commit a1e3976

Browse files
committed
Add a log middleware
1 parent 1b37f77 commit a1e3976

File tree

5 files changed

+248
-18
lines changed

5 files changed

+248
-18
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
}
2929
},
3030
"require-dev": {
31-
"phpunit/phpunit": "^6.5"
31+
"phpunit/phpunit": "^6.5",
32+
"mockery/mockery": "^1.2"
3233
}
3334
}

composer.lock

Lines changed: 114 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

readme.md

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ This is almost the same example as the previous one, but with a more flexible an
4141
`phpbg/rtsp` comes with some handy middlewares that will help you build a rfc compliant application:
4242
* `AutoCseq`: automatically add cseq header to your responses
4343
* `AutoContentLength`: automatically add content-length to your responses
44+
* `Log`: Automatically log request and responses
4445

4546
```php
4647
require __DIR__ . '/../vendor/autoload.php';
@@ -51,22 +52,7 @@ $loop = React\EventLoop\Factory::create();
5152
$socket = new \React\Socket\TcpServer('tcp://0.0.0.0:5540', $loop);
5253

5354
$middlewares = [
54-
function (\PhpBg\Rtsp\Message\Request $request, \React\Socket\ConnectionInterface $connection, $next) {
55-
// echo request middleware
56-
echo $request;
57-
return $next($request, $connection);
58-
},
59-
function (\PhpBg\Rtsp\Message\Request $request, \React\Socket\ConnectionInterface $connection, $next) {
60-
// echo response middleware
61-
$response = $next($request, $connection);
62-
if (!($response instanceof \React\Promise\PromiseInterface)) {
63-
$response = new \React\Promise\FulfilledPromise($response);
64-
}
65-
return $response->then(function($resolvedResponse) {
66-
echo $resolvedResponse."\r\n";
67-
return $resolvedResponse;
68-
});
69-
},
55+
new \PhpBg\Rtsp\Middleware\Log(),
7056
new \PhpBg\Rtsp\Middleware\AutoCseq(),
7157
new \PhpBg\Rtsp\Middleware\AutoContentLength(),
7258
function (\PhpBg\Rtsp\Message\Request $request, \React\Socket\ConnectionInterface $connection) {

src/Middleware/Log.php

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
/**
4+
* MIT License
5+
*
6+
* Copyright (c) 2018 Samuel CHEMLA
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in all
16+
* copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24+
* SOFTWARE.
25+
*/
26+
27+
namespace PhpBg\Rtsp\Middleware;
28+
29+
use PhpBg\Rtsp\Message\Request;
30+
use PhpBg\Rtsp\Message\Response;
31+
use Psr\Log\LoggerInterface;
32+
use Psr\Log\LogLevel;
33+
use React\Promise\FulfilledPromise;
34+
use React\Promise\PromiseInterface;
35+
use React\Socket\ConnectionInterface;
36+
37+
/**
38+
* Middleware that log requests and responses
39+
*/
40+
class Log
41+
{
42+
43+
private $logger;
44+
private $level;
45+
46+
public function __construct(LoggerInterface $logger, $level = LogLevel::DEBUG)
47+
{
48+
$this->logger = $logger;
49+
$this->level = $level;
50+
}
51+
52+
/**
53+
* This middleware just looks like a standard middleware: invokable, receive request and return response
54+
*
55+
* @param Request $request
56+
* @param ConnectionInterface $connection
57+
* @param callable $next
58+
* @return Response|PromiseInterface
59+
*/
60+
public function __invoke(Request $request, ConnectionInterface $connection, callable $next)
61+
{
62+
$this->logger->log($this->level, "Request:\r\n$request");
63+
$response = $next($request, $connection);
64+
if (!($response instanceof PromiseInterface)) {
65+
$response = new FulfilledPromise($response);
66+
}
67+
return $response->then(function (Response $resolvedResponse) use ($request) {
68+
$this->logger->log($this->level, "Response:\r\n$resolvedResponse");
69+
return $resolvedResponse;
70+
});
71+
}
72+
}

tests/Middleware/LogTest.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
/**
4+
* MIT License
5+
*
6+
* Copyright (c) 2018 Samuel CHEMLA
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in all
16+
* copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24+
* SOFTWARE.
25+
*/
26+
27+
namespace PhpBg\Rtsp\Tests\Middleware;
28+
29+
use Mockery\Adapter\Phpunit\MockeryTestCase;
30+
use PhpBg\Rtsp\Message\Request;
31+
use PhpBg\Rtsp\Message\Response;
32+
use PhpBg\Rtsp\Middleware\Log;
33+
use PhpBg\Rtsp\Tests\ConnectionStub;
34+
use PhpBg\Rtsp\Tests\Mock\EmptyResponseMiddleware;
35+
use PhpBg\Rtsp\Tests\Mock\ParametrizedResponseMiddleware;
36+
use Psr\Log\LoggerInterface;
37+
use React\Promise\PromiseInterface;
38+
39+
class LogTest extends MockeryTestCase
40+
{
41+
public function testAddHeader() {
42+
$logger = \Mockery::spy(LoggerInterface::class);
43+
$middleware = new Log($logger);
44+
45+
$request = new Request();
46+
47+
/** @var PromiseInterface $response */
48+
$response = $middleware($request, new ConnectionStub(), new ParametrizedResponseMiddleware());
49+
$extractedResponse = null;
50+
$response->then(function(Response $response) use (&$extractedResponse) {
51+
// We expect a FullFilledPromise that resolve instantly,
52+
// so extracting response and making assertions outside of callback secure them
53+
$extractedResponse = $response;
54+
});
55+
$this->assertTrue($extractedResponse instanceof Response);
56+
$logger->shouldHaveReceived('log')->twice();
57+
}
58+
}

0 commit comments

Comments
 (0)