Seekable streams for HTTP range requests

Javalin finally supports streaming large files, which is mainly used for music and video:

  • Kotlin
  • Java
app.get("/file") { ctx ->
    val file = File("/my-file.mp3")
    ctx.seekableStream(file.inputStream(), "audio/mpeg")
app.get("/file", ctx -> {
    File file = new File("/my-file.mp3");
    ctx.seekableStream(new FileInputStream(file), "audio/mpeg");

Using ctx.seekableStream enables seeking (“skipping”) in audio and video players, as well as resuming downloads of larger files.

WebSocket session attributes (and context path change)

We spoke with the people running the Jetty project, and it turns out that the way Javalin has been attaching the WebSocketServlet and HttpServlet to Jetty is “non-standard” (but not completely disallowed). We used to attach two ServletContextHandler objects to the Jetty Server, which caused some issues with sessions not being linked. We only use one ServletContextHandler now, which means that the config.wsContextPath config variable had to be removed, but it also means that we finally have session attributes working in WebSocket handlers!

This should make it a much easier to authenticate your WebSocket requests:

  • Kotlin
  • Java"/") { ws ->
    ws.onConnect { ctx ->
}"/", ws -> {
    ws.onConnect(ctx -> {

OpenAPI improvements

  • Added option to specify security (thanks to @TobiasWalle).
  • Improved docs for endpoints with both file-uploads and form-params (thanks to @manuelhuber).
  • Added support for different content types in formDataBody (thanks to @TobiasWalle).
  • Added support for adding examples to models.
  • Added missing boxed types (thanks to @28Smiles).
  • Added support for multiple query param values (thanks to @28Smiles).
  • Add assertion for multiple documentations of the same path (thanks to @28Smiles).
  • Added support for beans in query params (thanks to @28Smiles).

Misc features and fixes

  • Added a ByteArray/byte[] overload to Context#result (thanks to @danwallach).
  • Added option to use jsDelivr for static resource on non localhost in JavalinVue plugin.
  • The RateLimit class now takes load-balancers into account by checking X-Forwarded-For (previously just used ip).
  • JSON deserialization errors now log info instead of debug in ctx.bodyAsClass().
  • The staticInstance() method of the ApiBuilder is now public, making the ApiBuilder easy to extend.