Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTP/2 server #687

Merged
merged 104 commits into from
Nov 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
e1bebcd
Clean up and reformatting of server code
KingMob Jun 30, 2023
b67c250
Re-indent safe-execute as a body macro
KingMob Jun 30, 2023
1deac6e
More cleanup of docstring table
KingMob Jun 30, 2023
9070415
Add ALPN support to server SslContexts
KingMob Jun 30, 2023
21e9dbd
Move http2 pipeline setup to a.h.http2 ns
KingMob Jun 30, 2023
02095f2
Setup conn-level pipeline
KingMob Jun 30, 2023
2bd5198
Replaced slow, ad hoc date formatting with Netty fns
KingMob Jul 1, 2023
b3338de
Move add-non-http-handlers to common ns
KingMob Jul 16, 2023
3a1a149
Minor refactoring and docstrings
KingMob Jul 16, 2023
70fad2c
Move date-related code and server name to a.h.common
KingMob Jul 29, 2023
4e7cd03
Fix unnecessary continue-executor shutdown
KingMob Jul 29, 2023
2bda782
Simplified common header generation
KingMob Jul 29, 2023
c5c143c
Update server params for setup-http1-pipeline
KingMob Jul 29, 2023
87a3411
Update and fix HTTP/2 header handling
KingMob Jul 29, 2023
1e98ffa
First pass at HTTP2 server code
KingMob Jul 29, 2023
463b424
Ignore .pem files
KingMob Jul 31, 2023
f16147e
WIP
KingMob Jul 31, 2023
3a03056
Fix bug confusing conn chan with outbound chan
KingMob Aug 13, 2023
97fda5c
Update contrib instructions for using TLS
KingMob Aug 30, 2023
b748c92
Minor cleanup
KingMob Aug 30, 2023
a35226a
Fix issue with byte-streams.graph.Type loaded by different ClassLoaders
KingMob Aug 30, 2023
7ad1b8c
Update TLS return type hints
KingMob Aug 30, 2023
23503a1
Switch to BoringSSL for local dev
KingMob Aug 30, 2023
ded4f0f
Add a lot of logging
KingMob Aug 30, 2023
275cd30
Update comments and commented server examples
KingMob Aug 30, 2023
04eee02
Log exceptions in send-response
KingMob Aug 30, 2023
18f4ec6
Add type hint on te-header-name for .equals
KingMob Aug 30, 2023
877f7ad
Convert :scheme pseudo-header to string
KingMob Aug 30, 2023
787f40f
Close the circuit - http2 server now sending
KingMob Aug 30, 2023
35c6093
Update project.clj
KingMob Aug 30, 2023
21e4b44
Fix NPE bug when ALPN not used
KingMob Aug 30, 2023
02ac0a8
Reset ALPN fallback protocol to HTTP/1
KingMob Aug 30, 2023
ed61b85
Moved server-test to common-test
KingMob Aug 30, 2023
30feb0a
Minor reformatting and aleph.http comment example update
KingMob Aug 30, 2023
4522f13
Refactor existing HTTP tests in prep for http2
KingMob Aug 31, 2023
01f0cbc
Alter final pipeline error handling
KingMob Aug 31, 2023
5230389
Revert reject handler to only being invoked on executor rejection
KingMob Aug 31, 2023
30e4f91
First pass at adding HTTP2 testing
KingMob Aug 31, 2023
472254f
Improve pr support for AsciiStrings
KingMob Sep 1, 2023
7f9ad2a
Switch to using Http2Exception/StreamException in client
KingMob Sep 1, 2023
b155a4a
Minor doc updates
KingMob Sep 18, 2023
cc0ebc4
Add :protocol to http1 ring request maps
KingMob Sep 18, 2023
e4b6b17
Convert util fns to use ChannelOutboundInvoker
KingMob Sep 18, 2023
522c275
Update add-exception-handler to close and not propagate
KingMob Sep 18, 2023
72d4ae1
If client-handler's channel goes inactive, set (or try to) complete t…
KingMob Sep 18, 2023
9969937
Add stream-ex helper fn
KingMob Sep 18, 2023
41c6f9e
Add :channel-read-complete to server handler
KingMob Sep 18, 2023
2c708dc
Add go-away fn
KingMob Sep 18, 2023
71cbb3e
Add header validation and status parsing
KingMob Sep 18, 2023
3cc3ca1
Update imports
KingMob Sep 18, 2023
caa0baf
Always add :query-string to ring map, even when nil
KingMob Sep 18, 2023
467f76a
Move body back to header frame let
KingMob Sep 18, 2023
e449ce2
Replace server handler `complete`
KingMob Sep 18, 2023
9fdf1b9
Fixed missing header validation call
KingMob Sep 18, 2023
f6188c0
Add conn-ex helper fn, convert all to use ex helpers
KingMob Sep 18, 2023
c01d583
Improve handling of GOAWAY and RST_STREAM
KingMob Sep 18, 2023
4c5891c
Improve error handling
KingMob Oct 2, 2023
4eb6cf6
Refactor out common user event trigger handler
KingMob Oct 2, 2023
83d0bea
Refactor stream-ex to support public error messages
KingMob Oct 2, 2023
0ec4a5b
Server handler now sends a 400 resp for stream errors
KingMob Oct 2, 2023
67da7a6
Handle AsciiString directly in to-byte-buf
KingMob Oct 2, 2023
1b3a1d4
Only add debug handler when debug log level is set
KingMob Oct 3, 2023
e1f56f8
Fix bug where conn-ex-handler closed indiscrimantely
KingMob Oct 3, 2023
0f1facd
Consolidated H2 exception code betw server and client
KingMob Oct 3, 2023
30e792f
Flush in client-handler read-complete
KingMob Oct 3, 2023
8960435
Defer lookup of Compiler class loader until needed
KingMob Oct 3, 2023
f972047
Add status to status-based ex-info maps
KingMob Oct 4, 2023
e85f983
Update public error msgs to hide H2
KingMob Oct 4, 2023
7afb9a0
Refactored write-http-error-response
KingMob Oct 4, 2023
890d566
Fix bug in redirect tests
KingMob Oct 4, 2023
75e9e81
Fix bug in transport test that checks cert
KingMob Oct 4, 2023
ac49918
Fix ClassCastException bug when not using Http2Exceptions
KingMob Oct 4, 2023
9eb0123
Support :max-request-body-size in HTTP2 code
KingMob Oct 4, 2023
37543fb
Update request timeout test
KingMob Oct 6, 2023
2b4732e
Move idle handlers to netty ns
KingMob Oct 16, 2023
456aa8b
Update HTTP server docstrings
KingMob Oct 16, 2023
5a30b59
Fix idle timeout error
KingMob Oct 16, 2023
642bcbc
Fix bug caused by closing already-closed client chan
KingMob Oct 18, 2023
15a8a24
Fix bug in HTTP2 handling of client-pool
KingMob Oct 18, 2023
c24a073
Minor changes
KingMob Oct 18, 2023
023569f
Made some tests HTTP1
KingMob Oct 18, 2023
d91ccce
Expand pipeline transformation options
KingMob Oct 20, 2023
48c1548
Add tests for lower-level HTTP2 fns
KingMob Oct 21, 2023
8adefc5
Set default to HTTP/1 only
KingMob Oct 21, 2023
c61d6f1
Support backwards compatibility
KingMob Oct 21, 2023
f0a7234
Parity between HTTP1 and HTTP2 header retrieval
KingMob Oct 25, 2023
a181e12
Netty 4.1.100.Final
KingMob Oct 30, 2023
0ad1654
Add Brotli and Zstd deps to dev profile
KingMob Oct 31, 2023
9b201c0
Add testutils ns
KingMob Nov 1, 2023
4a5fc81
Add HTTP/2 compression support
KingMob Nov 1, 2023
ee4e626
Add profile... profile
KingMob Nov 3, 2023
5583d22
WIP on H2 examples
KingMob Nov 3, 2023
9a37528
Merge master into feature/http2-server
KingMob Nov 3, 2023
45dca06
Fix bug when using map for :ssl-context
KingMob Nov 3, 2023
996c6c2
Fix bugs in SSL cert ID tests
KingMob Nov 3, 2023
56360c8
Fix Clojure compiler bug with optional compression classes
KingMob Nov 4, 2023
36108d6
Add HTTP/2 examples
KingMob Nov 4, 2023
ec9e6a9
Bump deps
KingMob Nov 4, 2023
2eb16ba
Addressed feedback on self-signed cert language
KingMob Nov 6, 2023
f074c88
Address Arnaud's initial feedback
KingMob Nov 7, 2023
d19ef5b
Rename complete to destroy-conn?
KingMob Nov 7, 2023
d10e30e
Addressed Moritz's feedback
KingMob Nov 9, 2023
e1969aa
Updated project bouncycastle note
KingMob Nov 17, 2023
335875a
Address Moritz's feedback
KingMob Nov 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .envrc.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Set this to a local file for curl to write premaster secrets to for Wireshark
SSLKEYLOGFILE=
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ target/**
**/.clj-kondo/.cache
**/.lsp
/.eastwood
*.pem
75 changes: 75 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,81 @@ This document is a work in progress, so if there's anything you feel needs to be

