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

SinglePageAppRoutingHandler applies filters to rewritten requests #851

Open
adamschoenemann opened this issue Jan 26, 2023 · 1 comment
Open

Comments

@adamschoenemann
Copy link

Hi http4k! First of all, thanks for the great library.

I noticed that when applying filters to SinglePageAppRoutingHandler, the filters are in practice applied to inner static routing handler.
That means that during the SPA's rewrite of certain requests to its root (typically "/public"), the filters are applied with that URI and not the original URI that was requested.
This may or may not be what you expect as a user of http4k.
In our use case, it's a problem, because it makes it impossible/hard to redirect the user based on their original request.
I understand that there may be other use cases where the current behavior might be more appropriate (although none springs to mind right now).

In any case, the behavior is easily tweaked, by maintaining the filter in SinglePageAppRoutingHandler, as opposed to inside the staticHandler, as such:

data class SinglePageAppRoutingHandler(
    private val pathSegments: String,
    private val staticHandler: RoutingHttpHandler,
    private val filter: Filter = Filter.NoOp, // <-- new
) : RoutingHttpHandler {
    private val handlerWithoutFilter = { request: Request ->
        val matchOnStatic = when (val matchResult = staticHandler.match(request)) {
            is RouterMatch.MatchingHandler -> matchResult(request)
            else -> null
        }

        val matchOnIndex = when (val matchResult = staticHandler.match(get(pathSegments))) {
            is RouterMatch.MatchingHandler -> matchResult
            else -> null
        }

        val fallbackHandler = matchOnIndex ?: { Response(NOT_FOUND) }
        matchOnStatic ?: fallbackHandler(get(pathSegments))
    }
    private val handlerWithFilter = filter.then(handlerWithoutFilter)

    override fun invoke(request: Request): Response = handlerWithFilter(request)

    override fun match(request: Request) = when (request.method) {
        Method.OPTIONS -> RouterMatch.MethodNotMatched(RouterDescription("template == '$pathSegments'"))
        else -> RouterMatch.MatchingHandler(handlerWithFilter, description)
    }

    override fun withFilter(new: Filter) = copy(filter = new.then(filter))

    override fun withBasePath(new: String) =
        copy(pathSegments = new + pathSegments, staticHandler = staticHandler.withBasePath(new))
}

@s4nchez
Copy link
Collaborator

s4nchez commented Jan 26, 2023

Hey @adamschoenemann, thank you for reporting this.

At first glance, this looks like a relatively common issue of when filters are applied (pre vs post routing). To be sure though, are you able to put together a minimal failing test case demonstrating the behaviour you'd like to see? If you're confident about how to design a fix, feel free to put those in a PR and we'd be happy to review it.

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