Skip to content

Commit ffc99b5

Browse files
authored
Merge pull request #4 from Micro-PHP/v1.0.2-release
v1.0.3-release
2 parents a5de462 + 0c43d21 commit ffc99b5

15 files changed

+345
-106
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
.idea
12
vendor
23
composer.lock
34
.phpunit.result.cache

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
},
2929
"autoload-dev": {
3030
"psr-4": {
31-
"Micro\\Plugin\\Http\\Test\\": "tests/"
31+
"Micro\\Plugin\\Http\\Test\\Unit\\": "tests/Unit"
3232
}
3333
},
3434
"config": {

src/Business/Executor/HttpExecutorLoggerAwareDecorator.php

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
namespace Micro\Plugin\Http\Business\Executor;
1515

1616
use Micro\Plugin\Http\Business\Logger\Formatter\LogFormatterInterface;
17+
use Micro\Plugin\Http\Exception\HttpException;
1718
use Psr\Log\LoggerInterface;
1819
use Symfony\Component\HttpFoundation\Request;
1920
use Symfony\Component\HttpFoundation\Response;
@@ -40,12 +41,35 @@ public function execute(Request $request, bool $flush = true): Response
4041
$response = null;
4142
try {
4243
$response = $this->decorated->execute($request, $flush);
43-
} catch (\Throwable $throwable) {
44+
} catch (HttpException $exception) {
45+
if ($exception->getCode() >= 500) {
46+
$this->loggerError->critical(
47+
$this->logErrorFormatter->format($request, $response, $exception),
48+
[
49+
'exception' => $exception,
50+
]
51+
);
52+
53+
throw $exception;
54+
}
55+
56+
$this->loggerError->info(
57+
$this->logErrorFormatter->format($request, $response, $exception),
58+
[
59+
'exception' => $exception,
60+
]
61+
);
62+
63+
throw $exception;
64+
} catch (\Throwable $exception) {
4465
$this->loggerError->critical(
45-
$this->logErrorFormatter->format($request, $response, $throwable)
66+
$this->logErrorFormatter->format($request, $response, $exception),
67+
[
68+
'exception' => $exception,
69+
]
4670
);
4771

48-
throw $throwable;
72+
throw $exception;
4973
} finally {
5074
$this->loggerAccess->info(
5175
$this->logAccessFormatter->format($request, $response, null)
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Micro framework package.
7+
*
8+
* (c) Stanislau Komar <kost@micro-php.net>
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Micro\Plugin\Http\Business\Logger\Formatter\Format;
15+
16+
use Symfony\Component\HttpFoundation\Request;
17+
use Symfony\Component\HttpFoundation\Response;
18+
19+
/**
20+
* @author Stanislau Komar <head.trackingsoft@gmail.com>
21+
*
22+
* @codeCoverageIgnore
23+
*/
24+
abstract class AbstractHeaderFormatter implements LogFormatterConcreteInterface
25+
{
26+
public function format(Request $request, ?Response $response, ?\Throwable $exception, ?string $message = null): string
27+
{
28+
if (!$message) {
29+
return '';
30+
}
31+
32+
$matchPattern = sprintf('/{{%s_header\.(.*?)}}/', $this->getPrefix());
33+
$matched = preg_match_all($matchPattern, $message, $matches);
34+
if (!$matched || 2 !== \count($matches)) {
35+
return $message;
36+
}
37+
38+
$matchesPattern = $matches[0];
39+
$matchesVars = $matches[1];
40+
41+
$countMatches = \count($matchesVars);
42+
43+
for ($i = 0; $i < $countMatches; ++$i) {
44+
$message = str_ireplace(
45+
$matchesPattern[$i],
46+
$this->getValue($request, $response, $matchesVars[$i]),
47+
$message
48+
);
49+
}
50+
51+
return $message;
52+
}
53+
54+
abstract protected function getValue(Request $request, ?Response $response, string $matchedVar): string;
55+
56+
abstract protected function getPrefix(): string;
57+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Micro framework package.
7+
*
8+
* (c) Stanislau Komar <kost@micro-php.net>
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Micro\Plugin\Http\Business\Logger\Formatter\Format;
15+
16+
use Symfony\Component\HttpFoundation\Request;
17+
use Symfony\Component\HttpFoundation\Response;
18+
19+
/**
20+
* @author Stanislau Komar <head.trackingsoft@gmail.com>
21+
*/
22+
class HeadersRequestFormatter extends AbstractHeaderFormatter
23+
{
24+
/**
25+
* @var string[]
26+
*/
27+
private readonly array $securedHeadersList;
28+
29+
/**
30+
* @param string[] $securedHeadersList
31+
*/
32+
public function __construct(
33+
array $securedHeadersList
34+
) {
35+
$this->securedHeadersList = array_map('mb_strtolower', $securedHeadersList);
36+
}
37+
38+
protected function getPrefix(): string
39+
{
40+
return 'request';
41+
}
42+
43+
protected function getValue(Request $request, ?Response $response, string $matchedVar): string
44+
{
45+
if (!$matchedVar) {
46+
return '';
47+
}
48+
$isSingleVar = true;
49+
if ('*' === $matchedVar) {
50+
$headersArray = $request->headers->all();
51+
$isSingleVar = false;
52+
} else {
53+
$tmpHeaderValue = $request->headers->get($matchedVar);
54+
55+
$headersArray = [$matchedVar => $tmpHeaderValue];
56+
}
57+
58+
$headersArray = array_change_key_case($headersArray);
59+
foreach ($this->securedHeadersList as $securedHeader) {
60+
if (!\array_key_exists($securedHeader, $headersArray)) {
61+
continue;
62+
}
63+
/** @var string[] $securedHeaderValue */
64+
$securedHeaderValue = $headersArray[$securedHeader];
65+
66+
$headersArray[$securedHeader] = array_map(fn (mixed $value) => '** Secured **', $securedHeaderValue);
67+
}
68+
69+
if ($isSingleVar) {
70+
$headersArray = array_values($headersArray);
71+
if (1 === \count($headersArray)) {
72+
$tmpValue = $headersArray[0];
73+
if (!\is_array($tmpValue)) {
74+
return (string) $tmpValue;
75+
}
76+
}
77+
}
78+
79+
return (string) json_encode($headersArray);
80+
}
81+
}

src/Business/Logger/Formatter/Format/HttpRefererFormat.php

Lines changed: 0 additions & 33 deletions
This file was deleted.

src/Business/Logger/Formatter/LogFormatterFactory.php

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,33 +13,25 @@
1313

1414
namespace Micro\Plugin\Http\Business\Logger\Formatter;
1515

16-
use Micro\Plugin\Http\Business\Logger\Formatter\Format\HttpRefererFormat;
17-
use Micro\Plugin\Http\Business\Logger\Formatter\Format\IpFormat;
18-
use Micro\Plugin\Http\Business\Logger\Formatter\Format\MethodFormat;
19-
use Micro\Plugin\Http\Business\Logger\Formatter\Format\RequestBodyFormat;
20-
use Micro\Plugin\Http\Business\Logger\Formatter\Format\RequestFormat;
21-
use Micro\Plugin\Http\Business\Logger\Formatter\Format\StatusFormat;
22-
use Micro\Plugin\Http\Business\Logger\Formatter\Format\TimeFormat;
23-
use Micro\Plugin\Http\Business\Logger\Formatter\Format\UsernameFormat;
16+
use Micro\Plugin\Http\Business\Logger\Formatter\Format\LogFormatterConcreteInterface;
2417

2518
/**
2619
* @author Stanislau Komar <kost@micro-php.net>
2720
*/
28-
class LogFormatterFactory implements LogFormatterFactoryInterface
21+
readonly class LogFormatterFactory implements LogFormatterFactoryInterface
2922
{
23+
/**
24+
* @param iterable<LogFormatterConcreteInterface> $logFormatterCollection
25+
*/
26+
public function __construct(
27+
private iterable $logFormatterCollection,
28+
) {
29+
}
30+
3031
public function create(string $format): LogFormatterInterface
3132
{
3233
return new LogFormatter(
33-
[
34-
new HttpRefererFormat(),
35-
new IpFormat(),
36-
new MethodFormat(),
37-
new RequestBodyFormat(),
38-
new RequestFormat(),
39-
new StatusFormat(),
40-
new TimeFormat(),
41-
new UsernameFormat(),
42-
],
34+
$this->logFormatterCollection,
4335
$format
4436
);
4537
}

src/HttpLoggerPlugin.php

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@
2020
use Micro\Framework\Kernel\Plugin\PluginDependedInterface;
2121
use Micro\Plugin\Http\Business\Executor\HttpExecutorLoggerAwareDecoratorFactory;
2222
use Micro\Plugin\Http\Business\Executor\RouteExecutorFactoryInterface;
23+
use Micro\Plugin\Http\Business\Logger\Formatter\Format\HeadersRequestFormatter;
24+
use Micro\Plugin\Http\Business\Logger\Formatter\Format\IpFormat;
25+
use Micro\Plugin\Http\Business\Logger\Formatter\Format\MethodFormat;
26+
use Micro\Plugin\Http\Business\Logger\Formatter\Format\RequestBodyFormat;
27+
use Micro\Plugin\Http\Business\Logger\Formatter\Format\RequestFormat;
28+
use Micro\Plugin\Http\Business\Logger\Formatter\Format\StatusFormat;
29+
use Micro\Plugin\Http\Business\Logger\Formatter\Format\TimeFormat;
30+
use Micro\Plugin\Http\Business\Logger\Formatter\Format\UsernameFormat;
2331
use Micro\Plugin\Http\Business\Logger\Formatter\LogFormatterFactory;
2432
use Micro\Plugin\Http\Business\Logger\Formatter\LogFormatterFactoryInterface;
2533
use Micro\Plugin\Http\Decorator\HttpFacadeLoggerDecorator;
@@ -73,7 +81,18 @@ protected function createHttpExecutorFactory(): RouteExecutorFactoryInterface
7381

7482
protected function createLogFormatterFactory(): LogFormatterFactoryInterface
7583
{
76-
return new LogFormatterFactory();
84+
return new LogFormatterFactory(
85+
[
86+
new HeadersRequestFormatter($this->configuration()->getRequestHeadersSecuredList()),
87+
new IpFormat(),
88+
new MethodFormat(),
89+
new RequestBodyFormat(),
90+
new RequestFormat(),
91+
new StatusFormat(),
92+
new TimeFormat(),
93+
new UsernameFormat(),
94+
]
95+
);
7796
}
7897

7998
public function getDependedPlugins(): iterable

src/HttpLoggerPluginConfiguration.php

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ class HttpLoggerPluginConfiguration extends PluginConfiguration implements HttpL
2323
{
2424
public const CFG_LOGGER_ACCESS = 'MICRO_HTTP_LOGGER_ACCESS';
2525
public const CFG_LOGGER_ERROR = 'MICRO_HTTP_LOGGER_ERROR';
26+
public const CFG_LOGGER_HEADERS_SECURED = 'MICRO_HTTP_LOGGER_HEADERS_SECURED';
27+
public const CFG_LOGGER_HEADERS_SECURED_DEFAULT = 'Authorization';
2628
public const CFG_DECORATION_WEIGHT = 'MICRO_HTTP_LOGGER_DECORATION_WEIGHT';
27-
2829
public const CFG_HTTP_LOGGER_ACCESS_FORMAT = 'MICRO_HTTP_LOGGER_ACCESS_FORMAT';
2930
public const CFG_HTTP_LOGGER_ERROR_FORMAT = 'MICRO_HTTP_LOGGER_ERROR_FORMAT';
30-
public const LOGGER_ERROR_FORMAT_DEFAULT = '{{remote_addr}} - {{remote_user}} [{{time}}] "{{request}}" {{status}}';
31-
public const LOGGER_ACCESS_FORMAT_DEFAULT = '{{remote_addr}} - {{remote_user}} [{{time}}] "{{request}}" {{status}} {{http_referer}} {{http_user_agent}}';
32-
31+
public const LOGGER_ERROR_FORMAT_DEFAULT = '{{remote_addr}} - {{remote_user}} [{{status}}] "{{request}}"';
32+
public const LOGGER_ACCESS_FORMAT_DEFAULT = '{{remote_addr}} - {{remote_user}} [{{status}}] "{{request}}" {{request_header.http-referer}} {{request_header.user-agent}}';
3333
public const DECORATION_DEFAULT = 10;
3434

3535
public function getAccessLoggerName(): string
@@ -56,4 +56,14 @@ public function getAccessLogFormat(): string
5656
{
5757
return $this->configuration->get(self::CFG_HTTP_LOGGER_ACCESS_FORMAT, self::LOGGER_ACCESS_FORMAT_DEFAULT, false);
5858
}
59+
60+
public function getRequestHeadersSecuredList(): array
61+
{
62+
return $this->explodeStringToArray(
63+
$this->configuration->get(
64+
self::CFG_LOGGER_HEADERS_SECURED,
65+
self::CFG_LOGGER_HEADERS_SECURED_DEFAULT
66+
)
67+
);
68+
}
5969
}

src/HttpLoggerPluginConfigurationInterface.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,10 @@ public function getErrorLogFormat(): string;
2626

2727
public function getAccessLogFormat(): string;
2828

29+
/**
30+
* @return string[]
31+
*/
32+
public function getRequestHeadersSecuredList(): array;
33+
2934
public function getWeight(): int;
3035
}

0 commit comments

Comments
 (0)