We require a recent version of [Leiningen](https://leiningen.org/), and a minimum Java version of 8. Running the deps update script will require bash on your system. Other than that, we have no specific requirements.

### TLS/SSL

To develop against TLS, (effectively mandatory for HTTP/2+) it's helpful to install
your own root authority and certificates. The [mkcert](https://github.com/FiloSottile/mkcert) tool is ideal for that.
While a self-signed certificate will work, it's possible to run into warnings and
odd behavior.

#### Mkcert
An example setup:
```shell
# first check $JAVA_HOME is not empty, mkcert will use it to know where to install
echo $JAVA_HOME

# this is installs the root certificate authority (CA) for browsers/OS/Java
mkcert -install

# if you have multiple JVMs in use, you will need to install the CA for each one separately
export JAVA_HOME=/path/to/some/other/jdk
TRUST_STORES=java mkcert -install

# this will generate a cert file and a key file in .pem format
mkcert aleph.localhost localhost 127.0.0.1 ::1
# e.g., aleph.localhost+3.pem and aleph.localhost+3-key.pem
```

If you are using an HTTP tool with its own trust store, like Insomnia, you will
need to add the root CA to its trust store as well.

For Insomnia, it's hidden under the project dropdown in the top center, under
Collection Settings > Client Certificates > CA Certificate. (NB: you don't need
a client certificate, just the CA.)

For curl, you would run something like: `curl --cacert "$(mkcert -CAROOT)/rootCA.pem"`

Warning: As of August 2023, many tools still do not support HTTP/2: Postman,
HTTPie, RapidAPI/Paw, and many others.

#### DNS
You'll need to add `aleph.localhost` to your `/etc/hosts` file, e.g.:

```
127.0.0.1 aleph.localhost
::1 aleph.localhost
```

#### Aleph SslContext
Then, in code, generate an SslContext like:

```clojure
(aleph.netty/ssl-server-context
{:certificate-chain "/path/to/aleph.localhost+3.pem"
:private-key "/path/to/aleph.localhost+3-key.pem"
...})
```

#### Wireshark and curl

If you need to debug at the wire level, Wireshark is a powerful, but difficult
to use, tool. It supports TLS decryption, not via the use of certificates (which are
only a starting point), but by recording the actual TLS session keys to a file.

In curl, you can support this by adding an env var called `SSLKEYLOGFILE`, and in
Wireshark's Preferences > Protocols > TLS, set the "(Pre)-Master-Secret log
filename" to the same value. This is a bit of a pain to set up, but once done,
it's very useful.

You would then run something like:

```shell
curl --cacert "$(mkcert -CAROOT)/rootCA.pem" --http2-prior-knowledge --max-time 3 --tls-max 1.2 https://aleph.localhost:11256/
```

*Note* the `--tls-max 1.2`. In testing, it was required or else the session key
log file was empty.

## Testing

`lein test` should be run, and pass, before pushing up to GitHub.
Expand Down
28 changes: 14 additions & 14 deletions deps.edn
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,29 @@
org.clojure/tools.logging
{:mvn/version "1.2.4", :exclusions [org.clojure/clojure]},
manifold/manifold
{:mvn/version "0.3.0", :exclusions [org.clojure/tools.logging]},
org.clj-commons/byte-streams {:mvn/version "0.3.2"},
{:mvn/version "0.4.1", :exclusions [org.clojure/tools.logging]},
org.clj-commons/byte-streams {:mvn/version "0.3.4"},
org.clj-commons/dirigiste {:mvn/version "1.0.3"},
org.clj-commons/primitive-math {:mvn/version "1.0.0"},
org.clj-commons/primitive-math {:mvn/version "1.0.1"},
potemkin/potemkin {:mvn/version "0.4.6"},
io.netty/netty-transport {:mvn/version "4.1.94.Final"},
io.netty/netty-transport {:mvn/version "4.1.100.Final"},
io.netty/netty-transport-native-epoll$linux-x86_64
{:mvn/version "4.1.94.Final"},
{:mvn/version "4.1.100.Final"},
io.netty/netty-transport-native-epoll$linux-aarch_64
{:mvn/version "4.1.94.Final"},
{:mvn/version "4.1.100.Final"},
io.netty/netty-transport-native-kqueue$osx-x86_64
{:mvn/version "4.1.94.Final"},
{:mvn/version "4.1.100.Final"},
io.netty.incubator/netty-incubator-transport-native-io_uring$linux-x86_64
{:mvn/version "0.0.18.Final"},
io.netty.incubator/netty-incubator-transport-native-io_uring$linux-aarch_64
{:mvn/version "0.0.18.Final"},
io.netty/netty-codec {:mvn/version "4.1.94.Final"},
io.netty/netty-codec-http {:mvn/version "4.1.94.Final"},
io.netty/netty-codec-http2 {:mvn/version "4.1.94.Final"},
io.netty/netty-handler {:mvn/version "4.1.94.Final"},
io.netty/netty-handler-proxy {:mvn/version "4.1.94.Final"},
io.netty/netty-resolver {:mvn/version "4.1.94.Final"},
io.netty/netty-resolver-dns {:mvn/version "4.1.94.Final"},
io.netty/netty-codec {:mvn/version "4.1.100.Final"},
io.netty/netty-codec-http {:mvn/version "4.1.100.Final"},
io.netty/netty-codec-http2 {:mvn/version "4.1.100.Final"},
io.netty/netty-handler {:mvn/version "4.1.100.Final"},
io.netty/netty-handler-proxy {:mvn/version "4.1.100.Final"},
io.netty/netty-resolver {:mvn/version "4.1.100.Final"},
io.netty/netty-resolver-dns {:mvn/version "4.1.100.Final"},
metosin/malli
{:mvn/version "0.10.4", :exclusions [org.clojure/clojure]}},
:aliases
Expand Down
5 changes: 4 additions & 1 deletion examples/project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
[gloss "0.2.6"]
[metosin/reitit "0.5.18"]
[org.clojure/clojure "1.11.1"]
[org.clojure/core.async "1.6.673"]]
[org.clojure/core.async "1.6.673"]
;; necessary for self-signed cert example when not using OpenJDK
[org.bouncycastle/bcprov-jdk18on "1.75"]
[org.bouncycastle/bcpkix-jdk18on "1.75"]]
:plugins [[lein-marginalia "0.9.1"]
[lein-cljfmt "0.9.0"]])
108 changes: 108 additions & 0 deletions examples/src/aleph/examples/http2.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
(ns aleph.examples.http2
(:require
[aleph.http :as http]
[aleph.netty :as netty]
[clj-commons.byte-streams :as bs])
(:import
(java.util.zip
GZIPInputStream
InflaterInputStream)))

