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

    Cies

    06/12/2025, 8:40 AM
    Any good suggestions for a light weight (many JWT libs depend on kotlin-reflect and/or jackson!) JWT lib that supports the
    hs256
    algorithm that Supabase uses?
    d
    c
    • 3
    • 5
  • c

    Cies

    06/12/2025, 8:42 AM
    Or should I just parse it myself (I've learned to lean on established libs when it comes to auth stuff, but decrypting a JSON string cannot be thát hard...)
  • p

    Paul Reijbroek

    06/13/2025, 6:52 PM
    Hello, Because the company I’m working for is looking to do some operations on CloudWatch that are not supported (yet), I’m working on a PR to include a new CloudWatch module for http4k-connect to support some of those operations. I’ve written functionality in particular for alarms, metric data and metric streams (considering these look like the most common use cases and/or are the operations we need to have), but I’m running into a couple of issues for the fake implementations and the tests. Please see 🧵 for a list of the issues I’m running into. What would be a good approach for them?
    j
    d
    • 3
    • 10
  • d

    DanielZ

    06/13/2025, 8:23 PM
    Hi, I'm struggling using http4k-connect. I try to use S3 with an ARN role based authentication but failing with a lens error of a missing AWS_ACCESS_KEY_ID. Wondering where I miss something?
    Copy code
    const val USE_REAL_CLIENT = false
    fun main() {
        val env = Environment.defaults(
            AWS_REGION of Region.EU_WEST_1,
            AWS_ROLE_ARN of ARN.of("arn:aws:sts:us-east-1:000000000001:role:myrole")
        )
        val http: HttpHandler = if (USE_REAL_CLIENT) JavaHttpClient() else FakeS3().debug()
        val credentialsProvider = CredentialsProvider.STS(env, FakeSTS().debug())
        val s3 = S3.Http(credentialsProvider = credentialsProvider, http)
    
        val sourceName = BucketName.of("source-bucket")
        val targetName = BucketName.of("target-bucket")
        s3.createBucket(sourceName, env[AWS_REGION]).recover(RemoteFailure::throwIt) // <<< fails here: env 'AWS_ACCESS_KEY_ID' is required
        s3.createBucket(targetName, env[AWS_REGION]).recover(RemoteFailure::throwIt)
    
        val source = S3Bucket.Http(sourceName, env[AWS_REGION], credentialsProvider, http)
        source.putObject(BucketKey.of("hello"), "hello ".byteInputStream()).recover(RemoteFailure::throwIt)
    
        val target = S3Bucket.Http(targetName, env[AWS_REGION], credentialsProvider, http)
        target.copyObject(source.bucketName, BucketKey.of("hello"), BucketKey.of("copy"))
            .recover(RemoteFailure::throwIt)
    }
    d
    a
    • 3
    • 6
  • t

    Tudor Luca

    06/14/2025, 7:14 PM
    Stupid question incoming: if http4k is a pure kotlin framework, why doesn’t it support kotlin/native or js/wasm as targets? Context: I’m looking into enabling our experienced mobile devs to reach and contribute to “the server”. We’re already supporting both Android & iOS platforms with a KMP shared module for business logic, networking & sqlite, so we’re experimenting what’s the smoothest path to enable feature contributions to the server too. We’re using the Ktor client on mobile, but I always had a soft spot for arrow & sane fp patterns so I’m seriously looking at http4k, ktor or smth full-blown like Quarkus. Our current server stack is dotnet-core, don’t ask why 😅.
    d
    • 2
    • 2
  • 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