Question: does anyone (know how to) do reversible ...
# http4k
c
Question: does anyone (know how to) do reversible routes (routes that can also be used to build links from) in http4k? I found [Krouton](https://github.com/npryce/krouton), bit old, unmaintained, but certainly interesting. But that was about it. Just in case "reverse routing" is not understood (it's a bit of a lesser know concept, sometimes called "type-safe link building from routes"), some examples in other frameworks: KTor (explained here: https://ktor.io/docs/server-resources.html#resource_links) and Revel (explained here: https://revel.github.io/manual/routing.html#reverse_routing).
👀 1
d
we don't have anything "featured", but you could do something with the typesafe http4k lens system trivially easily:
Copy code
fun Uri.with(vararg inject: (Request) -> Request): Uri = Request(GET, this).with(*inject).uri
then...
Copy code
fun main() {
    val time = Path.localDate().of("time")
    val id = Path.uuid().of("id")
    val sort = Query.boolean().required("sort")
    val url =  Uri.of("/{id}/{time}").with(time of LocalDate.now(), id of UUID.randomUUID(), sort of true)
    println(url)
}
yields:
Copy code
/dfcbf834-d739-4140-8f03-be365e7fdea8/2025-05-20?sort=true
With a little more finagling, you could possibly apply this to a RoutedHttpHandler, but I haven't checked
I'm not really one for boasting, but that really was quite cool, no? I really ❤️ K*+*http4k!
😁 2
💯 1
c
Nice one, indeed! Definitely a solid case of ❤️ K*+*http4k! I may not be understanding your solution completely, but I'm looking for a way to create a link (url) from a route by a handle. The handle could be the KFunction of the handler (controller) function that the route is bound to, or a new handle (see the KTor example). This way there's some level of type-safety (and thus certainty when refactoring) wrt the internal links within the application. As I see it, currently in the KTor router there are no "handles" of routes: I cannot refer to them in a concise and type-safe way. So it's more about the link/url building. For example there's a route that points to
auth::signInHandler
and the Router is "aware" of that. Then building a url for that should be:
Copy code
val fullUrl = Router.fullUrlFor(request, books::findByIsbnHandler).with(isbn of "123123") // => "<https://b.co/books/by-isbn/123123>"
val relativeUrl = Router.urlFor(books::findByIsbnHandler).with(isbn of "123123", showSimilar = true) // => "<https://b.co/books/by-isbn/123123?showSimilar=true>"
For a route that's defined as
"/books/by-isbn/{isbn}"
. Now if I were to change the route definition to
"/books/find-by-isbn/{isbn}"
all would still work. The KTor implementation goes as far to even make the parameters part of the type, so I can change
isbn
to
isbnCode
with the rename refactor tool and all should still work.
n
I wrote Krouton when working with Kotlin + Undertow (and later Jetty), before Http4k was invented.
I think it could be made to work with Http4k but I have not maintained it for many years.
c
Hi Nat! Thanks for open sourcing. 🙂 I've just forked and updated it's deps + README and made some modifications in order to see what it can do for me. https://github.com/cies/krouton It's a very nice lib, and I think it can add serious value to the http4k ecosystem for those making traditional SSR web apps.
m
sort of cool
!