-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
24 changed files
with
1,015 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{:linters {:refer-all {:exclude [clojure.test]}}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/target | ||
/classes | ||
/checkouts | ||
profiles.clj | ||
pom.xml | ||
pom.xml.asc | ||
*.jar | ||
*.class | ||
/.lein-* | ||
/.nrepl-port | ||
/.prepl-port | ||
.hgignore | ||
.hg/ | ||
.idea/ | ||
*.iml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../common |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.3.xsd"> | ||
|
||
<!-- Only include legitimate suppressions of false-positives in this file --> | ||
|
||
</suppressions> |
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
(defproject io.factorhouse/slipway-jetty12 "1.1.18" | ||
|
||
:description "A Clojure Companion for Jetty 12" | ||
|
||
:url "https://github.com/factorhouse/slipway" | ||
|
||
:license {:name "Apache 2.0 License" | ||
:url "https://github.com/factorhouse/slipway/blob/main/LICENSE"} | ||
|
||
:profiles {:dev {:dependencies [[com.fasterxml.jackson.core/jackson-core "2.18.2"] ;; required for internal inconsistency within clj-kondo, kept at latest for CVE avoidance | ||
[clj-kondo "2024.11.14"] | ||
[clj-http "3.13.0"] | ||
[ch.qos.logback/logback-classic "1.3.14"] ;; Logback 1.3.x supports the Java EE edition whereas logback 1.4.x supports Jakarta EE, otherwise the two versions are feature identical. The 1.5.x continues the 1.4.x series but with logback-access relocated to its own repository. | ||
[ring/ring-anti-forgery "1.3.1"] | ||
[metosin/reitit-ring "0.7.2" :exclusions [ring/ring-core]]] | ||
:resource-paths ["dev-resources" "common/dev-resources"] | ||
:plugins [[lein-cljfmt "0.9.2"]]} | ||
:smoke {:pedantic? :abort}} | ||
|
||
:aliases {"check" ["with-profile" "+smoke" "check"] | ||
"kondo" ["with-profile" "+smoke" "run" "-m" "clj-kondo.main" "--lint" "common/src:common-jetty1x/src:test:common/test" "--parallel"] | ||
"fmt" ["with-profile" "+smoke" "cljfmt" "check"]} | ||
|
||
:dependencies [[org.clojure/clojure "1.12.0"] | ||
[org.clojure/tools.logging "1.3.0"] | ||
[commons-io "2.16.1"] ;; replaces old version with CVE in ring-servlet, remove when ring bumped to latest | ||
[org.ring-clojure/ring-jakarta-servlet "1.13.0"] | ||
[com.taoensso/sente "1.17.0"] | ||
[org.eclipse.jetty.websocket/jetty-websocket-jetty-api "12.0.16"] | ||
[org.eclipse.jetty.websocket/jetty-websocket-jetty-server "12.0.16" :exclusions [org.slf4j/slf4j-api]] | ||
[org.eclipse.jetty/jetty-server "12.0.16" :exclusions [org.slf4j/slf4j-api]] | ||
[org.eclipse.jetty/jetty-security "12.0.16" :exclusions [org.slf4j/slf4j-api]] | ||
[org.eclipse.jetty.ee10/jetty-ee10-servlet "12.0.16"] | ||
[org.slf4j/slf4j-api "2.0.16"]] | ||
|
||
:source-paths ["src" "common/src" "common-jetty1x/src" "common-javax/src"] | ||
:test-paths ["common/test"] | ||
|
||
:javac-options ["--release" "17"]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
(ns slipway | ||
(:require [clojure.tools.logging :as log] | ||
[slipway.connector.http] | ||
[slipway.connector.https] | ||
[slipway.handler] | ||
[slipway.security :as security] | ||
[slipway.server :as server] | ||
[slipway.user]) | ||
(:import (org.eclipse.jetty.server Handler Server))) | ||
|
||
(comment | ||
#:slipway.handler.gzip{:enabled? "is gzip enabled? default true" | ||
:included-mime-types "mime types to include (without charset or other parameters), leave nil for default types" | ||
:excluded-mime-types "mime types to exclude (replacing any previous exclusion set)" | ||
:min-gzip-size "min response size to trigger dynamic compression (in bytes, default 1024)"} | ||
|
||
#:slipway.connector.https{:host "the network interface this connector binds to as an IP address or a hostname. If null or 0.0.0.0, then bind to all interfaces. Default null/all interfaces" | ||
:port "port this connector listens on. If set to 0 a random port is assigned which may be obtained with getLocalPort(), default 443" | ||
:idle-timeout "max idle time for a connection, roughly translates to the Socket.setSoTimeout. Default 200000 ms" | ||
:http-forwarded? "if true, add the ForwardRequestCustomizer. See Jetty Forward HTTP docs" | ||
:proxy-protocol? "if true, add the ProxyConnectionFactor. See Jetty Proxy Protocol docs" | ||
:http-config "a concrete HttpConfiguration object to replace the default config entirely" | ||
:configurator "a fn taking the final connector as argument, allowing further configuration" | ||
:keystore "keystore to use, either path (String) or concrete KeyStore" | ||
:keystore-type "type of keystore, e.g. JKS" | ||
:keystore-password "password of the keystore" | ||
:key-manager-password "password for the specific key within the keystore" | ||
:truststore "truststore to use, either path (String) or concrete KeyStore" | ||
:truststore-password "password of the truststore" | ||
:truststore-type "type of the truststore, eg. JKS" | ||
:include-protocols "a list of protocol name patterns to include in SSLEngine" | ||
:exclude-protocols "a list of protocol name patterns to exclude from SSLEngine" | ||
:replace-exclude-protocols? "if true will replace existing exclude-protocols, otherwise will add them" | ||
:exclude-ciphers "a list of cipher suite names to exclude from SSLEngine" | ||
:replace-exclude-ciphers? "if true will replace existing exclude-ciphers, otherwise will add them" | ||
:security-provider "the security provider name" | ||
:client-auth "either :need or :want to set the corresponding need/wantClientAuth field" | ||
:ssl-context "a concrete pre-configured SslContext" | ||
:sni-required? "true if SNI is required, else requests will be rejected with 400 response, default false" | ||
:sni-host-check? "true if the SNI Host name must match when there is an SNI certificate, default false" | ||
:sts-max-age "set the Strict-Transport-Security max age in seconds, default -1" | ||
:sts-include-subdomains? "true if a include subdomain property is sent with any Strict-Transport-Security header"} | ||
|
||
#:slipway.connector.http{:host "the network interface this connector binds to as an IP address or a hostname. If null or 0.0.0.0, then bind to all interfaces. Default null/all interfaces." | ||
:port "port this connector listens on. If set to 0 a random port is assigned which may be obtained with getLocalPort(), default 80" | ||
:idle-timeout "max idle time for a connection, roughly translates to the Socket.setSoTimeout. Default 200000 ms" | ||
:http-forwarded? "if true, add the ForwardRequestCustomizer. See Jetty Forward HTTP docs" | ||
:proxy-protocol? "if true, add the ProxyConnectionFactory. See Jetty Proxy Protocol docs" | ||
:http-config "a concrete HttpConfiguration object to replace the default config entirely" | ||
:configurator "a fn taking the final connector as argument, allowing further configuration"} | ||
|
||
#:slipway.security{:realm "the Jetty authentication realm" | ||
:hash-user-file "the path to a Jetty Hash User File" | ||
:login-service "a Jetty LoginService identifier, 'jaas' and 'hash' supported by default" | ||
:identity-service "a concrete Jetty IdentityService" | ||
:authenticator "a concrete Jetty Authenticator (e.g. FormAuthenticator or BasicAuthenticator)" | ||
:constraint-mappings "a list of concrete Jetty ConstraintMapping"} | ||
|
||
#:slipway.session{:secure-request-only? "set the secure flag on session cookies (default true)" | ||
:http-only? "set the http-only flag on session cookies (default true)" | ||
:same-site "set session cookie same-site policy to :none, :lax, or :strict (default :strict)" | ||
:max-inactive-interval "max session idle time (in s, default -1)" | ||
:tracking-modes "a set (colloection) of #{:cookie, :ssl, or :url}" | ||
:cookie-name "the name of the session cookie" | ||
:session-id-manager "the meta manager used for cross context session management" | ||
:refresh-cookie-age "max time before a session cookie is re-set (in s)" | ||
:path-parameter-name "name of path parameter used for URL session tracking"} | ||
|
||
;; Jetty 10 / Jetty 11 Websockets | ||
#:slipway.websockets{:idle-timeout "max websocket idle time (in ms), default 500000" | ||
:input-buffer-size "max websocket input buffer size (in bytes)" | ||
:output-buffer-size "max websocket output buffer size (in bytes)" | ||
:max-text-message-size "max websocket text message size (in bytes, default 65536)" | ||
:max-binary-message-size "max websocket binary message size (in bytes)" | ||
:max-frame-size "max websocket frame size (in bytes)" | ||
:auto-fragment "websocket auto fragment (boolean)"} | ||
|
||
;; Jetty 9 Websockets | ||
#:slipway.websockets{:idle-timeout "max websocket idle time (in ms), default 500000" | ||
:input-buffer-size "max websocket input buffer size" | ||
:max-text-message-size "max websocket text message size" | ||
:max-binary-message-size "max websocket binary message size"} | ||
|
||
#:slipway.handler{:context-path "the root context path, default '/'" | ||
:ws-path "the path serving the websocket upgrade handler, default '/chsk'" | ||
:null-path-info? "true if /path is not redirected to /path/, default true"} | ||
|
||
#:slipway.server{:handler "the base Jetty handler implementation (:default defmethod impl found in slipway.handler)" | ||
:connectors "the connectors supported by this server" | ||
:thread-pool "the thread-pool used by this server (leave null for reasonable defaults)" | ||
:error-handler "the error-handler used by this server for Jetty level errors"} | ||
|
||
#:slipway{:join? "join the Jetty threadpool, blocks the calling thread until jetty exits, default false"}) | ||
|
||
(defn start ^Server | ||
[ring-handler {::keys [join?] :as opts}] | ||
(log/info "starting slipway server") | ||
(let [server (server/create-server opts) | ||
login-service (security/login-service opts)] | ||
(.setHandler server ^Handler (server/handler ring-handler login-service opts)) | ||
(some->> login-service (.addBean server)) | ||
(.start server) | ||
(when join? | ||
(log/info "joining jetty thread") | ||
(.join server)) | ||
server)) | ||
|
||
(defn stop | ||
[^Server server] | ||
(log/info "stopping slipway server") | ||
(.stop server)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
(ns slipway.common.websockets | ||
(:require [clojure.string :as string])) | ||
|
||
(defprotocol WebSockets | ||
(send! [this msg] [this msg callback]) | ||
(ping! [this] [this msg]) | ||
(close! [this] [this status-code reason]) | ||
(remote-addr [this]) | ||
(idle-timeout! [this ms]) | ||
(connected? [this]) | ||
(req-of [this])) | ||
|
||
(defprotocol WebSocketSend | ||
(-send! [x ws] [x ws callback])) | ||
|
||
(defprotocol WebSocketPing | ||
(-ping! [x ws])) | ||
|
||
(defn upgrade-request? | ||
[{:keys [headers]}] | ||
(let [connection (or (get headers "Connection") (get headers "connection")) | ||
upgrade (or (get headers "Upgrade") (get headers "upgrade"))] | ||
(and (some? upgrade) | ||
(some? connection) | ||
(string/includes? (string/lower-case upgrade) "websocket") | ||
(string/includes? (string/lower-case connection) "upgrade")))) | ||
|
||
(defn upgrade-response? | ||
[{:keys [status ws] :as resp}] | ||
(and (= 101 status) (map? ws) (upgrade-request? resp))) | ||
|
||
(defn upgrade-response | ||
[ws-handler] | ||
{:status 101 | ||
:headers {"Connection" "Upgrade" | ||
"Upgrade" "Websocket"} | ||
:ws ws-handler}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
(ns slipway.connector.http | ||
(:require [clojure.tools.logging :as log] | ||
[slipway.server :as server]) | ||
(:import (org.eclipse.jetty.server ConnectionFactory ForwardedRequestCustomizer HttpConfiguration | ||
HttpConnectionFactory ProxyConnectionFactory Server ServerConnector))) | ||
|
||
(defn default-config ^HttpConfiguration | ||
[{::keys [http-forwarded? send-server-version? send-date-header?] | ||
:or {send-server-version? false | ||
send-date-header? false}}] | ||
(let [config (doto (HttpConfiguration.) | ||
(.setSendServerVersion send-server-version?) | ||
(.setSendDateHeader send-date-header?))] | ||
(when http-forwarded? (.addCustomizer config (ForwardedRequestCustomizer.))) | ||
config)) | ||
|
||
(comment | ||
#:slipway.connector.http{:host "the network interface this connector binds to as an IP address or a hostname. If null or 0.0.0.0, then bind to all interfaces. Default null/all interfaces" | ||
:port "port this connector listens on. If set to 0 a random port is assigned which may be obtained with getLocalPort(), default 80" | ||
:idle-timeout "max idle time for a connection, roughly translates to the Socket.setSoTimeout. Default 200000 ms" | ||
:http-forwarded? "if true, add the ForwardRequestCustomizer. See Jetty Forward HTTP docs" | ||
:proxy-protocol? "if true, add the ProxyConnectionFactor. See Jetty Proxy Protocol docs" | ||
:http-config "a concrete HttpConfiguration object to replace the default config entirely" | ||
:configurator "a fn taking the final connector as argument, allowing further configuration" | ||
:send-server-version? "if true, send the Server header in responses" | ||
:send-date-header? "if true, send the Date header in responses"}) | ||
|
||
(defmethod server/connector ::connector | ||
[^Server server {::keys [host port idle-timeout proxy-protocol? http-forwarded? configurator http-config] | ||
:or {idle-timeout 200000 | ||
port 80} | ||
:as opts}] | ||
(log/infof (str "starting " (when proxy-protocol? "proxied ") "HTTP connector on %s:%s" (when http-forwarded? " with http-forwarded support")) (or host "all-interfaces") port) | ||
(let [http-factory (HttpConnectionFactory. (or http-config (default-config opts))) | ||
factories (->> (if proxy-protocol? [(ProxyConnectionFactory.) http-factory] [http-factory]) | ||
(into-array ConnectionFactory)) | ||
connector (ServerConnector. ^Server server ^"[Lorg.eclipse.jetty.server.ConnectionFactory;" factories)] | ||
(.setHost connector host) | ||
(.setPort connector port) | ||
(.setIdleTimeout connector idle-timeout) | ||
(when configurator (configurator connector)) | ||
connector)) |
Oops, something went wrong.