Need help with ring-jetty9-adapter?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

140 Stars 27 Forks 275 Commits 5 Opened issues


Ring adapter for jetty9, which supports websocket and http2

Services available


Need anything else?

Contributors list

ring-jetty9-adapter (rj9a)

Ring adapter for Jetty 9 with HTTP2 and WebSocket support.

This is a simple and plain wrapper on Jetty 9. It doesn't introduce additional thread model or anything else (no unofficial ring variance, no core.async). You are free to add those on top of our base API.

As of Ring 1.6, the official Jetty adapter has been updated to Jetty 9.2. However, rj9a tracks most recent Jetty release and offers additional features like http/2 and websocket.



latest version on clojars


In the REPL:

(require '[ring.adapter.jetty9 :refer [run-jetty]])
(run-jetty app {:port 50505}) ;; same as the 'official' adapter

In ns declaration:

(ns my.server
  (:require [ring.adapter.jetty9 :refer [run-jetty]]))

Ring 1.6 async handler

(require '[ring.adapter.jetty9 :refer [run-jetty]])

(defn app [request send-response raise-error] (send-response {:body "It works!"})) (run-jetty app {:port 50505 :async? true})

Use HTTP 1.1 Only

If you use plain socket http 1.1 only, for example, behind an nginx with ssl off-loading, you can exclude HTTPs dependencies to reduce the uberjar size:

:exclusions [org.eclipse.jetty/jetty-alpn-conscrypt-server


ALPN is required for HTTP/2 transport, you will need additional dependency to enable ALPN.

  • For JDK 11 and above, add
    [org.eclipse.jetty/jetty-alpn-java-server ~jetty-version]
  • For OpenJDK 8u252 and above, add
    [org.eclipse.jetty/jetty-alpn-openjdk8-server ~jetty-version]
  • For OpenJDK 8 but below 252, please check
    profile in project.clj for boot-classpath configuration
  • For any version of JDK users, conscrypt implementation is supported by adding
    [org.eclipse.jetty/jetty-alpn-conscrypt-server ~jetty-version]
    but it's not recommended for now because of memory leak issue

Note your will need to replace

with corresponding jetty version that your version of rj9a uses.

To enable HTTP/2 on cleartext and secure transport, you can simply add options to

(jetty/run-jetty dummy-app {:port 5000
                            :h2c? true  ;; enable cleartext http/2
                            :h2? true   ;; enable http/2
                            :ssl? true  ;; ssl is required for http/2
                            :ssl-port 5443
                            :keystore "dev-resources/keystore.jks"
                            :key-password "111111"
                            :keystore-type "jks"})


You can define following handlers for websocket events.

(def ws-handler {:on-connect (fn [ws])
                 :on-error (fn [ws e])
                 :on-close (fn [ws status-code reason])
                 :on-text (fn [ws text-message])
                 :on-bytes (fn [ws bytes offset len])
                 :on-ping (fn [ws bytebuffer])
                 :on-pong (fn [ws bytebuffer])})

WebSocketProtocol allows you to read and write data on the

  • (send! ws msg)
  • (send! ws msg callback)
  • (ping! ws)
  • (ping! ws msg)
  • (close! ws)
  • (remote-addr ws)
  • (idle-timeout! ws timeout)

Notice that we support different type of msg:

  • byte[] and ByteBuffer: send binary websocket message
  • String and other Object: send text websocket message
  • (fn [ws]) (clojure function): Custom function you can operate on Jetty's RemoteEndpoint

A callback can also be specified for

(send! ws msg {:write-failed (fn [throwable]) :write-success (fn [])})

A callback is a map where keys

are optional.

There is a new option

available. Accepting a map of context path and listener class:
(use 'ring.adapter.jetty9)
(run-jetty app {:websockets {"/loc" ws-handler}})

In the javascript:

// remember to add the trailing slash.
// Otherwise, jetty will return a 302 on websocket upgrade request,
// which is not supported by most browsers.
var ws = new WebSocket("ws://somehost/loc/");
ws.onopen = ....

If you want to omit the trailing slash from your URLs (and not receive a redirect from Jetty), you can start the server like:

(run-jetty app {:websockets {"/loc" ws-handler}
                :allow-null-path-info true})

Websocket Handshake

Sometimes you may have a negotiation with the websocket client on the handshake (upgrade request) phase. You can define a ring like function that returns the websocket handler, or raises an error. You may also select a subprotocol from

(:subprotocol request)
and configure available
(:extensions request)
. See websocket example for detail.


You can find examples in

folder. To run example:
  • http:
    lein with-profile default,example-http run
    a very basic example of ring handler
  • async:
    lein with-profile default,example-async run
    ring 1.6 async handler example
  • http2 with openjdk 8u252 and above:
    lein with-profile example-http2-openjdk8 run
  • http2 with openjdk 11+
    lein with-profile example-http2 run
  • websocket:
    lein with-profile default,example-websocket run



Copyright © 2013-2017 Sun Ning

Distributed under the Eclipse Public License, the same as Clojure.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.