What HTTP Components have you created - does a replacement middleware exists?

Our redirecthandler has one too https://github.com/neos/redirecthandler/blob/master/Classes/RedirectComponent.php. But also doesn’t look too complex.

1 Like

Yep, the hardest part is the ComponentParameters replacement, which is yet to be decided, but will likely end up as PSR-7 Request attribute.

Given that, the code will look s.th. like:

    /**
     * Check if the current request match a redirect
     *
     * @param ServerRequestInterface $request
     * @param RequestHandlerInterface $next
     * @return ResponseInterface
     * @throws Exception
     */
    public function process(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface
    {
        $routingMatchResults = $request->getAttribute(RoutingComponent::class . ':matchResults');
        if ($routingMatchResults !== null) {
            return $next->handle($request);
        }
        $response = $this->redirectService->buildResponseIfApplicable($request);
        if ($response !== null) {
            return $response;
        }
        return $next->handle($request);
    }
1 Like

This might really be an interesting use-case to collect feedback on the breakiness and migration edge-cases. Also how to maintain a multi-major compatible package - right now it uses the class_exists() to check for Flow 5 vs 6 - how that could look for components vs middleware is something we need to think through (hopefully before the release).

Maybe the answer is, this needs to be a new major version of the package that only targets middleware (but therefore becomes cross-framework if done carefully).

1 Like

I agree that this is a good solution. Middleware will be the standard, to move closer to PSR and the PHP eco system :star_struck:

I also have a few components running in various projects, most notably one in the OIDC package (https://github.com/flownative/flow-openidconnect-client/blob/master/Classes/Http/SetJwtCookieComponent.php). I assume that it can be refactored to a middleware as well.

What nags me though (as always) is that one (a package maintainer) needs to adjust and maintain so much code due to these breaking changes. It’s always a hassle to maintain two codebases / branches which are incompatible.

So, what’s the motivation – from a user’s point of view – to drop components support? Wouldn’t it be possible to let them live side-by-side? Is it about our components being reusable in other, non-Flow projects? If so, I think that wouldn’t justify such a big break up.

2 Likes

This can be a hassle, if we change a lot of things in the HTTP Component afterwards - but since we deprecated them (the HTTP Component context etc), what support and maintanence do you expect to have for a package versioned 1.0 that uses HTTP components, if 2.0 and beyond is a middleware implementation?

Middleware has been mentioned since 2016, Alexander did the first work about one year ago (from reading issues) . We could have decided to push the topic harder and have had it in for the 6.3 LTS release - but I don’t think any time would have been better than other :slight_smile: We didn’t get it in for 6.3 LTS - so kept the LTS stable with concept known, for a longer support release.

Instead we are pushing this along with many other topic for the major 7.0 release.

To work with a framework following the PSR-* standards - “easier” adoption, due to usage of documented concept, describes in numerous of blog post, written by none-Flow users, but still they can use the concept and values.

Mentioned here RFC: PSR-15 / Replace HTTP Component completely, with Flow 7.0 - #8 by aberl - Alexander did some concept for that, but he mentiones the drawbacks, so it’s out there in the open.

The other way around - it’s about others middleware being usable by Flow. Which then (secondary?) leads to, our middlewares being usable by others :slight_smile:

circle-of-life

The problem is that if we keep support the flow processing chains and use them as three middlewares it would not be possible to place a psr middleware in between those or the other way around. We need a single definition of the processing order and we want to be able to use psr middlewares.

I see no way around the breakiness. Maybe we can provide a wrapper to add flow components as psr middlewares or the other way around but on the long run a clear cut may be the better option.

Okay, I got you. I think I need to develop a middleware myself in order to get a better understanding of what’s possible and where limits are.

I’m sorry that I didn’t do my homework and looked up the discussions and progress already made. I really appreciate all the work and certainly agree with initiatives to make Flow and Neos accessible to more people!

Looking at all the comments in the original PR (https://github.com/neos/flow-development-collection/pull/1928) I think we owe @aberl some feedback. I’m not sure if @bwaidelich had a chance to talk / write to Alex already?

Since the PR is merged I have the following question: As far as I understood the discussion, the component chain and middleware support can’t live side-by-side. Doesn’t that mean that PR 1928 is a breaking change (and should be declared as one)?

If I’m to experiment with my own middleware plugin, do I need anything else than Flow master?

Not side by side, but one after the other is perfectly fine and not breaking anything. That is also the current status as of Flow 6.3, where the middleware chain “wraps” our old component chain. So you can already write middlewares, configure them and play around with them, as long as they don’t need to run between components.

See above, even 6.3 works already to experiment :slight_smile: In master we will only remove the existing components, so you can no longer order your own components relative to existing flow components (once we are through) and that is in fact the breaking part of the change.

We could indeed keep the “ComponentChainMiddleware” that runs as the innermost middleware, so existing components could in some way still function. But that begs the question what the reason would be, when components can no longer “interact” with (wrap/interrupt) the Frameworks own http kernel layers.

I’m not sure if @bwaidelich had a chance to talk / write to Alex already?

I did have a talk with Bastian a couple weeks ago regarding the middleware change for 7.0 and he too was on the side of keeping b/c as much as possible. Since then I just found this harder to achieve than anticipated. See also my post in the other thread that @sorenmalling already mentioned RFC: PSR-15 / Replace HTTP Component completely, with Flow 7.0
I would love to have existing components simply work as a middleware without having to touch code, but right now I can’t seem to find a solution that works for all cases.
But nothing is decided yet. The current open issue for the final switch to middlewares is Convert existing HTTP Components to PSR-15 middleware · Issue #2019 · neos/flow-development-collection · GitHub

FYI: The move is going forward now with the few remaining components being replaced with middlewares hopefully right before feature freeze at the end of the week. So far it is working out pretty well, but we will need help with testing the master branch in projects after that. Especially from package maintainers. So please try to allocate a little bit of time for that in between next week and the release.

FYI: That will actually end up as
$routingMatchResults = $request->getAttribute(ServerRequestAttributes::ROUTING_RESULTS);

Also NOTE: if anyone used the ComponentParameters for passing data from a component to an “outgoing” (~postprocess, more correctly anything after “dispatch”) component, that will no longer be possible (easily). The reason is that with middlewares we can only attach metadata to the request object via attributes and pass that on, but once a middleware returns a response, the reference to the most current request is not passed on any more.
Aside from this being a strange use-case anyway (which funnily enough we did do in Flow core, but that’s taken care of), there is still a way to do this though with abusing e.g. the response headers, or introducing your own global context. But really, try to avoid this.

See Convert existing HTTP Components to PSR-15 middleware · Issue #2019 · neos/flow-development-collection · GitHub

Update everyone: All the Flow core components have been migrated to middlewares in current master as of now. The ComponentChain is still in (but disfunctional) and will be removed soon with https://github.com/neos/flow-development-collection/pull/2221 unless voices are raised against this.
So please everyone, play around with your packages on master and let us know what we can do to mitigate your pain of this breaking change.

Most likely, you will need to create a new major version of your package that targets Flow 7.0+ though. Yes, we know this will be a hassle to maintain, especially if the code inside your component is supposed to change.
So as a rule-of-thumb maybe: try to reduce the code inside the component/middleware and move the core logic into some service.

2 Likes

Thanks! That works really well and makes the code not only maintainable across two branches but also more readable. I totally like this change.

1 Like

Just had another great chat with @bwaidelich and he came up with the idea to keep just the ComponentInterface (marked as deprecated), which would allow existing Components to still pass the compile step. That way, a package could provide both a Component and Middleware version (+according config settings) of it’s functionality, and the enduser decides which is used by just installing either Flow < 7 or Flow 7+. This would avoid having to create a new major version of your package that is only compatible with Flow 7+.

cc @robert

Don’t we just push solving of the actual issue another version for the package creator? It will have to be done, no matter what. Do we really help by doing this, or pushing the legacy further?

We provide an option for package maintainers that costs us nothing and doesn’t force them to maintain two versions.

It “costs us” to keep a deprecated and removed concept in the codebase. Relatively speaking, we move the “cost” on to the core?

How big of an issue is this really?

It’s really just a single interface laying around. Nothing more.

It’s a deprecated concept that is being kept alive :slight_smile: It’s even marked as deprecated since 6.0 (IIRC)

I will not block it, but do not see it add value either