Ring adapter for Jetty 11 (although named as jetty9), with HTTP/2, WebSocket and experimental HTTP/3 support.
This is a simple and plain wrapper on modern Jetty versions. 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. This library can be used as a drop-in replacement of original ring-jetty-adapter.
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, http/3 and websocket.
JDK 8 support was dropped in Jetty 10 and above. To use JDK 8 and
Jetty 9, please use to 0.14.3
of this library.
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]]))
(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})
To enable HTTP/2 on cleartext and secure transport, you can simply add
options to run-jetty
like:
(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"})
ALPN dependency is required for secure HTTP/2 transport. For rj9a
version 0.17.1
and newer, org.eclipse.jetty/jetty-alpn-java-server
is included by default.
For rj9a versions prior to 0.17
, you will need additional dependency
to enable ALPN. Add following dependencies according to the jdk
version you use.
[org.eclipse.jetty/jetty-alpn-java-server ~jetty-version]
[org.eclipse.jetty/jetty-alpn-openjdk8-server ~jetty-version]
example-http2-legacy
profile
in project.clj for boot-classpath configuration[org.eclipse.jetty/jetty-alpn-conscrypt-server ~jetty-version]
but it's not recommended for now because of memory
leak issueNote your will need to replace ~jetty-version
with corresponding jetty version that
your version of rj9a uses.
From 10.0.9, Jetty ships an expiremental HTTP/3 implementation based
on Jetty's own build of
the quiche library. rj9a 0.17.6
made
it an optional feature. To enable HTTP/3 support, you will need to:
libquiche.so
can be
loaded from the Clojure(Java) application.[info.sunng/ring-jetty9-adapter-http3 "VERSION"]
to your clojure
project to bring in HTTP/3 staff. Remember to replace VERSION
with our
latest release, which can be checked
here:http3? true
to run-jetty
to enable HTTP/3
protocol.(jetty/run-jetty dummy-app {:port 5000 ;; default clear-text http/1.1 port
:http3 true ;; enable http/3 support
:ssl-port 5443 ;; ssl-port is used by http/3
:keystore "dev-resources/keystore.jks"
:key-password "111111"
:keystore-type "jks"})
Since HTTP/3 runs on UDP, it is possible to share the same port with TCP based protocol like HTTP/2 or 1.1.
An example is available in examples
folder.
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 ws
value:
Notice that we support different type of msg:
A callback can also be specified for send!
:
(send! ws msg {:write-failed (fn [throwable]) :write-success (fn [])})
A callback is a map where keys :write-failed
and :write-success
are optional.
In your ring app, detect a websocket handshake request and upgrade it with a websocket handler.
(require '[ring.adapter.jetty9 :as jetty])
(defn app [req]
(if (jetty/ws-upgrade-request? req)
(jetty/ws-upgrade-response ws-handler)))
(run-jetty app)
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 {:allow-null-path-info true})
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 (:websocket-subprotocol upgrade-request)
and
configure available (:websocket-extensions upgrade-request)
via the
websocket handler creator function. See websocket
example
for detail.
You can find examples in examples
folder. To run example:
lein with-profile example-http run
a very basic
example of ring handlerlein with-profile example-async run
ring 1.6 async
handler examplelein with-profile example-http2 run
lein with-profile example-http3 run
lein with-profile example-websocket run
Copyright © 2013-2022 Sun Ning
Distributed under the Eclipse Public License, the same as Clojure.
Can you improve this documentation? These fine people already did:
Ning Sun, Sun Ning, Thomas Crowley, Daniel Fitzpatrick, Joe Littlejohn, Dmitri Sotnikov & Michael KlishinEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close