Plum: An HTTP/2 Library for Ruby
A pure Ruby HTTP/2 server and client implementation.
WARNING: Plum is currently under heavy development. You will encounter bugs when using it.
Requirements
- Ruby
- Ruby 2.2 with ALPN support patch and ECDH support patch (r51348)
- or latest Ruby 2.3.0-dev
- OpenSSL 1.0.2 or newer (HTTP/2 requires ALPN)
- Optional:
- http_parser.rb gem (HTTP/1.x parser; if you use “http” URI scheme)
- rack gem (if you use Plum as Rack server)
Installation
“ gem install plum
“
Usage
- Documentation: http://www.rubydoc.info/gems/plum
- Some examples are in
examples/
As a Rack-compatible server
Most existing Rack-based applications should work without modification.
“by
config.ru
App = -> env { [200, { Content-Type => text/plain }, request: #envREQUEST_METHOD #envPATH_INFO] }
run App
“
You can run it:
“ % plum -e production -p 8080 –https –cert server.crt –key server.key config.ru
“
NOTE: If --cert
and --key
are omitted, a temporary dummy certificate will be generated.
As a HTTP/2 (HTTP/1.x) client library
If the server does’t support HTTP/2, Plum::Client
tries to use HTTP/1.x instead.
“ +—————–+ |:http2 option | false |(default: true) |——-> HTTP/1.x +—————–+ v true +—————–+ |:scheme option | “http” |(default:“https”)|——-> Try Upgrade from HTTP/1.1 +—————–+ v “https” +—————–+ | ALPN(/NPN) | failed | negotiation |——-> HTTP/1.x +—————–+ | “h2” v HTTP/2
“
Sequential request
“by client = Plum::Client.start(“http2.rhe.jp”, 443, user_agent: “nyaan”) res1 = client.get!(“/”, headers: { “accept” => “/” }) puts res1.body # => “…” res2 = client.post!(“/post”, “data”) puts res2.body # => “…”
client.close
“
Parallel request
“by res1 = res2 = nil Plum::Client.start(“rhe.jp”, 443, http2_settings: { max_frame_size: 32768 }) { |client| res1 = client.get(“/”) res2 = client.post(“/post”, “data”) # res1.status == nil ; because it’s async request } # wait for response(s) and close
p res1.status # => “200”
“
Download a large file
“by Plum::Client.start(“http2.rhe.jp”, 443, hostname: “assets.rhe.jp”) { |client| client.get(“/large”) do |res| # called when received response headers p res.status # => “200” File.open(“/tmp/large.file”, “wb”) { |file| res.on_chunk do |chunk| # called when each chunk of response body arrived file « chunk end } end }
“
TODO
- Better API
- Plum::Client
- PING frame handling
- Server Push support
- Stream Priority support
- Better HTTP/1.x support
License
MIT License