Skip to content

Commit 51568de

Browse files
authored
#19 Fix (#20)
1 parent 7cd5089 commit 51568de

File tree

3 files changed

+151
-12
lines changed

3 files changed

+151
-12
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/)
55
and this project adheres to [Semantic Versioning](http://semver.org/).
66

7+
## [2.1.1] - 2025-04-27
8+
### Fixed
9+
- Fix for `shouldUpdateResponse returns only true with one handler` [#19]
10+
711
## [2.1.0] - 2025-04-22
812
### Fixed
913
- Fix for Whoop's PlainHandler `loggerOnly()` mode [#17].
@@ -97,7 +101,9 @@ First version
97101
[#7]: https://github.com/middlewares/whoops/issues/7
98102
[#11]: https://github.com/middlewares/whoops/issues/11
99103
[#17]: https://github.com/middlewares/whoops/issues/17
104+
[#19]: https://github.com/middlewares/whoops/issues/19
100105

106+
[2.1.1]: https://github.com/middlewares/whoops/compare/v2.1.0...v2.1.1
101107
[2.1.0]: https://github.com/middlewares/whoops/compare/v2.0.4...v2.1.0
102108
[2.0.4]: https://github.com/middlewares/whoops/compare/v2.0.3...v2.0.4
103109
[2.0.3]: https://github.com/middlewares/whoops/compare/v2.0.2...v2.0.3

src/Whoops.php

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -136,25 +136,31 @@ protected function createWhoopsInstance(ServerRequestInterface $request): Run
136136

137137
private static function shouldUpdateResponse(Run $whoops): bool
138138
{
139-
if (1 !== count($whoops->getHandlers())) {
139+
$handlers = $whoops->getHandlers();
140+
141+
$plainTextWithLoggerOnly = array_filter($handlers, function ($handler) {
142+
return $handler instanceof PlainTextHandler && $handler->loggerOnly();
143+
});
144+
145+
if ($plainTextWithLoggerOnly && count($plainTextWithLoggerOnly) === count($handlers)) {
140146
return false;
141147
}
142148

143-
$handler = current($whoops->getHandlers());
144-
145-
return !($handler instanceof PlainTextHandler && $handler->loggerOnly());
149+
return true;
146150
}
147151

148152
/**
149153
* Updates Response's content type to match Handler's content type.
150154
*/
151155
private static function updateResponseContentType(ResponseInterface $response, Run $whoops): ResponseInterface
152156
{
153-
if (1 !== count($whoops->getHandlers())) {
154-
return $response;
155-
}
157+
$handlers = $whoops->getHandlers();
158+
159+
$handlersWithOutput = array_filter($handlers, function ($handler) {
160+
return !($handler instanceof PlainTextHandler && $handler->loggerOnly());
161+
});
156162

157-
$handler = current($whoops->getHandlers());
163+
$handler = current($handlersWithOutput);
158164

159165
if (method_exists($handler, 'contentType')) {
160166
return $response->withHeader('Content-Type', $handler->contentType());

tests/WhoopsTest.php

Lines changed: 131 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
use Psr\Http\Message\ResponseFactoryInterface;
1212
use Psr\Http\Message\ResponseInterface;
1313
use Psr\Log\NullLogger;
14+
use Whoops\Handler\JsonResponseHandler;
1415
use Whoops\Handler\PlainTextHandler;
16+
use Whoops\Handler\PrettyPageHandler;
1517
use Whoops\Run;
1618

1719
class WhoopsTest extends TestCase
@@ -47,6 +49,33 @@ function () {
4749
$this->assertNotFalse(strpos((string) $response->getBody(), 'Undefined variable'));
4850
}
4951

52+
public function testStandardErrorWithPrettyPageHandler(): void
53+
{
54+
error_reporting(E_ALL);
55+
56+
$whoops = new Run();
57+
$whoops->writeToOutput(false);
58+
$whoops->allowQuit(false);
59+
$whoops->sendHttpCode(false);
60+
61+
$prettyPage = new PrettyPageHandler();
62+
$whoops->pushHandler($prettyPage);
63+
64+
$whoops->register();
65+
66+
$response = Dispatcher::run([
67+
new Whoops($whoops),
68+
function () {
69+
throw new Exception('Error Processing Request');
70+
},
71+
]);
72+
73+
$this->assertEquals(500, $response->getStatusCode());
74+
$this->assertEquals('text/html', $response->getHeaderLine('Content-Type'));
75+
// Whoops doesn't output anything on CLI
76+
$this->assertEquals('', (string) $response->getBody());
77+
}
78+
5079
public function testPlainHandlerWithLoggerOnlyDisableChangesResponseBody(): void
5180
{
5281
$whoops = new Run();
@@ -70,8 +99,8 @@ function () {
7099

71100
$this->assertEquals(500, $response->getStatusCode());
72101
$this->assertEquals('text/plain', $response->getHeaderLine('Content-Type'));
73-
$this->assertStringContainsString('Stack trace:', (string)$response->getBody());
74-
$this->assertStringContainsString('Exception: Error Processing Request in file', (string)$response->getBody());
102+
$this->assertStringContainsString('Stack trace:', (string) $response->getBody());
103+
$this->assertStringContainsString('Exception: Error Processing Request in file', (string) $response->getBody());
75104
}
76105

77106
public function testPlainHandlerWithLoggerOnlyLeavesResponseUntouched(): void
@@ -97,7 +126,7 @@ function () {
97126

98127
$this->assertEquals(500, $response->getStatusCode());
99128
$this->assertEquals('', $response->getHeaderLine('Content-Type'));
100-
$this->assertEquals('', (string)$response->getBody());
129+
$this->assertEquals('', (string) $response->getBody());
101130
}
102131

103132
public function testPlainHandlerWithLoggerOnlyAndPrettyResponseFactoryShowsPrettyResponse(): void
@@ -130,7 +159,105 @@ function () {
130159

131160
$this->assertEquals(500, $response->getStatusCode());
132161
$this->assertEquals('text/html; charset=utf-8', $response->getHeaderLine('Content-Type'));
133-
$this->assertEquals('<strong>Sorry! Come back later</strong>', (string)$response->getBody());
162+
$this->assertEquals('<strong>Sorry! Come back later</strong>', (string) $response->getBody());
163+
}
164+
165+
public function testWithLoggerOnlyAndPrettyHandlerTakesThePrettyHandler(): void
166+
{
167+
$whoops = new Run();
168+
$whoops->writeToOutput(false);
169+
$whoops->allowQuit(false);
170+
$whoops->sendHttpCode(false);
171+
172+
// logger only
173+
$text = new PlainTextHandler(new NullLogger());
174+
$text->loggerOnly(true);
175+
$whoops->pushHandler($text);
176+
177+
$prettyPage = new PrettyPageHandler();
178+
$whoops->pushHandler($prettyPage);
179+
180+
$whoops->register();
181+
182+
$response = Dispatcher::run([
183+
new Whoops($whoops),
184+
function () {
185+
throw new Exception('Error Processing Request');
186+
},
187+
]);
188+
189+
$this->assertEquals(500, $response->getStatusCode());
190+
$this->assertEquals('text/html', $response->getHeaderLine('Content-Type'));
191+
// for some reason PrettyPageHandler doesn't output anything in CLI
192+
$this->assertEquals('', (string) $response->getBody());
193+
}
194+
195+
public function testWithLoggerOnlyItTakesTheFirstHandlerWithOutput(): void
196+
{
197+
$whoops = new Run();
198+
$whoops->writeToOutput(false);
199+
$whoops->allowQuit(false);
200+
$whoops->sendHttpCode(false);
201+
202+
// without output, ignored
203+
$text = new PlainTextHandler(new NullLogger());
204+
$text->loggerOnly(true);
205+
$whoops->pushHandler($text);
206+
207+
// with output, taken first
208+
$text = new JsonResponseHandler();
209+
$whoops->pushHandler($text);
210+
211+
// ignored
212+
$prettyPage = new PrettyPageHandler();
213+
$whoops->pushHandler($prettyPage);
214+
215+
$whoops->register();
216+
217+
$response = Dispatcher::run([
218+
new Whoops($whoops),
219+
function () {
220+
throw new Exception('Error Processing Request');
221+
},
222+
]);
223+
224+
$this->assertEquals(500, $response->getStatusCode());
225+
$this->assertEquals('application/json', $response->getHeaderLine('Content-Type'));
226+
$this->assertStringStartsWith('{"error":{"type":"Exception"', (string) $response->getBody());
227+
}
228+
229+
public function testItTakesTheFirstHandlerWithOutputWhenBothHaveOutput(): void
230+
{
231+
$whoops = new Run();
232+
$whoops->writeToOutput(false);
233+
$whoops->allowQuit(false);
234+
$whoops->sendHttpCode(false);
235+
236+
// first handler with output
237+
$prettyPage = new PrettyPageHandler();
238+
$whoops->pushHandler($prettyPage);
239+
240+
// never reaches this one
241+
$text = new PlainTextHandler(new NullLogger());
242+
$text->loggerOnly(false);
243+
$whoops->pushHandler($text);
244+
245+
$whoops->register();
246+
247+
$response = Dispatcher::run([
248+
new Whoops($whoops),
249+
function () {
250+
throw new Exception('Error Processing Request');
251+
},
252+
]);
253+
254+
$this->assertEquals(500, $response->getStatusCode());
255+
// the content type of pretty page handler is used
256+
$this->assertEquals('text/html', $response->getHeaderLine('Content-Type'));
257+
// the output of the plain text handler is used
258+
$this->assertStringStartsWith('Exception: Error Processing Request', (string) $response->getBody());
259+
260+
// ... its interesting how Whoops works internally
134261
}
135262

136263
public function testWithoutError(): void

0 commit comments

Comments
 (0)