{"id":15629752,"url":"https://github.com/sunng87/ring-jetty9-adapter","last_synced_at":"2025-05-14T16:12:05.411Z","repository":{"id":8139730,"uuid":"9558392","full_name":"sunng87/ring-jetty9-adapter","owner":"sunng87","description":"An enhanced version of jetty adapter for ring, with additional features like websockets, http/2 and http/3","archived":false,"fork":false,"pushed_at":"2025-04-08T01:36:41.000Z","size":612,"stargazers_count":281,"open_issues_count":6,"forks_count":50,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-04-12T21:18:52.240Z","etag":null,"topics":["clojure","clojure-ring","http","jetty","websockets"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sunng87.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["sunng87"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":"Sunng","issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2013-04-20T02:55:58.000Z","updated_at":"2025-04-08T01:36:44.000Z","dependencies_parsed_at":"2023-09-24T17:21:33.940Z","dependency_job_id":"a345b24d-a79e-42de-a115-e31b4825f2de","html_url":"https://github.com/sunng87/ring-jetty9-adapter","commit_stats":{"total_commits":376,"total_committers":28,"mean_commits":"13.428571428571429","dds":"0.44946808510638303","last_synced_commit":"2b27154e31096b05cf7d36865f46f15faef280b3"},"previous_names":[],"tags_count":106,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sunng87%2Fring-jetty9-adapter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sunng87%2Fring-jetty9-adapter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sunng87%2Fring-jetty9-adapter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sunng87%2Fring-jetty9-adapter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sunng87","download_url":"https://codeload.github.com/sunng87/ring-jetty9-adapter/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248631825,"owners_count":21136572,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clojure","clojure-ring","http","jetty","websockets"],"created_at":"2024-10-03T10:28:31.402Z","updated_at":"2025-04-12T21:18:56.685Z","avatar_url":"https://github.com/sunng87.png","language":"Clojure","funding_links":["https://github.com/sponsors/sunng87","https://liberapay.com/Sunng","https://liberapay.com/Sunng/donate"],"categories":[],"sub_categories":[],"readme":"# ring-jetty9-adapter (rj9a)\n\n[![CI](https://github.com/sunng87/ring-jetty9-adapter/actions/workflows/clojure.yml/badge.svg)](https://github.com/sunng87/ring-jetty9-adapter/actions/workflows/clojure.yml)\n[![Clojars](https://img.shields.io/clojars/v/info.sunng/ring-jetty9-adapter.svg?maxAge=2592000)](https://clojars.org/info.sunng/ring-jetty9-adapter)\n[![license](https://img.shields.io/github/license/sunng87/ring-jetty9-adapter.svg?maxAge=2592000)]()\n[![Donate](https://img.shields.io/badge/donate-liberapay-yellow.svg)](https://liberapay.com/Sunng/donate)\n\nRing adapter for Jetty 12 and 11 (although named as jetty9), with HTTP/2,\nWebSocket, experimental HTTP/3 and virtual threads support.\n\nThis is a simple and plain wrapper on modern Jetty versions. It\ndoesn't introduce additional thread model or anything else (no\nunofficial ring variance, no core.async). You are free to add those on\ntop of our base API. This library can be used as a drop-in replacement\nof original ring-jetty-adapter.\n\nAs of Ring 1.6, the official Jetty adapter has been updated to Jetty\n9.2. However, rj9a tracks most recent Jetty release and offers\nadditional features like http/2, http/3 and websocket.\n\n## Version Matrix\n\nrj9a works on top of certain components of Java/Clojure ecosystem. To find a\nversion works for your stack, check the version matrix below.\n\n| rj9a | Jetty | JDK | Clojure | Servlet API | Ring API | Maintained? |\n| --- | --- | --- | --- | --- | --- | --- |\n| HEAD | 12.0.x | 17 | 1.12 | N/A | 1.14 | true |\n| 0.33.x | 12.0.x | 17 | 1.11 | N/A | 1.12 | false |\n| 0.32.x | 12.0.x | 17 | 1.11 | N/A | 1.11 | false |\n| 0.30.x | 12.0.x | 17 | 1.11 | N/A | 1.10 | false |\n| 0.22.x | 11.0.x | 11 | 1.11 | Jakarta 5.0 | 1.10 | false |\n| 0.17.x | 10.0.x | 11 | 1.10 | Jakarta 4.0 | 1.9 | false |\n| 0.14.x | 9.4.x | 8 | 1.10 | 3.1 | 1.8 | false |\n\nThe `master` branch will keep tracking Jetty 12 as our default release\nchannel. Jetty versions prior to 12 have reached their EOF (support is only\navailable with commercial version), so now we are dropping support of them. But\nyou can still use it.\n\nNote that from 0.33 of rj9a, we dropped dependencies to `ring/ring-core` and\nonly depend on their protocol artifacts. This won't be a problem if your\napplications are just normal ring sync or async handlers. However, for websocket\nusers, you will need to include `ring/ring-core` explicitly as dependency to be\nable to use websocket APIs.\n\nFor JDK 8 users, `0.14` releases should be usable but I'm no longer actively\nmaintaining it.\n\n## Usage\n\n### Leiningen\n\n[![latest version on clojars](http://clojars.org/info.sunng/ring-jetty9-adapter/latest-version.svg)](https://clojars.org/info.sunng/ring-jetty9-adapter)\n\n### Code\n\nIn the REPL:\n\n```clojure\n(require '[ring.adapter.jetty9 :refer [run-jetty]])\n(run-jetty app {:port 50505}) ;; same as the 'official' adapter\n```\n\nIn ns declaration:\n\n```clojure\n(ns my.server\n  (:require [ring.adapter.jetty9 :refer [run-jetty]]))\n```\n\n### Ring 1.6 async handler\n\n```clojure\n(require '[ring.adapter.jetty9 :refer [run-jetty]])\n\n(defn app [request send-response raise-error]\n  (send-response {:body \"It works!\"}))\n(run-jetty app {:port 50505 :async? true})\n```\n\n### HTTP/2\n\nHTTP/2 becomes an optional feature since rj9a `0.35`, to enable HTTP/2 on\ncleartext and secure transport, first you need to add our optional dependency:\n\n```\n[info.sunng/ring-jetty9-adapter-http2 \"VERSION\"]\n```\n\n`VERSION` can be checked\n[here](https://clojars.org/info.sunng/ring-jetty9-adapter-http2)\n\nSecond, provide HTTP/2 options to `run-jetty` like:\n\n```clojure\n(jetty/run-jetty dummy-app {:port 5000\n                            :h2c? true  ;; enable cleartext http/2\n                            :h2? true   ;; enable http/2\n                            :ssl? true  ;; ssl is required for http/2\n                            :ssl-port 5443\n                            :keystore \"dev-resources/keystore.jks\"\n                            :key-password \"111111\"\n                            :keystore-type \"jks\"})\n```\n\nALPN dependency is required for secure HTTP/2 transport. For rj9a\nversion `0.17.1` and newer, `org.eclipse.jetty/jetty-alpn-java-server`\nis included by default.\n\nFor rj9a versions prior to `0.17`, you will need additional dependency\nto enable ALPN. Add following dependencies according to the JDK\nversion you use.\n\n* For JDK 11 and above, add `[org.eclipse.jetty/jetty-alpn-java-server\n  ~jetty-version]`\n* For OpenJDK 8u252 and above, add\n  `[org.eclipse.jetty/jetty-alpn-openjdk8-server ~jetty-version]`\n* For OpenJDK 8 prior to update 252, please [check `example-http2-legacy`\n  profile](https://github.com/sunng87/ring-jetty9-adapter/blob/0.14.3/project.clj#L26)\n  in `project.clj` for boot-classpath configuration\n* For any version of JDK users, conscrypt implementation is supported by adding\n  `[org.eclipse.jetty/jetty-alpn-conscrypt-server ~jetty-version]` but it's not\n  recommended for now because of [memory leak\n  issue](https://github.com/google/conscrypt/issues/835)\n\nNote your will need to replace `~jetty-version` with corresponding jetty version\nthat your version of rj9a uses.\n\n### HTTP/3\n\nFrom 10.0.9, Jetty ships an experimental HTTP/3 implementation based\non [Jetty's own build](https://github.com/jetty-project/jetty-quiche-native) of\n[the quiche library](https://github.com/cloudflare/quiche). rj9a `0.17.6` made\nit an optional feature. To enable HTTP/3 support, you will need to:\n\n* In addition to rj9a, add dependency\n  `[info.sunng/ring-jetty9-adapter-http3 \"VERSION\"]` to your clojure\n  project to bring in HTTP/3 staff. Remember to replace `VERSION` with our\n  latest release, which can be checked\n  [here](https://clojars.org/info.sunng/ring-jetty9-adapter-http3)\n* Provide certficate and key just like HTTPs setup because HTTP/3 is\n  secure by default. There is no plaintext fallback for now.\n* Provide option `:http3? true` and a work directory to for pem\n  `:http3-pem-work-directory` to `run-jetty` to enable HTTP/3 protocol.\n\n```clojure\n(jetty/run-jetty dummy-app {:port 5000  ;; default clear-text http/1.1 port\n                            :http3 true  ;; enable http/3 support\n                            :http3-pem-work-directory \"/some/path\" ;; a pre-created directory for quic configuration\n                            :ssl-port 5443 ;; ssl-port is used by http/3\n                            :keystore \"dev-resources/keystore.jks\"\n                            :key-password \"111111\"\n                            :keystore-type \"jks\"})\n```\n\nSince HTTP/3 runs on UDP, it is possible to share the same port with\nTCP based protocol like HTTP/2 or 1.1.\n\nAn example is available in `examples` folder.\n\n### WebSocket\n\nFrom Ring 1.11, Websocket API has been standardized. A valid websocket handler\ncan be defined as a map of listener functions:\n\n```clojure\n(def ws-handler {:on-open (fn [ws])\n                 :on-error (fn [ws e])\n                 :on-close (fn [ws status-code reason])\n                 :on-message (fn [ws message])\n                 :on-ping (fn [ws bytebuffer])\n                 :on-pong (fn [ws bytebuffer])})\n```\n\nFunctions are provided in `ring.websocket` to read and write data on the `ws`\nvalue:\n\n* `(ring.websocket/send ws msg)`\n* `(ring.websocket/send ws msg succeed-callback fail-callback)`\n* `(ring.websocket/ping ws msg)`\n* `(ring.websocket/close ws)`\n\nNotice that we support different type of msg:\n\n* **String**: send text websocket message\n* **ByteBuffer**: send binary websocket message\n\nIn your ring app, detect a websocket handshake request and upgrade it\nwith a websocket handler.\n\n```clojure\n(require '[ring.adapter.jetty9 :as jetty])\n\n(defn app [req]\n  (if (jetty/ws-upgrade-request? req)\n    (jetty/ws-upgrade-response ws-handler)))\n\n(run-jetty app)\n```\n\nIn the javascript:\n```javascript\n// remember to add the trailing slash.\n// Otherwise, jetty will return a 302 on websocket upgrade request,\n// which is not supported by most browsers.\nvar ws = new WebSocket(\"ws://somehost/loc/\");\nws.onopen = ....\n```\n\nIf you want to omit the trailing slash from your URLs (and not receive\na redirect from Jetty), you can start the server like:\n\n```clojure\n(run-jetty app {:allow-null-path-info true})\n```\n\n### Websocket Handshake\n\nSometimes you may have a negotiation with the websocket client on the\nhandshake (upgrade request) phase. You can define a ring like function\nthat returns the websocket handler, or raises an error. You may also\nselect a subprotocol from `(:websocket-subprotocol upgrade-request)` via the\nwebsocket handler creator function. See [websocket\nexample](https://github.com/sunng87/ring-jetty9-adapter/blob/master/examples/rj9a/websocket.clj)\nfor detail.\n\n## Examples\n\nYou can find examples in `examples` folder. To run example:\n\n* http: `lein with-profile example-http run` a very basic\n  example of ring handler\n* async: `lein with-profile example-async run` ring 1.6 async\n  handler example\n* http2: `lein with-profile example-http2 run`\n* http3: `lein with-profile example-http3 run`\n* websocket: `lein with-profile example-websocket run`\n\n## License\n\nCopyright © 2013-2024 Sun Ning\n\nDistributed under the Eclipse Public License, the same as Clojure.\n\n## Sponsors\n\nThis project is sponsored by:\n\n- [TOYOKUMO](https://github.com/toyokumo) sponsored this project in [Thanks OSS\n  Award](https://oss.toyokumo.co.jp/) program.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsunng87%2Fring-jetty9-adapter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsunng87%2Fring-jetty9-adapter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsunng87%2Fring-jetty9-adapter/lists"}