;; This file assumes you've already covered basic HTTP client/server usage
;; in aleph.examples.http. This file covers just HTTP/2 additions.

;; ## Servers

;; By default, you don't usually start up an HTTP/2-only server. In most
;; scenarios, the server will support multiple HTTP versions, and you don't
;; know which you need until the client connects. Instead, you
;; start up a general HTTP server with support for Application-Layer Protocol
;; Negotiation (ALPN), which negotiates the HTTP version during the TLS
;; handshake. Unlike HTTP/1, HTTP/2 effectively requires TLS.

;; For Aleph, this means you need to provide a `SslContext` to the server
;; with ALPN configured, and HTTP/2 available as a protocol.

(defn hello-world-handler
"A basic Ring handler which immediately returns 'hello world!'"
[_]
{:status 200
:headers {"content-type" "text/plain"}
:body "hello world!"})

(def http2-ssl-ctx
"This creates a self-signed certificate SslContext that supports both HTTP/2
and HTTP/1.1. The protocol array lists which protocols are acceptable, and
the order indicates the preference; in this example, HTTP/2 is preferred over
HTTP/1 if the client supports both.

NB: Avoid self-signed certs unless you control the clients, too. Browsers
will not accept them. See aleph.netty/ssl-server-context."
(netty/self-signed-ssl-context
"localhost"
{:application-protocol-config (netty/application-protocol-config [:http2 :http1])}))


