--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+unsubscribe@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/php-fig/AD782EAE-00D2-4D01-BFE9-476427080DEB%40gmail.com.
For more options, visit https://groups.google.com/d/optout.
Anyone else from PSR-15 (proposed) WG have comments?
--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/php-fig/235bad6d-dca0-46af-b66e-b9f0d5a2f5d2%40googlegroups.com.
This approach has some limitations:- There’s no (standard) way to decide whether the exception produces a 500 code, 404, 405, etc… This decision is made by the error handler.- There’s no way to get context data for loggin purposes.
interface XResponseInterface extends ResponseInterface
{
public function getAttributes();
public function getAttribute($name, $default = null);
public function withAttribute($name, $value);
public function withoutAttribute($name);
}
class ErrorHandler implements MiddlewareInterface
{
public function process(ServerRequestInterface $request, DelegateInterface $delegate)
{
try {
$response = $delegate->process($request);
} catch (Exception $exception) {
// Generic error 500
$response = $this
->factory
->createResponse(500)
->withAttribute(Exception::class, $exception);
$response->getBody()->write('Server error');
}
if ($exception = $response->getAttribute(Exception::class)) {
// Logs exceptions of inner middlewares too!
$this->logger->error('Exception', ['exception' => $exception]);
}
return $response;
}
}
class SendFileMiddleware implements MiddlewareInterface
{
public function process(ServerRequestInterface $request, DelegateInterface $delegate = null)
{
// …
if (!file_exists($path)) {
return $this
->factory
->createResponse(404)
->withAttribute(Exception::class, new Exception("The file \"$path\" does not exist."))
->…;
}
// …
}
}
try {
$gget = new GuzzleGet(['base_uri' => 'https://httpbin.org']);
$response = $gget(new Request('GET', '/'));
$response->getStatusCode(); // may return 500!
} catch (HttpErrorException $exception) {
// a network failure or anything else prevented the request from completing
$exception->getResponse(); // may return null!
}
I initially liked this idea, but on a second thought I think this could cause some major design issues.
First and foremost, http errors are not exactly exceptional. Every web application produces negative responses, they're part of their normal life cycle, so it could be said that this interface encourages using an exception to control some flow that is actually part of how the application is expected to work.
Secondarily, middlewares don't need another interface to model the errors they produce, they can already use the responses, which have more than enough to provide context to the outer layers: code, reason phrase and body.
Since one of the points of a middleware collection is to decouple the stages of the request processing from each other, I think that offloading this logic to a specific middleware with such a specific mechanic is an implementation detail.
Now, many could have no problem with it per se, but I don't think standardising it would be wise.
For example, the double catch block could completely avoided:
class ErrorHandler implements MiddlewareInterface{public function process(ServerRequestInterface $request, DelegateInterface $delegate){try {$response = $delegate->process($request);} catch (Exception $e) {//Generic error 500$response = $this->factory->createResponse(500);$this->logger->error('Unexpected error', compact($request, $response, $e));return $response;
}
if ($this->debug and is_error($response)) {$this->logger->debug('Http Error', compact($request, $response));}
return $response;}}
This way the error handler would be catching only truly unexpected errors, the traditional 500s that make us freak out.
You certainly don't throw exceptions for 404s, do you? ;-)