itsgoingd / clockwork

Clockwork - php dev tools in your browser - server-side component
https://underground.works/clockwork
MIT License
5.69k stars 321 forks source link

Vanilla - added generic PSR-compatible middleware #689

Closed itsgoingd closed 8 months ago

itsgoingd commented 8 months ago

Example use in a Slim application:

use Clockwork\Support\Vanilla\ClockworkMiddleware;
$app->add(ClockworkMiddleware::init()->withResponseFactory($app->getResponseFactory()));

// Run App & Emit Response
$response = $app->handle($request);

With the php-http/discovery package installed, the response factory will be auto-detected (if one is installed), making the initialization as simple as:

use Clockwork\Support\Vanilla\ClockworkMiddleware;
$app->add(ClockworkMiddleware::init());

You can also instantiate the middleware with a custom Clockwork instance (useful if you want to register the instance with a DI container for example) and disable routing if you want to set it up on your own:

use Clockwork\Support\Vanilla\Clockwork;
use Clockwork\Support\Vanilla\ClockworkMiddleware;
$clockwork = new Clockwork([ ... ]);
$app->add((new ClockworkMiddleware($clockwork))->withoutRouting());

$app->get('/__clockwork/{request:.+}', function ($request, $response) use ($clockwork) {
    return $clockwork->usePsrMessage($request, $response)->handleMetadata();
});

Note, because the Slim skeleton project registers the routing middleware as the last (outermost) middleware, you will need to add Clockwork middleware in public/index.php just before the $app->handle() call, instead of app/middleware.php.

itsgoingd commented 8 months ago

@UlrichEckhardt @DominicDetta Please check this PR out and let me know what you think about my take on this feature.

itsgoingd commented 8 months ago

Thanks for the review, everything should be fixed now.

itsgoingd commented 8 months ago

An example Slim project is now also available here - https://github.com/underground-works/clockwork-examples/tree/master/Integrations/Slim#readme

UlrichEckhardt commented 8 months ago

Good morning!

I've been toying around with this a bit and found a few more issues:

That said, I personally find the implementation increasingly hard to follow. In particular the duality with the implementation switching between PSR and globals is making this difficult. Maybe making this a configuration flag which is set in the constructor would help a bit, splitting it into separate classes would be my preferred choice though, but that's a major change. One aspect of this is also that the core Clockwork class is volatile with respect to function parameters and return types. For example, Clockwork::response() either creates and returns a PSR response or it sends the response. So, depending on the use, it either returns something or causes a side effect, which is confusing for humans and also impossible to explain to a static analyzer (PHPStan, Psalm etc).

Just to prevent misunderstandings, I think this adds value and that it doesn't cause any regressions, so I'd be favorable to merging it, despite previous criticisms!

Uli

UlrichEckhardt commented 8 months ago

Just updated my demo repository:

The reason I'm mentioning this is that both of these have PHPUnit tests included, which check whether the demo API, the Clockwork API and the Clockwork web UI works. The tests there differ also a bit because of my uncertainty about where the web UI is supposed to be located URL-wise.

Cheers! :)

itsgoingd commented 8 months ago

Thanks for the feedback! Yes, I assume in the examples, that the enable behavior is already changed. That will be done in a separate PR though.

Oops, the default setting for the web UI assets public path was one level off, so they were not actually copied to the public dir as they were supposed to. This should be resolved in the latest commit.

So let me try to explain how the paths work (and good thing you've mentioned this, because I've realised we are missing a bit of the implementation here):

I kind of agree the Vanilla helper class is starting to get a little bit complicated and might be a good candidate for a rework at some point. I'm currently assuming a 5.x release for this feature, so I didn't want to do any big changes at this time.

I especially don't like that part, where the response factory gets randomly passed as a third argument to the usePsrMessage() method. I might still move that part to the middleware and pass in an empty response ready to be used.

UlrichEckhardt commented 8 months ago

Heya!

Let's merge this, and then make it better. It definitely adds value already, so there is no point in holding it back.

Concerning the things to improve, the web UI isn't working out of the box for me yet. Key to this is actually documented: "Path where to install the Web UI assets, should be publicly accessible". For me, this is not the case since I route every request through my Slim stack. Yes, for e.g. Nginx, you can tell it to just serve the file if it exists and is not a *.php and that should be the default if you care for performance. However, it doesn't have to be the case and since I don't serve a website (with some static content) but an API, I'm not be prepared for serving of static files.

Let's get this moving!

Uli

UlrichEckhardt commented 8 months ago

That last changes looks fine, too. Let's merge this!