Sending HTTP/2 POST request in Ruby

荒凉一梦 提交于 2019-12-04 00:36:14

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' # example
sock = TCPSocket.new('api.development.push.apple.com', 443)

conn = HTTP2::Client.new
conn.on(:frame) do |bytes|
  puts "Sending bytes: #{bytes.unpack("H*").first}"
  sock.print bytes
  sock.flush
end

stream = conn.new_stream

stream.on(:close) do
  sock.close
end

head = {
  ':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
  end
end

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 client
client = NetHttp2::Client.new("http://106.186.112.116")

# send request
response = client.call(:get, '/')

# read the response
response.ok?      # => true
response.status   # => '200'
response.headers  # => {":status"=>"200"}
response.body     # => "A body"

# close the connection
client.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 connection
connection = 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 response
response.ok?      # => true
response.status   # => '200'
response.headers  # => {":status"=>"200", "apns-id"=>"6f2cd350-bfad-4af0-a8bc-0d501e9e1799"}
response.body     # => ""

# close the connection
connection.close

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.

Here is how you do it using async-http:

#!/usr/bin/env ruby

require 'async'
require 'async/logger'
require 'async/http/client'
require 'async/http/url_endpoint'

Async.run do |task|
    endpoint = Async::HTTP::URLEndpoint.parse("https://www.google.com")

    client = Async::HTTP::Client.new(endpoint)

    headers = {
        'accept' => 'text/html',
    }

    request = Async::HTTP::Request.new("www.google.com", "GET", "/search?q=cats", headers)

    response = client.call(request)
    body = response.read
end

This will negotiate HTTP/1, HTTP/2 and SSL as required.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!