Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added error listeners to RequestHandlerRunner #2

Closed
weierophinney opened this issue Dec 31, 2019 · 9 comments
Closed

Added error listeners to RequestHandlerRunner #2

weierophinney opened this issue Dec 31, 2019 · 9 comments

Comments

@weierophinney
Copy link
Member

Added error listeners to RequestHandlerRunner to be able to log errors/exceptions thrown in ::run() method.
Also made emitMarshalServerRequestException public to it can be called from the outside-


Originally posted by @maurice2k at zendframework/zend-httphandlerrunner#5

@weierophinney
Copy link
Member Author

The only issue I see with this is that you would not be able to use the same listeners here as you do with the zend-stratigility ErrorHandler, as that class triggers listeners using the following signature:

function (Throwable $error, ServerRequestInterface $requst, ResponseInterface $response)

If we were to do this, we'd need to find a way to either document re-use of listeners, or provide a way to curry listeners to work properly (e.g., providing an empty request instance).


Originally posted by @weierophinney at zendframework/zend-httphandlerrunner#5 (comment)

@weierophinney
Copy link
Member Author

Unfortunately yes as the request object is not available. But still offers a chance to get the issue logged somewhere, maybe together with $_REQUEST.


Originally posted by @maurice2k at zendframework/zend-httphandlerrunner#5 (comment)

@weierophinney
Copy link
Member Author

Empty request would also be a possibility...

YES, really like the idea. One could create a class implementing ServerRequestInterface which just pipes thru the $_SERVER, $_FILES etc variables. Without triggering any exceptions.


Originally posted by @maurice2k at zendframework/zend-httphandlerrunner#5 (comment)

@weierophinney
Copy link
Member Author

$_REQUEST is not available in all SAPI environments; it's also unreliable, as the order in which the various sources are provided is based on php.ini settings. $_SERVER, $_FILES, etc. may or may not be populated depending on the SAPI as well (e.g. async frameworks). I think an empty request makes more sense here, potentially even supplying an empty implementation as part of the package.

The other point remains: we'd need a way of currying arguments for existing listeners. It'd likely look something like this:

class ErrorHandlerListenerAdapter
{
    /** @var callable */
    private $listener;

    /** @param ServerRequestInterface */
    private $request;

    public function __construct(callable $listener, ServerRequestInterface $request = null)
    {
        $this->listener = $listener;
        $this->request = $request ?: new EmptyServerRequest();
    }

    public function __invoke(Throwable $e, ResponseInterface $response) : void
    {
        ($this->listener)($e, $this->request, $response);
    }
}

function adaptErrorHandlerListener(callable $listener, ServerRequestInterface $request = null) : ErrorHandlerListenerAdapter
{
    return new ErrorHandlerListenerAdapter($listener, $request);
}

I'm not sure if that should belong here, or in the zend-expressive package, however.


Originally posted by @weierophinney at zendframework/zend-httphandlerrunner#5 (comment)

@weierophinney
Copy link
Member Author

Not at my PC right now. Yes @ $_REQUEST.

But why not just call the listeners in triggerListeners with the second arguments being the new EmptyServerRequest()?

Why an ...Adapter?


Originally posted by @maurice2k at zendframework/zend-httphandlerrunner#5 (comment)

@weierophinney
Copy link
Member Author

By currying, we can use existing listeners, and call them using the empty request instance only in this particular context; in other contexts, they get the populated request instance. That's the sole purpose of the approach I outline above.


Originally posted by @weierophinney at zendframework/zend-httphandlerrunner#5 (comment)

@weierophinney
Copy link
Member Author

Now I got it; was hard to read on mobile.
I thought I'd just make the listener callback compatible (which I think is easier/requires less code). On the other hand, if you're only using listeners for RequestHandlerRunner you would always have an empty request as the second parameter.
Up to you...

Another idea is to not use an EmptyServerRequest but some kind of Raw/UnitializedServerRequest which returns $_SERVER, $_FILES etc so that just have some bare minimum Request. Not sure if this is a good idea.


Originally posted by @maurice2k at zendframework/zend-httphandlerrunner#5 (comment)

@weierophinney
Copy link
Member Author

@maurice2k I'd like to bring this functionality in, but need:

  • A class representing the empty server request. This would implement ServerRequestInterface, but provide no-ops and/or default values for all methods.
  • A mechanism for providing listeners to the instance (likely via a constructor argument).
  • Unit tests.
  • Documentation of how to use the feature.

If you cannot provide those, close the issue, and indicate somebody else should pick it up.

Thanks!


Originally posted by @weierophinney at zendframework/zend-httphandlerrunner#5 (comment)

@boesing
Copy link
Member

boesing commented Jul 8, 2021

I'm closing this. I'll create a new interface RequestHandlerRunnerInterface with the run method.
This will land in 2.0.0 and will be used by mezzio/mezzio starting with v4.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants