https://kotlinlang.org logo
Join Slack
Powered by
# http4k
  • d

    dave

    06/18/2025, 12:27 PM
    👋 Happy Wednesday to all you http4k fans! We've got some news about what we've been cooking up at http4k towers... https://http4k.org/news/ai_without_tests_is_just_expensive_random_number_generation/
    http4k 2
  • d

    dave

    06/20/2025, 9:10 PM
    For those of you that didn't catch the livestream at KotlinConf, @s4nchez's great talk about http4k's support fo Streaming Protocols (and a history of the web browser) is now available:

    https://www.youtube.com/watch?v=vewgb-vyJMEâ–¾

    (as a bonus: @dmcg and @Dmitry Kandalov’s refactoring talk is also amazing 🙂

    https://www.youtube.com/watch?v=SwNTpgp262oâ–¾

    )
    http4k 4
    K 3
    d
    • 2
    • 1
  • l

    leonhardt

    06/30/2025, 4:02 AM
    Can the
    singlePageApp
    helper be used on a subpath? When it's configured on the root path, it works as expected. But when it's configured on a subpath, it still seems to match any path, even ones outside the subpath.
    d
    s
    • 3
    • 9
  • m

    Marco Garofalo

    06/30/2025, 3:42 PM
    Hi, I am trying to understand whether the oauth module does provide a way to fetch the authenticated user information somehow (e.g.
    <http://whatever/me>
    ) or propagate the token down the handlers chain/stack once the authFilter is satisfied.
    s
    • 2
    • 2
  • l

    leonhardt

    07/12/2025, 5:38 PM
    Hey @s4nchez! Thanks to its mention on the approval testing docs page my team has been using
    org.http4k:http4k-testing-approval
    in conjunction with your Okey-doke plugin for a couple months now. The tool + plugin has definitely a huge improvement over renaming the generated files manually, but now that we've been living with the process for a while a few DX issues have surfaced: 1. It's hard to know if the keyboard shortcut (Ctrl + F11) worked. You have to have the cursor focused in the right place. Precise placement in the editor on the test or in the project viewer on the file both work, but (perhaps unintuitively) the test execution's run window/console does not work. And there's no visual indication if it worked, beyond navigating to the file in the project viewer. As a result I've noticed we just hit Ctrl + F11 obsessively in every window "just to make sure." 2. When we rename tests, the generated approval files get abandoned. We often don't notice initially, and only after some time notice when there's many more approval files than tests. The process to clean up the clutter is tricky. We usually make sure all our tests are passing, commit, delete all the approval files, rerun tests, approve all the approval files, and commit again. But this is a little error-prone and tedious. When we only had 1-20 tests, these weren't big issues. But now that we're in the 100s it's painful enough issue we're looking to address it. Thought we'd check with the community here. Can anybody recommend any better ways to work with
    org.http4k:http4k-testing-approval
    that we might have missed?
    d
    s
    • 3
    • 6
  • t

    ted

    07/28/2025, 11:29 AM
    Hello, planning to fetch items from dynamodb using http4k-connect. I’m wondering if there will be an issue if we fetch too many items e.g. is there a maximum chunk size? Will also have a look at the code later today, thanks! 🙂
    a
    • 2
    • 2
  • c

    Cies Breijs

    08/07/2025, 3:42 AM
    The previous framework that I used had some authorization by annotation feature. The permissions were represented with a list of an enum, and passed with a vararg to the annotation:
    Copy code
    @RequiredPermissions(Perm.SEE_GOD, Perm.HEAR_GOD, Perm.FEEL_LOVE) // or: @RequiresNoPermissions
    fun ultimateExperienceGetHandler(req: Request): Resposne { /* ... */ }
    The were serialized to the db's
    user_permissions
    table (with columns: userId, permEnum). Kind of worked well. I liked that all handlers required such annotation (created some test for that in the test suite). It feels like in http4k the best place to implement this is simply in the handler body. Functional. No annofuzz... (But please correct me if I'm wrong about this)
    Copy code
    fun ultimateExperienceGetHandler(req: Request): Resposne {
      if (!currentUserCtx(req).permissions.contains(Perm.SEE_GOD)) return Response(FORBIDDEN)
      // ...
    }
    But there's one thing I miss: the "closed by default" that I had with the annotations. So I wondered, would it be possible to have some sort of "closed by default" back by somehow specifying them in the router... Then:
    Copy code
    val portalRouter = routes(
      Paths.dashboard bind GET to ::dashboardGetHandler,
      Paths.profileEdit bind POST to ::profilePostHandler,
      Paths.profileEdit bind GET to ::profileGetHandler,
      Paths.retailerList bind GET to ::retailerListGetHandler,
      Paths.retailerView bind GET to ::retailerViewGetHandler,
      // ...
    )
    Would become something like:
    Copy code
    val portalRouter = authorizedRoutes(
      Triple(Paths.dashboard, GET to ::dashboardGetHandler, listOf(Perm.SEE_DASHBOARD)),
      Triple(Paths.profileEdit, POST to ::profilePostHandler, listOf(Perm.MODIFY_MY_PROFILE)),
      Triple(Paths.profileEdit, GET to ::profileGetHandler, listOf(Perm.MODIFY_MY_PROFILE)),
      // ...
    )
    Or even methods on the UserPermissions object like:
    Copy code
    val portalRouter = authorizedRoutes(
      Triple(Paths.dashboard, GET to ::dashboardGetHandler, listOf(::seeDashboard)),
      Triple(Paths.profileEdit, POST to ::profilePostHandler, listOf(::modifyMyProfile)),
      Triple(Paths.profileEdit, GET to ::profileGetHandler, listOf(::userHasOrganizationWithTypeX)), // <--
      // ...
    )
    Maybe my question is: how are y'all implementing authorization? (give that i need a very simple scheme for the foreseeable future)
    m
    a
    • 3
    • 8
  • c

    Cies Breijs

    08/08/2025, 10:29 AM
    I'm using the generate function from
    UriTemplate
    to build paths in a slightly more typesafe way. When looking at it's implementation I kind of wish for there to be a version of this function that throws an error if not all parameters are filled. Like
    generateOrThrow
    . This may help in some cases where you forget to pass a parameter (and I cannot forsee any situation where you do not want a parameter filled in). Am I on to something, or is this is stupid idea? Here the original function:
    s
    • 2
    • 3
  • s

    Slackbot

    08/14/2025, 2:10 PM
    This message was deleted.
    j
    s
    • 3
    • 2
  • m

    Marco Garofalo

    08/22/2025, 11:12 AM
    Hi, when using OAuthProvider is there a way to configure it so that the filter validates the (previously) "persisted" token? (e.g. token received from a secure cookie) From what I can see it just seems to check whether there is a non-null token, then is happy to continue the filter chain, what am I missing?
    d
    • 2
    • 3
  • a

    Andrew O'Hara

    09/03/2025, 5:09 PM
    Happy to see the maven central upgrade is finally complete! 🥳 Except I don't see one of my changes in the latest release, even though it's still present on master. Was the latest release not for master/HEAD? UPDATE: The MC upgrade isn't finished after all. This was just an "older" release that went out.
    🎉 1
    d
    l
    • 3
    • 12
  • a

    Alessandro Ciccimarra

    09/08/2025, 8:10 PM
    Hello team! 🙂 Looking at
    JavaHttpClient
    , some
    IOExceptions
    are caught (
    UnknownHostException
    ,
    ConnectException
    ,
    HttpTimeoutException
    ). Other exceptions, for example a
    SocketException
    caused by a connection reset, need to be handled at call site. What’s the reason for that?
    d
    • 2
    • 5
  • a

    almeydajuan

    09/09/2025, 2:05 PM
    Hello all, it seems that the tooling under https://toolbox.http4k.org/ is not working. Anything that I try(f.e. https://toolbox.http4k.org/dataclass), I get redirected to a 404
    d
    • 2
    • 5
  • a

    almeydajuan

    09/10/2025, 7:03 AM
    Good morning, I have a question about a behaviour in the security framework. I did not find so intuitive. We are working with
    BearerAuthSecurity
    . I have 2 example implementations:
    Copy code
    class Lookup(lookup: (String) -> String?) : Security by BearerAuthSecurity({ lookup(it) != null }), TokenSecurity
    class WithKey(lookup: (String) -> String?) :
        Security by BearerAuthSecurity(key = Header.required("Authorization"), lookup = { lookup(it) }), TokenSecurity
    Then if I do:
    Copy code
    val http1: HttpHandler = newBackend(tokenSecurity = WithKey { "hello" })
    val http2: HttpHandler = newBackend(tokenSecurity = Lookup { "hello" })
    
    Request(GET, "/hello").header("Authorization", "Bearer 123").use(http1)
    Request(GET, "/hello").header("Authorization", "Bearer 123").use(http2)
    The backend which uses security in with only
    lookup
    receives the bearer header, but the in the call to the 2nd backend (with the required header)
    Authorization
    headers is overriden and I get
    Authorization hello
    instead of
    Authorization Bearer 123
    For me it is unintuitive because we are using the same
    BearerAuthSecurity
    but depending on which parameter we pass, the request that arrives to our system comes already modified. Is this how this should behave? If so, what is the rational behind it? cc: @Michal Wachowski
    d
    m
    • 3
    • 4
  • m

    Mikael Ståldal

    09/11/2025, 6:50 PM
    Is there any support for dealing with Structured Field Values in http4k?
    a
    • 2
    • 2
  • a

    Andrew O'Hara

    09/14/2025, 12:17 AM
    Warning: the latest http4k artifacts now require all the optional dependencies. Bug logged. https://github.com/http4k/http4k/issues/1417 Update: Fixed! Upgrade to 4.18.0.1
    d
    • 2
    • 1
  • c

    Cies Breijs

    09/22/2025, 1:58 PM
    I'm now working with http4k for a couple of weeks. The app is shaping up nicely. And http4k has been an absolute joy to work with! A big thank you to all involved inr open sourcing this. I use it together with terpal-sql and kotlinx.html, to build an SSR app on top of Supabase (which is clearly not Supabase's design goal, but still works nicely). I want to share a few details and questions that i have (casual sharing, no urgent needs/dramas).
    🔥 2
    a
    d
    • 3
    • 33
  • d

    dave

    10/01/2025, 2:01 PM
    Hey http4k fans! We didn't ever really get around to telling you here about the new modules that we've recently introduced to http4k since the switch to Maven Central over the summer. A couple of highlights if you're upgrading from versions <= 6.15.1.0 to the newest shiny v6.18.1.0: • New module: http4k-testing-powerassert - Power Assert is now bundled with Kotlin, so it’s the perfect assertions library to use • New module: http4k-template-htmlflow - typesafe HTML builders in code • New module: http4k-connect-amazon-route53 - Basic hosted zone and record set management • http4k-web-datastar - D* was update to V1 recently and we've kept up with the quite reasonaly significant changes to the library since the betas were released. • http4k-format-dataframe - New v1 version of the Kotlin DF library • http4k-client-okhttp - Update to v5 of OkHttp - which takes advantages of java's Virtual threads and has support http4k-ai-mcp-sdk: We have consolidated all of the MCP modules into the http4k AI ecosystemfor GraalVM built in • http4k-connect-amazon-cognito: Better support for various auth challenge modes • http4k-core: Support for lenses and content negoriation, and accept-like headers • Misc: Upgrades to Kotlin 2.2.20 • Misc: Fixed a gnarly bug with SPA routes to improve support for SPAs hosted at non-route paths You can see the full changelog here: https://www.http4k.org/ecosystem/changelog/ Things on the radar: • There is a new version of OpenAPI (3.2.0), which adds a fair amount of new features including SSE event schemas: https://spec.openapis.org/oas/v3.2.0.html • Jackson v3 is on the horizon: https://github.com/FasterXML/jackson/wiki/Jackson-Release-3.0 so expect eventual changes to http4k-format-jackson, and maybe we'll get around to the rewrite of the http4k-api-openapi module
    http4k 4
    💪 1
    🎉 1
    a
    c
    • 3
    • 4
  • r

    Rafael Diaz

    10/05/2025, 12:59 AM
    Hi all. I'm currently trying to declare a list of type
    List<ContractRoute>
    . However, I'm ending up with the type
    List<Pair<ContractRouteSpec2<Int, String>.Binder, (Request) -> Response>>
    when I add lenses to the route path. I want to add the list of routes to an api contract, which accepts the former type but not the latter, so I was wondering how I could fix it. More details inside: Edit: Found the solution. https://stackoverflow.com/questions/53278208/how-do-you-model-a-path-parameter-in-the-middle-with-http4k
    d
    • 2
    • 4
  • r

    Rafael Diaz

    10/05/2025, 5:36 AM
    Another question, this time regarding OpenAPI V3 and Swagger integration.
    m
    d
    • 3
    • 4
  • a

    Andrew O'Hara

    10/07/2025, 1:43 AM
    Is there any consensus on the most effective way to perform SSR testing nowadays? • approval tests verify the exact outputted HTML, but can't test form submissions • webdriver tests are slower, more finicky, flakey, but can test form submissions Is the answer a bit of both?
    s
    c
    g
    • 4
    • 6
  • r

    Rafael Diaz

    10/19/2025, 2:57 AM
    Does anyone here use http4k with KMP app with Ktor client and share Kotlin code directly (via a shared module) as opposed to using OpenAPI to generate client types? Are there any guides or examples on best practices for this? More details inside:
    s
    • 2
    • 5
  • s

    Steven Webber

    10/21/2025, 9:02 AM
    Hi. For Http4k based services, what's the recommended approach to improve scalability? The problem I'm experiencing is that under heavy concurrent load, when upstream dependencies start slowing down, the service just runs out of threads and stops responding. The current setting is
    Copy code
    val customJetty = jettyServer(maxRequestThreads = 200, meterRegistry = prometheusMeterRegistry)
    myService.asK8sServer(serverConfig = customJetty, environment, healthApp = healthApp()).start()
    With a Quarkus based framework I'd switch to virtual threads using an annotation and that solves the issue. For http4K, should we switch to a different http server or change config for the existing one? Is the recommended approach to try and use java virtual threads?
    m
    • 2
    • 3
  • d

    David Beer

    10/23/2025, 3:04 PM
    Hi All, I am new to http4k, some nice concepts. I need to be able to configure the server (Jetty) from ENV variables. I know of being able to inject the port via ENV etc. I need to be able start the server from a custom config and the add the routes which extend RoutingHttpHnadler. My issue is getting the ServerConfig right so that when I start the server it stays running. What I am looking for is a full blown example rather than code snippets. This is my ServerConfig:
    Copy code
    class JettyConfig(private val port: Int) : ServerConfig {
    
        override fun toServer(http: HttpHandler): Http4kServer {
            val server = Server().apply {
                insertHandler(http.toJettyHandler())
            }
    
            return object : Http4kServer {
                override fun start(): Http4kServer = apply { server.start() }
    
                override fun stop(): Http4kServer = apply { server.stop() }
    
                override fun port(): Int = port
            }
        }
    
    
    }
    And Called using
    App.app.asServer(JettyConfig(App.port)).start()
    d
    d
    • 3
    • 9
  • d

    DanielZ

    10/28/2025, 6:23 PM
    Hey, I'm using in a service
    http4k-connect-amazon-s3
    for copying files from one s3 bucket to another. Now I'm facing the situation to deal with some huge files (>5GB). Is it somehow possible to copy those file using
    http4k-connect-amazon-s3
    or do I have to use aws sdk? Background: I'm aware that
    CopyObject
    has a limitation of 5GB, so I tried
    GetObject
    and
    PutObject
    which fails OOM in
    StreamBody
    . Any ideas? Do you have any experience with such cases?
    j
    • 2
    • 12
  • d

    dave

    11/24/2025, 1:03 PM
    Announcement alert.. http4k v*6.22.0.0* has been released with a few interesting recent updates that you might want to take advantage of. These include: • Support for HTTP Query verb, which is now very close to being a formal standard. In case you're not familiar,
    QUERY
    explicitly allows a request body which describes the query. Note that not all server engines support QUERY yet, but we have added support to get ahead of the curve. • http4k-ai-mcp-sdk now supports the new conformance test suite that the Model Context Protocol team have recently released - we have also published the conformance server as an artifact which you can use to test MCP clients against. There is also a new MCP draft spec in the pipeline so we will be looking at supporting that soon. • Performance/memory optimisations around HTTP message body handling Check out the changelog: https://www.http4k.org/ecosystem/changelog/
    🚀 4
    http4k 1
    a
    • 2
    • 2
  • r

    Rob Elliot

    11/28/2025, 12:15 PM
    Just FYI, this line in `org.http4k.core.Status`:
    val clientError by lazy { CLIENT_ERROR.contains(code) || clientGenerated }
    completely failed the principle of least surprise for me. I was blindsided by the idea that
    Status.clientError
    can be
    true
    for a
    5xx
    . I think it mixes two quite separate concerns: indicating where the status comes from, and indicating what the requester can do about it. The point of something being a clientError, a 4xx, is that there's no point repeating the same request without a change in server side state. I'd much prefer the
    clientGenerated
    property to be public and
    clientError
    just to be
    CLIENT_ERROR.contains(code)
    .
  • r

    Rob Elliot

    11/28/2025, 1:46 PM
    Have you considered using the
    Proxy-Status
    header to signal when an error is generated by the http4k client rather than by a remote server? https://httpwg.org/specs/rfc9209.html#rfc.section.2.1.1
    d
    • 2
    • 1
  • n

    natpryce

    12/01/2025, 10:36 AM
    A little bit of http4k syntactic sugar … If you define path lenses as extensions of Path like this…
    Copy code
    val Path.bob by lazyOf(Path.value(Bob).of("bob"))
    Then using them in routes can get quite verbose…
    Copy code
    "/${Path.alice}/${Path.bob}/${Path.carol}" bind ...
    But the following inline function lets you refer to them without the Path. prefix and therefore without curly braces:
    Copy code
    inline operator fun Path.invoke(mkPath: Path.() -> String) = mkPath()
    Now I can write bindings like…
    Copy code
    Path { "/$alice/$bob/$carol" } bind ...
    K 3
    d
    a
    • 3
    • 2
  • m

    Mikael Ståldal

    12/01/2025, 6:54 PM
    Is it possible to configure http4k client to use multiple endpoints for failover and/or load balancing?
    d
    • 2
    • 1