• Stars
    star
    228
  • Rank 175,267 (Top 4 %)
  • Language
    Clojure
  • License
    Eclipse Public Li...
  • Created over 11 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

An enhanced version of jetty adapter for ring, with additional features like websockets, http/2 and http/3

ring-jetty9-adapter (rj9a)

CI Clojars license Donate

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.

Usage

Leiningen

latest version on clojars

Code

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})

HTTP/2

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.

  • 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 prior to update 252, please check example-http2-legacy 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 ~jetty-version with corresponding jetty version that your version of rj9a uses.

HTTP/3

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:

  • Install libquiche on your system and make sure libquiche.so can be loaded from the Clojure(Java) application.
  • In addition to rj9a, add dependency [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
  • Provide certficate and key just like HTTPs setup because HTTP/3 is secure by default. There is no plaintext fallback for now.
  • Provide option :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.

WebSocket

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:

  • (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!:

(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})

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 (:websocket-subprotocol upgrade-request) and configure available (:websocket-extensions upgrade-request) via the websocket handler creator function. See websocket example for detail.

Examples

You can find examples in examples folder. To run example:

  • http: lein with-profile example-http run a very basic example of ring handler
  • async: lein with-profile example-async run ring 1.6 async handler example
  • http2 lein with-profile example-http2 run
  • http3 lein with-profile example-http3 run
  • websocket: lein with-profile example-websocket run

Contributors

License

Copyright Š 2013-2022 Sun Ning

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

More Repositories

1

handlebars-rust

Rust templating with Handlebars
Rust
1,089
star
2

node-geohash

geohash library for nodejs
JavaScript
565
star
3

heatcanvas

Pixel based heatmap with html5 canvas.
JavaScript
401
star
4

slacker

Transparent, non-incursive RPC by clojure and for clojure
Clojure
356
star
5

diehard

Clojure resilience library for flexible retry, circuit breaker and rate limiter
Clojure
309
star
6

pgwire

PostgreSQL wire protocol implemented as a rust library.
Rust
163
star
7

shake

clojure library that shakes your shell
Java
122
star
8

handlebars-iron

Handlebars middleware for Iron web framework
Rust
118
star
9

slacker-cluster

Clojure Micro-Service framework based on Slacker RPC
Clojure
77
star
10

pyclj

talking clojure with python - an edn implementation for python
Python
63
star
11

lein-jlink

A lein plugin creates and manages custom java environment
Clojure
59
star
12

hbs

clojure templating by handlebars.java
Clojure
48
star
13

papaline

Clojure concurrent pipleline on core.async
Clojure
47
star
14

rigui

Hierarchical Timing Wheels for Clojure and ClojureScript
Clojure
45
star
15

urdict

command line urban dictionary
Rust
42
star
16

stavka

Stavka manages configuration from various sources, for your Clojure application.
Clojure
41
star
17

exaile-doubanfm-plugin

An alternative choice to enjoy personalized music from douban.fm
Python
40
star
18

openbirdingmap

eBird location and observation data rendered on OpenStreetMap
Clojure
35
star
19

metriki

Rust metrics ported from dropwizard metrics
Rust
27
star
20

reddit.clj

A clojure wrapper for Reddit API
Clojure
25
star
21

rustmann

A riemann client on tokio, async/await
Rust
20
star
22

clojalk

A beanstalkd (distributed task queue) clone in clojure
Clojure
20
star
23

Exaile-Soundmenu-Indicator

integrate exaile with sound menu indicator
Python
19
star
24

cljts

A clojure wrapper of JTS, implements Simple Feature Specification of OGC
Clojure
17
star
25

clojuredocs-android

An Android app for ClojureDocs
JavaScript
14
star
26

lein-control

A lein plugin for clojure control
Clojure
12
star
27

tojson_macros

Simple rust syntax extension generates default ToJson implementation
Rust
11
star
28

timing

clojure syntax sugars for perf4j
Clojure
11
star
29

iron-json-response

Json response middleware for iron
Rust
10
star
30

stages

SEDA framework
Java
7
star
31

exaile-doubanfm-gnome-shell-extension

Exaile DoubanFM Control on GNOME-shell
JavaScript
7
star
32

bason

annotaion driven bson mapping tookit
Java
6
star
33

rageviewer

A rage comic viewer in clojure
Clojure
6
star
34

slacker-rust

Slacker RPC implemented by Rust and for Rust
Rust
4
star
35

greptimedb-bin.aur

AUR repository for GreptimeDB
Shell
4
star
36

lein-bootclasspath-deps

A Leiningen plugin to manage your bootclasspath.
Clojure
4
star
37

slacker-python

python client for slacker
Python
3
star
38

lazypress

Simplified online writing and publishing
JavaScript
3
star
39

sway-im.aur

Sway with input method popup support, packaged as AUR
Shell
2
star
40

mapzei

A maps extension for Ruman Nurik's live wallpaper app Muzei.
Java
2
star
41

karmalet

working in progress
Clojure
2
star
42

debug

Clojure port of nodejs debug
Clojure
2
star
43

link-socketio

Socketio server with link API
Clojure
2
star
44

slacker-htrace

Distributed tracing support for Slacker RPC using Apache HTrace
Clojure
2
star
45

nordenize

A project aimed to transform any webpage into nord color theme.
TypeScript
2
star
46

Artificial301

a simple firefox plugin and google appengine help you to get real link behind feedburner/feedproxy.google.com and url shorten services
JavaScript
2
star
47

alpine-jlink-base

Minimal base image for custom JRE created from jlink
1
star
48

handlebars-gotham

Handlebars templating middleware for Gotham
Rust
1
star
49

slacker-metrics

The metrics middleware for slacker RPC
Clojure
1
star
50

athtool

Command line TOTP generator
Rust
1
star
51

radar

redis proxy [WIP]
Clojure
1
star
52

metaq

A set of metaq API in favour of clojure
Clojure
1
star
53

leancloud-rtm-blacklist

LeanCloud 实时通信聊天室黑名单范例
JavaScript
1
star
54

datafusion-postgres

Rust
1
star
55

greptimedb-metabase-driver

A metabase driver plugin for GreptimeDB
Clojure
1
star