Sending HTTP/2 POST request in Ruby Sending HTTP/2 POST request in Ruby ruby-on-rails ruby-on-rails

Sending HTTP/2 POST request in Ruby


DISCLAIMER: I'm the author of the two gems listed here below.

If you want to issue HTTP/2 calls, you may consider NetHttp2, a HTTP/2 client for Ruby.

Usage example for sync calls:

require 'net-http2'# create a clientclient = NetHttp2::Client.new("http://106.186.112.116")# send requestresponse = client.call(:get, '/')# read the responseresponse.ok?      # => trueresponse.status   # => '200'response.headers  # => {":status"=>"200"}response.body     # => "A body"# close the connectionclient.close    

On top of writing the HTTP/2 calls yourself, if you want an Apple Push Notification gem that uses the new HTTP/2 specifics and can be embedded in a Rails environment then you may also consider Apnotic.

Usage is very simple:

require 'apnotic'# create a persistent connectionconnection = Apnotic::Connection.new(cert_path: "apns_certificate.pem", cert_pass: "pass")# create a notification for a specific device token token = "6c267f26b173cd9595ae2f6702b1ab560371a60e7c8a9e27419bd0fa4a42e58f"notification       = Apnotic::Notification.new(token)notification.alert = "Notification from Apnotic!"# send (this is a blocking call)response = connection.push(notification)# read the responseresponse.ok?      # => trueresponse.status   # => '200'response.headers  # => {":status"=>"200", "apns-id"=>"6f2cd350-bfad-4af0-a8bc-0d501e9e1799"}response.body     # => ""# close the connectionconnection.close


There is an example of creating HTTP/2 client in this file. It could be adapted to APN requests like this:

require 'socket'require 'http/2'payload = '{"foo":"bar"}'device_token = '00fc13adff785122b4ad28809a3420982341241421348097878e577c991de8f0' # examplesock = TCPSocket.new('api.development.push.apple.com', 443)conn = HTTP2::Client.newconn.on(:frame) do |bytes|  puts "Sending bytes: #{bytes.unpack("H*").first}"  sock.print bytes  sock.flushendstream = conn.new_streamstream.on(:close) do  sock.closeendhead = {  ':scheme' => 'https',  ':method' => 'POST',  ':path' => "/3/device/#{device_token}",  'apns-id' => '123e4567-e89b-12d3-a456-42665544000', # or you could omit this header  'content-length' => payload.bytesize.to_s # should be less than or equal to 4096 bytes}puts 'Sending HTTP 2.0 request'stream.headers(head, end_stream: false)stream.data(payload)while !sock.closed? && !sock.eof?  data = sock.read_nonblock(1024)  puts "Received bytes: #{data.unpack("H*").first}"  begin    conn << data  rescue => e    puts "Exception: #{e}, #{e.message} - closing socket."    sock.close  endend


I’ve been working on a client implementation for this: https://github.com/alloy/lowdown.

Thus far I have been extensively testing it, but it won’t be deployed into production until next week. I’d love for it to get more testing, feedback, etc.