-
Notifications
You must be signed in to change notification settings - Fork 240
HTTP/2 server #687
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
Merged
Merged
HTTP/2 server #687
Changes from 101 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 b67c250
Re-indent safe-execute as a body macro
KingMob 1deac6e
More cleanup of docstring table
KingMob 9070415
Add ALPN support to server SslContexts
KingMob 21e9dbd
Move http2 pipeline setup to a.h.http2 ns
KingMob 02095f2
Setup conn-level pipeline
KingMob 2bd5198
Replaced slow, ad hoc date formatting with Netty fns
KingMob b3338de
Move add-non-http-handlers to common ns
KingMob 3a1a149
Minor refactoring and docstrings
KingMob 70fad2c
Move date-related code and server name to a.h.common
KingMob 4e7cd03
Fix unnecessary continue-executor shutdown
KingMob 2bda782
Simplified common header generation
KingMob c5c143c
Update server params for setup-http1-pipeline
KingMob 87a3411
Update and fix HTTP/2 header handling
KingMob 1e98ffa
First pass at HTTP2 server code
KingMob 463b424
Ignore .pem files
KingMob f16147e
WIP
KingMob 3a03056
Fix bug confusing conn chan with outbound chan
KingMob 97fda5c
Update contrib instructions for using TLS
KingMob b748c92
Minor cleanup
KingMob a35226a
Fix issue with byte-streams.graph.Type loaded by different ClassLoaders
KingMob 7ad1b8c
Update TLS return type hints
KingMob 23503a1
Switch to BoringSSL for local dev
KingMob ded4f0f
Add a lot of logging
KingMob 275cd30
Update comments and commented server examples
KingMob 04eee02
Log exceptions in send-response
KingMob 18f4ec6
Add type hint on te-header-name for .equals
KingMob 877f7ad
Convert :scheme pseudo-header to string
KingMob 787f40f
Close the circuit - http2 server now sending
KingMob 35c6093
Update project.clj
KingMob 21e4b44
Fix NPE bug when ALPN not used
KingMob 02ac0a8
Reset ALPN fallback protocol to HTTP/1
KingMob ed61b85
Moved server-test to common-test
KingMob 30feb0a
Minor reformatting and aleph.http comment example update
KingMob 4522f13
Refactor existing HTTP tests in prep for http2
KingMob 01f0cbc
Alter final pipeline error handling
KingMob 5230389
Revert reject handler to only being invoked on executor rejection
KingMob 30e4f91
First pass at adding HTTP2 testing
KingMob 472254f
Improve pr support for AsciiStrings
KingMob 7f9ad2a
Switch to using Http2Exception/StreamException in client
KingMob b155a4a
Minor doc updates
KingMob cc0ebc4
Add :protocol to http1 ring request maps
KingMob e4b6b17
Convert util fns to use ChannelOutboundInvoker
KingMob 522c275
Update add-exception-handler to close and not propagate
KingMob 72d4ae1
If client-handler's channel goes inactive, set (or try to) complete t…
KingMob 9969937
Add stream-ex helper fn
KingMob 41c6f9e
Add :channel-read-complete to server handler
KingMob 2c708dc
Add go-away fn
KingMob 71cbb3e
Add header validation and status parsing
KingMob 3cc3ca1
Update imports
KingMob caa0baf
Always add :query-string to ring map, even when nil
KingMob 467f76a
Move body back to header frame let
KingMob e449ce2
Replace server handler `complete`
KingMob 9fdf1b9
Fixed missing header validation call
KingMob f6188c0
Add conn-ex helper fn, convert all to use ex helpers
KingMob c01d583
Improve handling of GOAWAY and RST_STREAM
KingMob 4c5891c
Improve error handling
KingMob 4eb6cf6
Refactor out common user event trigger handler
KingMob 83d0bea
Refactor stream-ex to support public error messages
KingMob 0ec4a5b
Server handler now sends a 400 resp for stream errors
KingMob 67da7a6
Handle AsciiString directly in to-byte-buf
KingMob 1b3a1d4
Only add debug handler when debug log level is set
KingMob e1f56f8
Fix bug where conn-ex-handler closed indiscrimantely
KingMob 0f1facd
Consolidated H2 exception code betw server and client
KingMob 30e792f
Flush in client-handler read-complete
KingMob 8960435
Defer lookup of Compiler class loader until needed
KingMob f972047
Add status to status-based ex-info maps
KingMob e85f983
Update public error msgs to hide H2
KingMob 7afb9a0
Refactored write-http-error-response
KingMob 890d566
Fix bug in redirect tests
KingMob 75e9e81
Fix bug in transport test that checks cert
KingMob ac49918
Fix ClassCastException bug when not using Http2Exceptions
KingMob 9eb0123
Support :max-request-body-size in HTTP2 code
KingMob 37543fb
Update request timeout test
KingMob 2b4732e
Move idle handlers to netty ns
KingMob 456aa8b
Update HTTP server docstrings
KingMob 5a30b59
Fix idle timeout error
KingMob 642bcbc
Fix bug caused by closing already-closed client chan
KingMob 15a8a24
Fix bug in HTTP2 handling of client-pool
KingMob c24a073
Minor changes
KingMob 023569f
Made some tests HTTP1
KingMob d91ccce
Expand pipeline transformation options
KingMob 48c1548
Add tests for lower-level HTTP2 fns
KingMob 8adefc5
Set default to HTTP/1 only
KingMob c61d6f1
Support backwards compatibility
KingMob f0a7234
Parity between HTTP1 and HTTP2 header retrieval
KingMob a181e12
Netty 4.1.100.Final
KingMob 0ad1654
Add Brotli and Zstd deps to dev profile
KingMob 9b201c0
Add testutils ns
KingMob 4a5fc81
Add HTTP/2 compression support
KingMob ee4e626
Add profile... profile
KingMob 5583d22
WIP on H2 examples
KingMob 9a37528
Merge master into feature/http2-server
KingMob 45dca06
Fix bug when using map for :ssl-context
KingMob 996c6c2
Fix bugs in SSL cert ID tests
KingMob 56360c8
Fix Clojure compiler bug with optional compression classes
KingMob 36108d6
Add HTTP/2 examples
KingMob ec9e6a9
Bump deps
KingMob 2eb16ba
Addressed feedback on self-signed cert language
KingMob f074c88
Address Arnaud's initial feedback
KingMob d19ef5b
Rename complete to destroy-conn?
KingMob d10e30e
Addressed Moritz's feedback
KingMob e1969aa
Updated project bouncycastle note
KingMob 335875a
Address Moritz's feedback
KingMob File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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,2 @@ | ||
# Set this to a local file for curl to write premaster secrets to for Wireshark | ||
SSLKEYLOGFILE= |
This file contains hidden or 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 |
---|---|---|
|
@@ -15,3 +15,4 @@ target/** | |
**/.clj-kondo/.cache | ||
**/.lsp | ||
/.eastwood | ||
*.pem |
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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,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)) |
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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 @@ | ||
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(); | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.