forest
Version, currently 0.1.02 versions
- 0.1.1latestJan 31, 2021
- 0.1.0not indexedFeb 1, 2021
github.com/636f7374/forest.cr
⛵️ Available - Crystal HTTP2 Protocol Client and Server
12 stars
0 dependents
License: MIT
Nothing has been indexed for 0.1.0 yet. The tag is recorded, its shard.yml has not been read, so the manifest and dependency list below are empty because they are unknown rather than because they are absent.
Installation
# Add this to your shard.yml
dependencies:
forest:
github: 636f7374/forest.cr
version: ~> 0.1.0Then run:
shards installshard.yml
No shard.yml has been indexed for 0.1.0. You can read it on the repository.
Dependencies
Unknown: the shard.yml for this version has not been read yet.
README
This README is the one indexed from the repository at its latest ref, not from the tag for this version.
<div align = "center"><img src="images/icon.png" width="256" height="256" /></div>
<div align = "center">
<h1>Forest.cr - HTTP2 Client and Server</h1>
</div>
<p align="center">
<a href="https://crystal-lang.org">
<img src="https://img.shields.io/badge/built%20with-crystal-000000.svg" /></a>
<a href="https://github.com/636f7374/forest.cr/actions">
<img src="https://github.com/636f7374/forest.cr/workflows/Continuous%20Integration/badge.svg" /></a>
<a href="https://github.com/636f7374/forest.cr/releases">
<img src="https://img.shields.io/github/release/636f7374/forest.cr.svg" /></a>
<a href="https://github.com/636f7374/forest.cr/blob/master/license">
<img src="https://img.shields.io/github/license/636f7374/forest.cr.svg"></a>
</p>
## Description
* Since Crystal language lacks a perfect HTTP2 implementation, we implemented it.
* We spent some time to do this, it is not very easy.
* We started looking at [many documents](#references) and started researching how to build a HTTP2 server.
* In the `Hpack`, `Huffman` part, we reference to the design of [ysbaddaden](https://github.com/ysbaddaden).
* Channel design (ConnectionPool) is used inside HTTP2 server.
* It currently supports most HTTP2 flow control features (excluding priority).
* It can currently be perfectly combined with HTTP1 server.
* Including `Chunked`, `Compress`, and `Empty body`, ...
* Currently it needs to be regularly synchronized with Crystal upstream.
* Some monkey patches were used at the junction (E.g. `Server::RequestProcessor`, `Server::Response`).
* Currently only supports up to Crystal `0.36`.
## Features
* [X] Basic HTTP2 server features.
* [X] HTTP Server compatibility (HTTP1 & HTTP2).
* [X] Simplify the complex, Clear code syntax.
* [ ] HTTP2 client feature.
* [ ] More Spec tests.
* [ ] More Contributions.
## Test Information
* h2load
```text
$ h2load -n 100000 -c 100 -t 1 -T 5 -m 10 -H 'Accept-Encoding: gzip,deflate' https://127.0.0.1:9876
starting benchmark...
spawning thread #0: 100 total client(s). 100000 total requests
TLS Protocol: TLSv1.3
Cipher: TLS_AES_256_GCM_SHA384
Server Temp Key: ECDH P-256 256 bits
Application protocol: h2
progress: 10% done
progress: 20% done
progress: 30% done
progress: 40% done
progress: 50% done
progress: 60% done
progress: 70% done
progress: 80% done
progress: 90% done
progress: 100% done
finished in 12.11s, 8255.80 req/s, 508.46KB/s
requests: 100000 total, 100000 started, 100000 done, 100000 succeeded, 0 failed, 0 errored, 0 timeout
status codes: 100000 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 6.01MB (6306700) total, 1.24MB (1300000) headers (space savings 71.74%), 3.05MB (3200000) data
min max mean sd +/- sd
time for request: 27.49ms 3.00s 105.87ms 165.93ms 99.04%
time for connect: 45.34ms 2.89s 1.47s 831.38ms 58.00%
time to 1st byte: 2.96s 3.08s 3.02s 32.89ms 58.00%
req/s : 82.57 83.63 82.95 0.34 74.00%
```
* Curl
```text
$ curl -v "https://127.0.0.1:9876" --insecure
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 9876 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/cert.pem
CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
* subject: C=FI; ST= ; L= ; O= ; OU= ; CN=Finland; emailAddress=
* start date: Jun 30 08:22:14 2019 GMT
* expire date: Jun 29 08:22:14 2021 GMT
* issuer: C=FI; ST= ; L= ; O= ; OU= ; CN=Finland; emailAddress=
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fde8580dc00)
> GET / HTTP/2
> Host: 127.0.0.1:9876
> User-Agent: curl/7.64.1
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
< HTTP/2 200
< content-length: 12
<
* Connection #0 to host 127.0.0.1 left intact
Hello World!
* Closing connection 0
```
## Multithreading (Parallel)
* Crystal enabling `-Dpreview_mt` will cause a lot of `failed` in h2load.
* This will increase the speed by `1x`, this problem needs to be resolved.
```text
$ h2load -n 100000 -c 100 -t 1 -T 5 -m 10 -H 'Accept-Encoding: gzip,deflate' https://127.0.0.1:9876
starting benchmark...
spawning thread #0: 100 total client(s). 100000 total requests
TLS Protocol: TLSv1.3
Cipher: TLS_AES_256_GCM_SHA384
Server Temp Key: ECDH P-256 256 bits
Application protocol: h2
progress: 10% done
progress: 20% done
progress: 30% done
progress: 40% done
progress: 50% done
progress: 60% done
progress: 70% done
progress: 80% done
finished in 5.51s, 14877.00 req/s, 916.71KB/s
requests: 100000 total, 82180 started, 82000 done, 82000 succeeded, 18000 failed, 18000 errored, 0 timeout
status codes: 82018 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 4.93MB (5174068) total, 1.02MB (1066234) headers (space savings 71.74%), 2.50MB (2624000) data
min max mean sd +/- sd
time for request: 105us 970.27ms 46.09ms 95.82ms 90.93%
time for connect: 53.03ms 789.04ms 413.19ms 219.45ms 60.00%
time to 1st byte: 785.89ms 1.20s 872.68ms 84.87ms 89.02%
req/s : 0.00 254.78 163.72 78.86 79.00%
```
## Usage
* Need to be used with [Cherry.cr](https://github.com/636f7374/cherry.cr) (load certificate / private key via Text)
```crystal
require "forest"
require "cherry"
context = OpenSSL::SSL::Context::Server.new
context.ca_certificate_text = Base64.decode_string "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUpsVENDQlgyZ0F3SUJBZ0lKQU5paVYrR0YzaHM2TUEwR0NTcUdTSWIzRFFFQkN3VUFNR0V4Q3pBSkJnTlYKQkFZVEFrWkpNUW93Q0FZRFZRUUlEQUVnTVFvd0NBWURWUVFIREFFZ01Rb3dDQVlEVlFRS0RBRWdNUW93Q0FZRApWUVFMREFFZ01SQXdEZ1lEVlFRRERBZEdhVzVzWVc1a01SQXdEZ1lKS29aSWh2Y05BUWtCRmdFZ01CNFhEVEU1Ck1EWXpNREE0TWpJeE5Gb1hEVEl4TURZeU9UQTRNakl4TkZvd1lURUxNQWtHQTFVRUJoTUNSa2t4Q2pBSUJnTlYKQkFnTUFTQXhDakFJQmdOVkJBY01BU0F4Q2pBSUJnTlZCQW9NQVNBeENqQUlCZ05WQkFzTUFTQXhFREFPQmdOVgpCQU1NQjBacGJteGhibVF4RURBT0Jna3Foa2lHOXcwQkNRRVdBU0F3Z2dRaU1BMEdDU3FHU0liM0RRRUJBUVVBCkE0SUVEd0F3Z2dRS0FvSUVBUUQrOFE0ODJwOVYxMVVsZXVqYndZQWpHd1RXMXVWaS9SVFk5d3lxZ2JQOHBLbGkKOWkrRVpJckNTUllZaWlxRnFGTUdKQnFuTi9VNGNYZk95elp1SEh2bUYybGVQTkZ1cFBxcDlNUHVUcGlHbEpHZQplMVRZeVlaTTNSVU1VMk1UZHVZVzl6dzdKSURLOTM5VThhbjFYZlRMR3E0R0NMV1c3MENTdTRZQjVLby9SZkcwCnp4UkRVaVZwOWJpZ3FGdzBESkZWTFo3b05MMFltQW42dlg2eGIvWmxnV0RkTGFBZHI0L1BhL3RNM1Z1dzRoTDYKQnF4S0kySGRheHFOUnh6ZFhXOVhoVXJtbkNTU1oyNmVWbGhGUVM2QklQTlVtZng1aWlwZ3Y3Tks5cEVYbUpIeApUb1ljTzBScGhJVllhY1hmMGhKejJmZmJJZ0lWekxNRWIveXMvZFNwQUdIZEYxK3hiYUFaM3dQZTJvcm5OQ0F0CnlKSXltRXZ0Vjlmb09TVTJ1RWZKOUlWZ2NuRW56eWl2Z2tQaDBuc0JMc0RWaW9KYUUzVHhRZlBzbmdBZ2QwdGIKMXpianRWVXc0MGN0UmxQak9XM2phb2ROdGYwd0pYZ3RjTHFncDVCVWlNZGJ0NHIxMnFTSVc3akhTSUd4blRsVgo3aWo3YnNTZkRVb29QaW5CVmhXYUlBS0ZCUzh3SzJrUEk4TnM5bVZvNVc0M0Vra2F2ZnN2dUhYZkZVSFhSMFBxCnh2SGE3cU56SnBNc0cvMG1heDN6eFpIWUEyL1B4MERySjNDOXBnb2U4UE5vLytQdk1qS2tESkFPN3I0UmN3UlYKNlJCYWFXS1duS3pYN05LYWNML3IwT2pSQkVBWUttQTNzSkRTUDNPeW8yVmFnTHhPUWp0dTlKZlNjMUNacTlIcQpPRkFKWm5DWGYvaG9ESWJtQ2tyOEg0V3lPL21WRzdzYTRFZ2cvbHF5VnBmdDh2RlpHN1VRenBnZUUycHkwcnhTClFVOXBLeU94dUczc1pxb0hWYS9PYWdIZzh0bE5CaXp3UjhZVDFWTW1rL2FXQ3hGNm5TNDdkdS8zKzNKczZCQk4KNzlPdGtXQzQrcEdscnp3M2dXbW1weEdZdEQ0L2hVY2ZnSysrR2tJd1RQVE1xU1g1K0d0OThtL09kT2FkQWhwZgplSXNZMDQ4U1d4UkhGQVdGbVQ1OE53MEpHbXRpa2hESjE0SmloMVNFRDdhUEp0ZmNiWThwREk0RUY0S3FXTUxlCkZkN0pMQVN6Y2h3TSttY1hzWFVhQVhXOTBONnpFWmkwUEMzYk9zc0FSNnp0TWZ0SUZUb2dKVFJLUCs5cGk5T2QKUmZmeVNGTlFpUHhlaEdoTktldG9ENkdaYlhIUllXRm5HYlh1NlNHTmlabnhEUnZJTDVPRlc3bkthR1ZTZTRoRApmUjRIencxU1RoYmJaLzR1dFJlOEFoRmRFTWMrMVp4M1lmRnV2LzZBWWd0MXVYTUJ2WEpSbFd6L0ZOSGR2cnI3Clc5TGdOaVRId2ZTUm10b3VLcXdKNEdKMmc1VDhsY0pRVU5oWXg3aWk0QzF6MFQwVjlNVko2QzdjcnplTlM5WlkKdUdLUExpL2JTWkVyY2V1eHF4anBFUE9EUzRJaHJnd08xSEJwSmJ4Rjg3YVhEdlJkSlFSVUlsRXBHSFNrTzJ5OQpkVHVqUEFYZEF6L0J1WW4vVzdUNTVWcGpNMVdDbjkzL212MjA3cTFDSnZONXpUOWs3WHl2RUpialAwYVhTTW1jClhETWpmZWhPa0l4eVplZHFNZWErdlVRVisxeHVuOUxLTDNhckF6UXBBZ01CQUFHalVEQk9NQjBHQTFVZERnUVcKQkJUQmhROUd0R2xVRkVla2xqaVJKc1lRZjRaT1BUQWZCZ05WSFNNRUdEQVdnQlRCaFE5R3RHbFVGRWVrbGppUgpKc1lRZjRaT1BUQU1CZ05WSFJNRUJUQURBUUgvTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElFQVFCQ05idDZOZDdVCjlHZ0dCbGtLREFEbk9TRGE0dVlmbnd4VHd6cS94c01wTTB1a2dUelpNdjVLYmFQY2hsWkMzZVpFLzU4VXNyU1QKdnF2WXBIOFUyVUhReDRVcExuY215ckVYdGxvampHOTN1ZWpWUVBPTnhHbEdlRHVRMGgzekRnVWtjNnl6MVc1KwpDZlpSTGplcm5PbDFSWFJRY2c0OTY2WGhHU3NjUmV1ZVYraDVqRlE4eE15T0dmckNTVFJZcUNyK2hrd3hvM2NTCmpLTEJNSFJKZ2JqYVpGbFczRTFDNnZhZzFtRG9SMWRobUpZVjgwbWFXM1pwbmdybHJQUnpNenJCSmFYVmIwN1gKR0Z4MU1ST0NtREMya2lkdmQvWXRrckQ1ZE9XZXJBQWc4VGY0TlBMeFBRWldjMHljMUlrR1ZUYVF0MVh3T0pDVwpJMXVTbWhpVWFtdlcyK3d1TEdEWUtDcS8yR3oySVVxZjRqOGgyWUNWYUlVRSsyR3psRGpsazlSb21tdXBrR1hvCjlRZ3ZqZi9kaDd5NEptNDNURE9Zb2xyeEpOT203SWNpdVJqZnl0ZlZWRnZvaEttRktMNmZTN296T1hCRnpUcHMKclNXOWxYN0FjZWsyM1dIZzRBc1lCY3NIbzAzTldlcmFvVFBleVZSLy9Qc2lETzlUUy8xOVJBdVpCZnNGemZZMAo1TVNXcFpYM0g3MXBMUURMdGVjVnZDeVdxemN6elNGcHl3dmhZbGJUWFgyZGl4QmRuTEZpWFJkWmhKd3lFQmJXCldsWTNIdDV1Ny85c1BEUW42ZStIWGwxYlEwNkVXN1ppTmJWbUNvdHdMOWFDN2dtdHVqeEFTQnNZWnNmRnd0WHAKd0FwT2ZNSGtrZmxuNFBpc2FXT0gzelFNWEdQZTBmTEp6bFRXTlV5ZGxSS0JPY2I0QkNlK0hRQWZiekM4eVNXcgp0NFdHbWlYdkRvYmkrWVhXT3FwcFhOQWpZQXZEd1l1ZC9OT3o5V1VHc1JwQ3ZDbTNKNXpxUHEreE5xc0VEVndLCmEyZVR6Y2ZmTGhEZmFmRjg0b1hYKy92OFplYWZicDBnMjlYdVVtQnM2YnZud0YvMVMwTU5OYi9reEVsR3QrdzQKWE4vNFVybzcwcHIxSVRQQmxIT2R0VGQ5QkVpeDZ1SEgxQ1Z4eHQxMUxlT2x1bk9JdllOcUlqcmNtT1pWaHJJSwphOWZpMWlqZHdPT09ENFhLdW9sVEo2dVZiR3ppS0ljVmNqTU1NYjAzZUx5ZjZUNS95bGtUeVV5UzZPaysrMDdLCjBHWjkyb2xxT012U04yQ3c3TkR3S1FaOW0zMmk1WG5yZVNBeEszcmg2aDVZTkdnNXlyTkJCYWxMZTloTUZVVjkKaDdKMUxUY0c2QXNUU3BzbnJjcno1cyt5MEd5c0V2YlI1Tm4rZWdDWXBZZEZxa3BDYVQwN2VMcnk5WUVaODRKRgp2amNGV2hmSnlTaG5wWXhRaVJzN2dwRWlVcDd6cDFZbW43MWpvR0FpejhJZDVNNEJsOWZ0YXZRQWY2eDM2RUEyCkZjdU9ROEc4ZSt3Q1FyR2tMT1JTZVlYRkhYVTVhVk8xVXJpWElIVzF6ZU55MGNRajBvR2czU2JYSVAwRVJVSC8KdkxHc1YwYWFoaHBONjFTSW9RcEdkNnFYODVhLzZTdjVUZ1BoMXRFcTRGQTlHM0cxeFVyVTBnWTJHWWlpWDg5RgptWWtUbUd0bEhoUFFhQU8ySHhadmJxYVlnMXZtWFZFSlRJajRBZmpoR0VoeER3bEdFMUJGRUc1TFNCakd1d2RFClhYZTRBc3U2ZDFxVwotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg=="
context.private_key_text = Base64.decode_string "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlTSndJQkFBS0NCQUVBL3ZFT1BOcWZWZGRWSlhybzI4R0FJeHNFMXRibFl2MFUyUGNNcW9Hei9LU3BZdll2CmhHU0t3a2tXR0lvcWhhaFRCaVFhcHpmMU9IRjN6c3MyYmh4NzVoZHBYanpSYnFUNnFmVEQ3azZZaHBTUm5udFUKMk1tR1ROMFZERk5qRTNibUZ2YzhPeVNBeXZkL1ZQR3A5VjMweXhxdUJnaTFsdTlBa3J1R0FlU3FQMFh4dE04VQpRMUlsYWZXNG9LaGNOQXlSVlMyZTZEUzlHSmdKK3IxK3NXLzJaWUZnM1MyZ0hhK1B6MnY3VE4xYnNPSVMrZ2FzClNpTmgzV3NhalVjYzNWMXZWNFZLNXB3a2ttZHVubFpZUlVFdWdTRHpWSm44ZVlvcVlMK3pTdmFSRjVpUjhVNkcKSER0RWFZU0ZXR25GMzlJU2M5bjMyeUlDRmN5ekJHLzhyUDNVcVFCaDNSZGZzVzJnR2Q4RDN0cUs1elFnTGNpUwpNcGhMN1ZmWDZEa2xOcmhIeWZTRllISnhKODhvcjRKRDRkSjdBUzdBMVlxQ1doTjA4VUh6N0o0QUlIZExXOWMyCjQ3VlZNT05ITFVaVDR6bHQ0MnFIVGJYOU1DVjRMWEM2b0tlUVZJakhXN2VLOWRxa2lGdTR4MGlCc1owNVZlNG8KKzI3RW53MUtLRDRwd1ZZVm1pQUNoUVV2TUN0cER5UERiUFpsYU9WdU54SkpHcjM3TDdoMTN4VkIxMGRENnNieAoydTZqY3lhVExCdjlKbXNkODhXUjJBTnZ6OGRBNnlkd3ZhWUtIdkR6YVAvajd6SXlwQXlRRHU2K0VYTUVWZWtRCldtbGlscHlzMSt6U21uQy82OURvMFFSQUdDcGdON0NRMGo5enNxTmxXb0M4VGtJN2J2U1gwbk5RbWF2UjZqaFEKQ1dad2wzLzRhQXlHNWdwSy9CK0ZzanY1bFJ1N0d1QklJUDVhc2xhWDdmTHhXUnUxRU02WUhoTnFjdEs4VWtGUAphU3Nqc2JodDdHYXFCMVd2em1vQjRQTFpUUVlzOEVmR0U5VlRKcFAybGdzUmVwMHVPM2J2OS90eWJPZ1FUZS9UCnJaRmd1UHFScGE4OE40RnBwcWNSbUxRK1A0VkhINEN2dmhwQ01FejB6S2tsK2ZocmZmSnZ6blRtblFJYVgzaUwKR05PUEVsc1VSeFFGaFprK2ZEY05DUnByWXBJUXlkZUNZb2RVaEErMmp5YlgzRzJQS1F5T0JCZUNxbGpDM2hYZQp5U3dFczNJY0RQcG5GN0YxR2dGMXZkRGVzeEdZdER3dDJ6ckxBRWVzN1RIN1NCVTZJQ1UwU2ovdmFZdlRuVVgzCjhraFRVSWo4WG9Sb1RTbnJhQStobVcxeDBXRmhaeG0xN3VraGpZbVo4UTBieUMrVGhWdTV5bWhsVW51SVEzMGUKQjg4TlVrNFcyMmYrTHJVWHZBSVJYUkRIUHRXY2QySHhici8rZ0dJTGRibHpBYjF5VVpWcy94VFIzYjY2KzF2Uwo0RFlreDhIMGtacmFMaXFzQ2VCaWRvT1UvSlhDVUZEWVdNZTRvdUF0YzlFOUZmVEZTZWd1M0s4M2pVdldXTGhpCmp5NHYyMG1SSzNIcnNhc1k2UkR6ZzB1Q0lhNE1EdFJ3YVNXOFJmTzJsdzcwWFNVRVZDSlJLUmgwcER0c3ZYVTcKb3p3RjNRTS93Ym1KLzF1MCtlVmFZek5WZ3AvZC81cjl0TzZ0UWliemVjMC9aTzE4cnhDVzR6OUdsMGpKbkZ3egpJMzNvVHBDTWNtWG5hakhtdnIxRUZmdGNicC9TeWk5MnF3TTBLUUlEQVFBQkFvSUVBUUM3QW9TWkt4MjZVRXpMClE0L1FzKzZVMGRzSTVYWTYyTDhVTUpULzlramJTTVpnSzRyTHFSMElTNmlEczhaaGFRb045U29BQTlKRDV5Z2wKYjNlcjZnVVEwWmVmWXltVjZqdGR0SWlOSk9aSndtM1hQVTBPQVRZYzZBZnFsTGlXcko4M3RZQmZPZlduN1VsZwpQQzJhS2FQSjRQWkt3dFRCdFJzL0I0UFRtN011MnRYazlnbzlIK01HQ1JPMzlnZzh2Z05WNGpNd3pvN3ZuWWVrCmdLQ1E5RHBnVnptQXhWa3dyWG5tZzZWQnl4YlpkOXpIdjJGZXVQbXUvRVByNG9CUCtad1ZMVmUyTmsrMWZWM3QKbEJVSUtEbyt5cmIwRmtqWHR2eERJQndiSHlkcmthVnN4MWNsR215aW9tMVdYN0NnOEc1TXdWVkpUM2NNR3E0dQowUjhlbnN3Q2RKOVZHVEkrNnRXSVpNbG9EaFBhYWFnNUxXbmc1MHE2L2JjSlIvSCtZOHQxWDRML0xyUEdxZldFCldTQUdaT21LQW91OW1PN3B1R0FPSVgwVzB3Znd5TkZrdTBndVhQUHkrcVZabHI4dWJSQW94Qm9nYlNFZTBqMkgKeDZ0KzhhdXo5dW1XWTlyeFljTlRxMFN1R29mWWpDWmszR0QvbjA5b0JNMmpHNFp4cGY0T292QjJOMGxZSWwvYwpsVFZqbHBMcEVYTjV2bFlWNGNxQ1JPTmlFeXZMQ1NITzlNU3cvbUN6dFZZOEF3UDl6SkdhSWhGTHphbVZWdXBPCkZRNWtiNG41REhMaFVPUVlzRS9wZXJXcDNvTmFOVzYydmxJYW9EZUxsNzVLWGhSVzZlSSt6MjRZOU84M1NzNXQKeTMxUVhPODMyUmdkL1ZVa2F2MUI5UFh4a0ZsTmZ2K2RqMWs2Zi9YVUVPUTVyVGYrQUxvTnFDU0JoVi9KeTlBSAp0azBNKzgyZ1lFQ3hFOWdocVVub2ZieDVFN3BUdUR0bGtReGZMd0pSaXI1M2ZudkczaHZya2xsZkdMWkltTEJpCnYrNm0yVm9SeHEyaW9sRjU1NG5ONC9xMm5SUG5PelBadjU0YUxjUXU2dW1nMVhZOXNsQSs5NTV3OEhERVpSYzkKNjBrdE1EZ1BIcDVYb0pvMTZ2clo0bVVuOTRzanh0Q09QQkpPbU1RNUFodEdsY0ZzVEx1cWthV29hZEgxdDNLZQpsME9NcjdaZXVQMGxGN2t1bkcvMnNqNXpqL3ZFV3RIeWNDaEJsd3VZZitsVVhGMzZWU1czWkJBTnFyN1phZExYClZKTUp2ZlhuZWNRZG1IM2tuck9VdUp6OGxTbU5iZHlZeHZ6dHY2T0xWQUdrYThFRlEvdnVMWi8vd3RkTWVtbDAKZmprM0RFckRVV1c1clBqS2tTNlgwZWZEQ0FpcWZyUE5pbkR4dzFSOS81V2ppejFsTEdGL0JoNDRtWjBZbll5MApNalA5MTQ2V2Fsakc5L1ZIREJua3dnTEtHbzlIbzVHck1iK1RpK3ZkOFN4YXZINmo1RFlYcFd4NW9XSlRFV2J2ClhvV1ppUi9EYk01cmNQSTVEWFRFRTJBdXdQcjNWaWJDRVVieUx1dmZFMDlTN1M3aU4wdlF3UUJCTW9mTHpuTHgKTi8vQ2diZWFNOExxQ0FsRWIxNUZLNThtMERHOXZPZHZyM0pLUnVhVjU1YkQ5dk9FV2dlMTJpbG1Sb1dpQmR1UAo5a3VhOW9IYkQ2N25JNkJBTkNndXdtdVJ3M3A1eklMNkpoV2IvajIzWVYvS3VBUTMvbi9TZnNJYjAweVdoa21iCk1IT1hvcUVwQW9JQ0FRRC80aW1mRjdhLzROdnF5NW5vQ0J1UnBkRUFtbWxIVThhYmtoTHdZdkFJS3ZwbHpqZ0EKVjEzYjEwWEFXcEZNWENHcVN5L1Fvd2loNHNxZ2d2ZForZXo4SThkL3R3V1I5RHdHamtRb3BORVkwNkt0N3BkYgplVi8vV3cvRkdiTFd1Mm5QbzRRb0Z1S29tRG5uSEhRV1l5V3lvbkQvOUdRamovbnk2eHZ5WDkyNWE2aldlV2hLCnJmZnJIa0xyTmt4NFhLaTBBV2txN1NlaExJb0dvSE9GT1VoRjlWcXNhSWNWSm1ibldVMjg4cUFrWHBpcnFJZmcKTXc5MTVVcXhFMnYwODdoVFBIcklBOGVOdzRwMFoyZnprTEV5MnppNHZ2VUdCdjZQYTBtNTQxVTNjcklETXo3WQpGaDFEdzVpWEpQLzdlQUI3WVVqMGFXTUgxQllQRUErUEtZZExtdFdiL3UwVlcwZHZBalFxb1o4cHB1TTJ2cHFoCit4eTNkaDZrVXAzTE5yTmE5UkNVbERuUGpPc2VqelNIZkdTQi9Udkc5aXBBN3BXVG9iS0xKK3M5a2hqRXBSTzUKRzZ1S3JMMEp1aDVlVTU3djVkeHh6T0lSZXR3NGgzSFFwbXpvOThOb2poSzRqUDNING1VYXVuRzFnUkJ4MEdtUApOVFg1SkE4am91dGZVdy9JUmN6TndVbWNNby8xNjZ3OVplNWgzeHk4d0dBRDFQL3E3MDZPV3lxSWszWDdUK0VlClpJWHRycjJWeDNIdFpMR3VNNmRPWHlQVTVWWVg0TGJVSnd2cnFvdnZLbWhIWndMNklqS3RiSVAxYmZaVFptVTYKT3g3OW5jRXU3anRqQzZtTktxRkNYR2lxUmxwVkIvL0VrQ29xSHBJcVY1ZmFKdGtORjgyQk1JeHIrd0tDQWdFQQovdzdJZ0huQ0Y1Zzl2czZTSFhoMnVqS2dtYmx3OFAxVk10dEJLN2ZVNTFWREU2cjFSRExTTHFGWUtvTUZHNnlKCnBkMWhnc2I0QStYdGc4a1JxSWNHVjdRUEQ3Z2JjMmtjZmc4R2xEVFZqYldjOHBmV3gycXo5NFVHYUNBWHRjdWkKTm5Vc0ZCUkt6cTU0T0dOWG9hZGVZTFh1djFLM2QybTQxQ2EvYTdYTG5ScGNmNWUxUm4wbGdja2dpR2U4K1hRbQordFpCWXVkMk1jWGY4TndOd3hNcWpqaEJTWTc1TkZreGxRbng2SnJBd2FCY2s5SHNRL1ZMa3lsUHhYLzgrbkNoClVZUXR1bitvaU4vanVkQ01KUC9WTGFKWUJOMW03NVI3QUt4a1BRQXdJVWRtdUFoMXpDVVJaNXZTUkoxQmlnQ2IKWE16RkgzU3RzWlc4S2Q5RlpNZWlFR1V0RkxWMm53ZHM3eFoxbEdQMGpld2xCaWFac3JxbUhVbDErczR0T1pKbApxUjA2cTMwVTMxdzBVQ2Y4U2xZSUZjdmE2ZDFCNy9aMFYyeWE0Q0E4cW5MQ2V4R2NKbmorVUdVcS9sWWM4ZEdICmtxL1ZXc04vTU5MWEM5ZXNjWHc1UzFkb0FhMVNkSEhLQUorcnlweUsrc285K1hqcDlHK1JHOTRRZk5kLzZIL1cKc2pGc0g5WGhtdWE1ZDBLNjhrZVNiRFhCQzNUWmNsRHpHMmZkZHlmSGFNSFhic0hTZmcwR0lEZS84Ri93ZFpuaApkQmNGb0xQdEtPRXhXbzRod2pFN3BYdXYzRGY1T1hPVGNnNnFacFBxZHFRWWk1ZEwwbEhuRXpma2o2RFhPRzZGCk1TNzFTMlowUG5zOVFyeUF0Qm1GN3IyTW55VkY4OGZ2MXNMajVmNFJZeXNDZ2dIL2ZmRFNpM3NnZDFBMDdWdEkKWk91WXBoYjJ4MVU0ZStLLzNkSUhnRWt4MnROTWFzOFV3UlkvRy9UWVg5UXpyMkdwTUNmUllON2RZTkErNnNHSwovTDRGNWhPMkhTWDNsOTZkckp4WTc2Z3ZRZ2pvQ0xObHk1L3huNzB5QmRDZ05SQUpCQ2wyNGtSaFNwbWg1aDRiCkJPbkhwQ1JQZWFyUG5yRStWRkZqYitlL09ZUERsY3dyaUpZWGI2RjFUazlyVTlKSE5sRjdjYVZIM0F3UDR6TVYKcUh5SkZlV3N1eTYzVGJHWTlFVC8vZjlzMG5tOHFzQklJQkVCaXdWUHZkZlJTcjZwK2szS0lLZTdrQXF1R3B6SwpqUmFxSUYzRmpTaHZjSWdBd3BZTHMzSXdmeG4wZzU2MVQ2V1N3Y2VEVXVEakhPSHpXc2FISWNTOCtSMXB2Z0FwCnFFeklTbTNxdE56RDA3OFphWW1zSTA5cEJ4Y2N2ZFVTUnFkUmV2cW9HamlQY1hWNjBVbk0zMVFWSUJJN3BzN1YKQzlvdG5jMEZudWVKNUd1Sk15Qml3QnJscldnNnlJNTNKcVIzeWNrN1FZNVpaQlBFSms3OE1RYW1QZlE2YjVnNgpiSGQ5SXl6UEFLYnNqK2pVLzR4dU5ybU5QY2hJVDd4RU9EZjRXS2RtekNOanRZY3NQV1lkWnllN0V5WFB0VHBKCmkrNmZaWXhxbUh3V3hjd1FLWkdmR0hIR2ZYSVduNXF4TWtSSHByUmFtMTJPdFVqYUt1TkJkVkZlVVdxTzlUR2sKeXNadEY1RFpUdDJRZFpROTR0N3lFbWxXaVhXVngzYWVYQXE5TmhadS9xcENrSDBzOWs0RkVLUnEzMlBCRWhqZAp5ZUVxMzVBc1lLcThFcU1NTVdXRndCQWxEUUtDQWdBR25MaC85Q2dlK25oblVPMml5L093QWczOXpqdnFVM2I0CitZd24rUDBRL2puZDhhbW9HZlV1OWtuVjJFMnltUGQ4a0UrdDEwQ293VFkyRzJsVXlDTlc5TGtMUEVlaDUxQ3cKeCt6d3ZLbm9vWk92Q2xhc0ZzMFJscVpDM3NvZWtXZmtKNGQ4QWNhcXN3VTAyUVoxajJRMzk1OTM0RW9YVTJ0UwpQS3Jydk92Slo5eU1Cai9SMHY2ODdaemxUR011eUY4V1U2V2dUY1hYcG55V3Z1MndaL2ZMZGhQak4weW9tY05hClRNYXp0QWRaUGJJSXR3RjhCWWp2Q0x3anI1eThWVjBwUXRiNHBjU1Z2OUFraWc2SUN3WFl5QU9tSktNOWhNam4KakpDUXNFZVBKVTI1YWFhOEl4M2ZaTCsvdlovc1Z2V3dJekxkRE9aUDIwVGtoUUJFaTVSYy9uSjd2ZlNVVE5uNwpITWJ4a09IUEtCY1JvTUNOVEo5djFPNjFFTkZGVTlGRTRCZ2NTQUxaZzRkcnFJMjIwNklrQm9QbldqQVNhMzQ2Cm9mc2w0bEFRVHlkUmozUlAzd1VneW02aDUxT2F4VWJSZTdONVJlWXZPdGdPVzRvQjZ5bUZGWUFCd3grSEcwZ1UKV2c5WEVsWGNDSkF3dm55Nk5JWTdoYmRCdFVpQW00ZlNXTXVueTZDc3BseWFoZVZZMEpnd0svaVVOblJJcldhUQpDRkpLZTRLRTZibVBDb0ZOZVVMMlpOdVovTEs4S2NBWmhWdEUva1Vnc1MzWlhpUHI1K0RXK216bHRhSEZab1NsCkNWSkxsSHdZbFVwNW0vT0FRVlZQUHp5eXFJWEwxYm1vTzhKcU1QN0VlK2RycW4xZnJlVzErYjRDaGpIWkR3N2QKcjNHL0RhWWZ2d0tDQWdCWTlXRG9qVTJ2c3hTUzN0S3JrTkp4YWEyeEZkZCt5MTRZRkFYNEtpb0FzMXlLd2kvUgpEN2FqZFBMckJZbkV5MWQ0QzZndzFnbVVZMXEyNW5YSUViMjlFbmJVaEZjQnZWT3htVkVsODI5SmJzTE1raTBXCndsTU5uZ2FBR1ZQZGluOGNmZGpxTXh0RFMyWjlVNG9EUTBwaGdTSVNHdy92OEhRTjJya1pKOFNOdHZHQ3paVW0KejlEVUthZDBWSTFsdFFVZWo5L2RWUHlSTHVMTVdIUE1YTnkwQ2ltSE15bU80dUNrdG9TRnY1N2VqZm1UNzNoaQpnTmt2WWNjMkp3UXgvR1dVUzl1c1ZQVWcwNFBQRGxPYTZzVHFLeVJMZGpkVUZjZXVoSVRPWnlRYU1JczRPc3ZGClJGUmk5Uk1rZEZEOHhYT0NPd0daSFhBZ0huQW1RckFaNlVqbXk2OUR0eGNBWmt2bXdXRWh1Wk4zUUJTaUV6N3gKQlhlNDNjTVpzMml6RnNGWlRBV3dXaXZaRmhDc0U2MUNQVE51cGFNNUpnTXdwSThNRHZVOE5EVE9BVjdSN1Q0Ywo3aHdiVXZFRGNpYmxoaFM1NlVLOElPNE1BZkhIRWo0elZDZDA3Q3J1cGtjbDZxbmczcVRoVlNpc0kvYmJhRFZrCitYK2daaTB6KzY2a0hkNWwrQUNrTjVPZUdTaDdxNXVPT21wVW1GWXAxRnhpeGFyNy80enVQS25Cb3crcnozbEIKcGlSWnJHNnZZWTdjcFQ5Rkpac3NpSm5xMElJMDNPUU1KY2RZaWRDZjZnQ1hKRWVqL1hhTFpmOW9OMEY2N1hETwpNU240RDZScU5USUNKNDE4RDI0Ly9oYWx1d1gyYndmU3dtdGRzL0RHMyt3RGhyekpna1JRQXZlTTlnPT0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0K"
context.alpn_protocol = "h2"
server = HTTP::Server.new [HTTP::CompressHandler.new] do |context|
STDOUT.puts [context]
context.response << "Hello World!"
end
address = server.bind_tls Socket::IPAddress.new("0.0.0.0", 9876_i32), context
STDOUT.puts "Listening on https://#{address}"
server.listen
```
### Installation
```bash
$ git clone https://github.com/636f7374/forest.cr.git
$ cd forest.cr && make build && make install
```
## Development
```bash
$ make test
```
## References
* [StackOverflow - Why do web browsers not support h2c (HTTP/2 without TLS)?](https://stackoverflow.com/questions/46788904/why-do-web-browsers-not-support-h2c-http-2-without-tls)
* [HttpWG - Hypertext Transfer Protocol Version 2 (HTTP/2)](https://http2.github.io/http2-spec/)
* [Blog - Programmersought HTTP2 detailed](http://www.programmersought.com/article/6185820249/)
* [StackOverflow - WINDOW_UPDATE HTTP/2 frame](https://stackoverflow.com/questions/51538391/window-update-http-2-frame)
* [Blog - HTTP: HTTP/2 - High Performance Browser Networking (O'Reilly)](https://hpbn.co/http2/)
* [Medium - HTTP/2 Flow Control](https://medium.com/coderscorner/http-2-flow-control-77e54f7fd518)
* [Cloudflare - HTTP/2 For Web Developers](https://blog.cloudflare.com/http-2-for-web-developers/)
* [Wireshark - Hypertext Transfer Protocol version 2](https://wiki.wireshark.org/HTTP2)
## Credit
* [\_Icon - Freepik/WebDevelopment](https://www.flaticon.com/packs/web-development-79)
## Contributors
|Name|Creator|Maintainer|Contributor|
|:---:|:---:|:---:|:---:|
|**[636f7374](https://github.com/636f7374)**|√|√||
|**[ysbaddaden](https://github.com/ysbaddaden)**|||√|
## License
* MIT LicenseDocumentation
Built from the current release. The first visit to a release nobody has asked for starts its build.
Links
This release
- Version
0.1.0- Tagged
- Feb 1, 2021
- Commit
d4b7bb1d1073- Indexed
- not yet
Dependents
No indexed shard depends on this one yet.
Repository
github.com/636f7374/forest.cr
Metadata
- Created
- Aug 12, 2026
- Updated
- Aug 12, 2026
- Synced
- Aug 12, 2026
- Versions
- 2