ソースを参照

Fix exception trap for 404

mscherer 2 年 前
コミット
1427c49f9e
3 ファイル変更112 行追加17 行削除
  1. 103 0
      src/Error/ExceptionTrap.php
  2. 2 4
      src/Utility/Language.php
  3. 7 13
      src/Utility/Number.php

+ 103 - 0
src/Error/ExceptionTrap.php

@@ -3,7 +3,13 @@
 namespace Tools\Error;
 
 use Cake\Core\Configure;
+use Cake\Core\Exception\CakeException;
+use Cake\Error\Debugger;
 use Cake\Error\ExceptionTrap as CoreExceptionTrap;
+use Cake\Http\ServerRequest;
+use Cake\Log\Log;
+use Psr\Http\Message\ServerRequestInterface;
+use Throwable;
 
 /**
  * Custom ErrorHandler to not mix the 404 exceptions with the rest of "real" errors in the error.log file.
@@ -27,6 +33,8 @@ use Cake\Error\ExceptionTrap as CoreExceptionTrap;
  */
 class ExceptionTrap extends CoreExceptionTrap {
 
+	use ErrorHandlerTrait;
+
 	/**
 	 * Constructor
 	 *
@@ -41,4 +49,99 @@ class ExceptionTrap extends CoreExceptionTrap {
 		parent::__construct($config);
 	}
 
+	/**
+	 * Log an error for the exception if applicable.
+	 *
+	 * @param \Exception $exception The exception to log a message for.
+	 * @param \Psr\Http\Message\ServerRequestInterface|null $request The current request.
+	 *
+	 * @return void
+	 */
+	public function logException(Throwable $exception, ?ServerRequestInterface $request = null): void {
+		if ($this->is404($exception, $request)) {
+			$level = LOG_ERR;
+			$message = $this->getMessage($exception);
+			if ($request !== null) {
+				$message .= $this->getRequestContext($request);
+			}
+
+			Log::write($level, $message, ['404']);
+
+			return;
+		}
+
+		parent::logException($exception, $request);
+	}
+
+	/**
+	 * Generate the message for the exception
+	 *
+	 * @param \Throwable $exception The exception to log a message for.
+	 * @param bool $isPrevious False for original exception, true for previous
+	 * @param bool $includeTrace Whether to include a stack trace.
+	 * @return string Error message
+	 */
+	protected function getMessage(Throwable $exception, bool $isPrevious = false, bool $includeTrace = false): string {
+		$message = sprintf(
+			'%s[%s] %s in %s on line %s',
+			$isPrevious ? "\nCaused by: " : '',
+			$exception::class,
+			$exception->getMessage(),
+			$exception->getFile(),
+			$exception->getLine(),
+		);
+
+		$debug = Configure::read('debug');
+		if ($debug && $exception instanceof CakeException) {
+			$attributes = $exception->getAttributes();
+			if ($attributes) {
+				$message .= "\nException Attributes: " . var_export($exception->getAttributes(), true);
+			}
+		}
+
+		if ($includeTrace) {
+			$trace = Debugger::formatTrace($exception, ['format' => 'points']);
+			assert(is_array($trace));
+			$message .= "\nStack Trace:\n";
+			foreach ($trace as $line) {
+				if (is_string($line)) {
+					$message .= '- ' . $line;
+				} else {
+					$message .= "- {$line['file']}:{$line['line']}\n";
+				}
+			}
+		}
+
+		$previous = $exception->getPrevious();
+		if ($previous) {
+			$message .= $this->getMessage($previous, true, $includeTrace);
+		}
+
+		return $message;
+	}
+
+	/**
+	 * Get the request context for an error/exception trace.
+	 *
+	 * @param \Psr\Http\Message\ServerRequestInterface $request The request to read from.
+	 * @return string
+	 */
+	protected function getRequestContext(ServerRequestInterface $request): string {
+		$message = "\nRequest URL: " . $request->getRequestTarget();
+
+		$referer = $request->getHeaderLine('Referer');
+		if ($referer) {
+			$message .= "\nReferer URL: " . $referer;
+		}
+
+		if ($request instanceof ServerRequest) {
+			$clientIp = $request->clientIp();
+			if ($clientIp && $clientIp !== '::1') {
+				$message .= "\nClient IP: " . $clientIp;
+			}
+		}
+
+		return $message;
+	}
+
 }

+ 2 - 4
src/Utility/Language.php

@@ -18,8 +18,7 @@ class Language {
 	 *
 	 * @return array
 	 */
-	public static function parseLanguageList(string $languageList = null, array $options = []): array
-	{
+	public static function parseLanguageList(?string $languageList = null, array $options = []): array {
 		$defaultOptions = [
 			'forceLowerCase' => true,
 		];
@@ -115,8 +114,7 @@ class Language {
 	 * @param array $available
 	 * @return array
 	 */
-	public static function findMatches(array $accepted, array $available = []): array
-	{
+	public static function findMatches(array $accepted, array $available = []): array {
 		$matches = [];
 		if (!$available) {
 			$available = static::parseLanguageList();

+ 7 - 13
src/Utility/Number.php

@@ -50,8 +50,7 @@ class Number extends CakeNumber {
 	 *
 	 * @return string
 	 */
-	public static function money($value, array $formatOptions = []): string
-	{
+	public static function money($value, array $formatOptions = []): string {
 		return static::currency($value, null, $formatOptions);
 	}
 
@@ -143,7 +142,7 @@ class Number extends CakeNumber {
 	 *
 	 * - signed: true/false
 	 *
-	 * @param string|int|float $value
+	 * @param string|float|int $value
 	 * @param string|null $currency
 	 * @param array<string, mixed> $options
 	 *
@@ -170,8 +169,7 @@ class Number extends CakeNumber {
 	 *
 	 * @return float Average
 	 */
-	public static function average(array $values, int $precision = 0): float
-	{
+	public static function average(array $values, int $precision = 0): float {
 		if (!$values) {
 			return 0.0;
 		}
@@ -204,8 +202,7 @@ class Number extends CakeNumber {
 	 *
 	 * @return float|int Result
 	 */
-	public static function roundUpTo($number, int $increment = 1)
-	{
+	public static function roundUpTo($number, int $increment = 1) {
 		return ceil($number / $increment) * $increment;
 	}
 
@@ -227,8 +224,7 @@ class Number extends CakeNumber {
 	 * @param float $number
 	 * @return int decimalPlaces
 	 */
-	public static function getDecimalPlaces($number): int
-	{
+	public static function getDecimalPlaces($number): int {
 		$decimalPlaces = 0;
 		while ($number > 1 && $number != 0) {
 			$number /= 10;
@@ -251,8 +247,7 @@ class Number extends CakeNumber {
 	 * @param float $precision
 	 * @return bool
 	 */
-	public static function isFloatEqual($x, $y, $precision = 0.0000001): bool
-	{
+	public static function isFloatEqual($x, $y, $precision = 0.0000001): bool {
 		return ($x + $precision >= $y) && ($x - $precision <= $y);
 	}
 
@@ -263,8 +258,7 @@ class Number extends CakeNumber {
 	 *
 	 * @return array currencySettings
 	 */
-	public static function getFormat(string $formatName): array
-	{
+	public static function getFormat(string $formatName): array {
 		if (!isset(static::$_currencies[$formatName])) {
 			return [];
 		}