(def s (http/start-server hello-world-handler
{:port 443
:ssl-context http2-ssl-ctx}))

;; ## Clients

;; Like the server, the client must specify which HTTP versions are acceptable.
;; Since connections are typically shared/reused between requests, the standard
;; way to do this is to set {:connection-options {:http-versions [:http2 :http1]}}
;; when setting up a connection-pool. At the moment, Aleph's default connection
;; pool is still HTTP/1-only, so you must specify a custom connection pool. This
;; will probably change in a future version of Aleph.

;; ### Basic H2 client

(def conn-pool
"Like with the ALPN config on the server, `:http-versions [:http2 :http1]`
specifies both what protocols are acceptable, and the order of preference.
Be warned, there is no guarantee a server will follow your preferred order,
even if it supports multiple protocols.

NB: `:insecure? true` is necessary for self-signed certs. Do not use in prod."
(http/connection-pool {:connection-options {:http-versions [:http2 :http1]
:insecure? true}}))

@(http/get "https://localhost:443" {:pool conn-pool})

(.close s)



;; ### Compression

;; server
(def s (http/start-server hello-world-handler
{:port 443
:ssl-context http2-ssl-ctx
:compression? true}))

;; client
;; TODO: add wrap-decompression middleware to handle this automatically
(let [acceptable-encodings #{"gzip" "deflate"}
resp @(http/get "https://localhost:443"
{:pool conn-pool
;; See https://www.rfc-editor.org/rfc/rfc9110#section-12.5.3
:headers {"accept-encoding" "gzip;q=0.8, deflate;q=0.5, *;q=0"}})
content-encoding (-> resp :headers (get "content-encoding"))
stream-ctor (case content-encoding
"gzip" #(GZIPInputStream. %)
"deflate" #(InflaterInputStream. %)
;; "br" #(BrotliInputStream. %) ; if you have brotli4j in your classpath
:unknown-encoding)]

(if (contains? acceptable-encodings content-encoding)
(do
(println "Decompressing" content-encoding "response")
(-> resp
;; remove/rename content-encoding header so nothing downstream tries to decompress again
(update :headers #(clojure.set/rename-keys % {"content-encoding" "orig-content-encoding"}))
:body
(stream-ctor)
bs/to-string))
resp))
37 changes: 28 additions & 9 deletions project.clj
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
;; you'll need to run the script at `deps/lein-to-deps` after changing any dependencies
(def netty-version "4.1.94.Final")
(def netty-version "4.1.100.Final")
(def brotli-version "1.12.0")


(defproject aleph (or (System/getenv "PROJECT_VERSION") "0.7.0-alpha2")
:description "A framework for asynchronous communication"
:url "https://github.com/clj-commons/aleph"
:license {:name "MIT License"}
:dependencies [[org.clojure/clojure "1.11.1"]
[org.clojure/tools.logging "1.2.4" :exclusions [org.clojure/clojure]]
[manifold "0.3.0" :exclusions [org.clojure/tools.logging]]
[org.clj-commons/byte-streams "0.3.2"]
[manifold "0.4.1" :exclusions [org.clojure/tools.logging]]
[org.clj-commons/byte-streams "0.3.4"]
[org.clj-commons/dirigiste "1.0.3"]
[org.clj-commons/primitive-math "1.0.0"]
[org.clj-commons/primitive-math "1.0.1"]
[potemkin "0.4.6"]
[io.netty/netty-transport ~netty-version]
[io.netty/netty-transport-native-epoll ~netty-version :classifier "linux-x86_64"]
Expand All @@ -31,19 +33,35 @@
[org.slf4j/slf4j-simple "1.7.30"]
[com.cognitect/transit-clj "1.0.324"]
[spootnik/signal "0.2.4"]
;; This is for self-generating certs for testing ONLY:
[org.bouncycastle/bcprov-jdk18on "1.72"]
[org.bouncycastle/bcpkix-jdk18on "1.72"]]
;; This is for dev and testing ONLY, not recommended for prod
[org.bouncycastle/bcprov-jdk18on "1.75"]
[org.bouncycastle/bcpkix-jdk18on "1.75"]
;;[org.bouncycastle/bctls-jdk18on "1.75"]
[io.netty/netty-tcnative-boringssl-static "2.0.61.Final"]
;;[com.aayushatharva.brotli4j/all ~brotli-version]
[com.aayushatharva.brotli4j/brotli4j ~brotli-version]
[com.aayushatharva.brotli4j/service ~brotli-version]
[com.aayushatharva.brotli4j/native-linux-aarch64 ~brotli-version]
[com.aayushatharva.brotli4j/native-linux-armv7 ~brotli-version]
[com.aayushatharva.brotli4j/native-linux-x86_64 ~brotli-version]
[com.aayushatharva.brotli4j/native-osx-aarch64 ~brotli-version]
[com.aayushatharva.brotli4j/native-osx-x86_64 ~brotli-version]
[com.aayushatharva.brotli4j/native-windows-x86_64 ~brotli-version]
[com.github.luben/zstd-jni "1.5.5-7"]]
:jvm-opts ["-Dorg.slf4j.simpleLogger.defaultLogLevel=debug"
"-Dorg.slf4j.simpleLogger.showThreadName=false"
"-Dorg.slf4j.simpleLogger.showThreadId=true"
"-Dorg.slf4j.simpleLogger.showLogName=false"
"-Dorg.slf4j.simpleLogger.showShortLogName=true"
"-Dorg.slf4j.simpleLogger.showDateTime=true"]}
"-Dorg.slf4j.simpleLogger.showDateTime=true"
"-Dorg.slf4j.simpleLogger.log.io.netty.util=error"
"-Dorg.slf4j.simpleLogger.log.io.netty.channel=warn"]}
:test {:jvm-opts ["-Dorg.slf4j.simpleLogger.defaultLogLevel=off"]}
:leak-level-paranoid {:jvm-opts ["-Dio.netty.leakDetectionLevel=PARANOID"]}
:pedantic {:pedantic? :abort}
:trace {:jvm-opts ["-Dorg.slf4j.simpleLogger.defaultLogLevel=trace"]}}
:trace {:jvm-opts ["-Dorg.slf4j.simpleLogger.defaultLogLevel=trace"]}
:profile {:dependencies [[com.clojure-goes-fast/clj-async-profiler "1.1.1"]]
:jvm-opts ["-Djdk.attach.allowAttachSelf"]}}
:java-source-paths ["src-java"]
:test-selectors {:default #(not
(some #{:benchmark :stress}
Expand All @@ -54,6 +72,7 @@
:jvm-opts ^:replace ["-server"
"-Xmx2g"
"-XX:+HeapDumpOnOutOfMemoryError"
"-XX:+PrintCommandLineFlags"
#_"-XX:+PrintCompilation"
#_"-XX:+UnlockDiagnosticVMOptions"
#_"-XX:+PrintInlining"]
Expand Down
4 changes: 2 additions & 2 deletions src-java/aleph/http/AlephChannelInitializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
import io.netty.channel.ChannelInitializer;

public class AlephChannelInitializer extends ChannelInitializer<Channel> {
KingMob marked this conversation as resolved.
Show resolved Hide resolved

private final IFn chanBuilderFn;

public AlephChannelInitializer(IFn chanBuilderFn) {
this.chanBuilderFn = chanBuilderFn;
}
Expand Down
42 changes: 42 additions & 0 deletions src-java/aleph/http/AlephCompressionOptions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package aleph.http;

import io.netty.handler.codec.compression.BrotliOptions;
import io.netty.handler.codec.compression.DeflateOptions;
import io.netty.handler.codec.compression.GzipOptions;
import io.netty.handler.codec.compression.SnappyOptions;
import io.netty.handler.codec.compression.StandardCompressionOptions;
import io.netty.handler.codec.compression.ZstdOptions;

/**
* {@link AlephCompressionOptions} exists because the Clojure compiler cannot
* distinguish between static fields and static methods without reflection.
*
* This is a problem when using Netty's StandardCompressionOptions, because
* reflection triggers a load of all the methods referencing optional classes,
* which may not exist in the classpath, resulting in a ClassNotFoundException.
*/
public class AlephCompressionOptions {
private AlephCompressionOptions() {
// Prevent outside initialization
}

public static BrotliOptions brotli() {
return StandardCompressionOptions.brotli();
}

public static ZstdOptions zstd() {
return StandardCompressionOptions.zstd();
}

public static SnappyOptions snappy() {
return StandardCompressionOptions.snappy();
}

public static GzipOptions gzip() {
return StandardCompressionOptions.gzip();
}

public static DeflateOptions deflate() {
return StandardCompressionOptions.deflate();
}
}
Loading