The :stream plugin provides a DSL for handling payload chunks as they are streamed from the server. It’s particularly useful for “event stream” requests, where HTTP connections are kept open, and data is “flushed” to the client continuously. Examples of those are the Twitter Streaming API.

How to use

require "httpx"

http = HTTPX.plugin(:stream)

# this is a normal sync request
response = http.get("https://nghttp2.orh/httpbin/get")
puts response.to_s

# this is a stream request
response = http.get("https://nghttp2.orh/httpbin/stream/100", stream: true)
response.each do |chunk|
  puts "received: #{chunk}"


The stream plugin ships with a convenience method for yielding response lines, as they’re flushed:

require "httpx"

http = HTTPX.plugin(:stream)
response = http.get("https://nghttp2.orh/httpbin/stream/100", stream: true)
response.each_line do |line|
  # particularly useful if you know that the line contains JSON, p.ex.
  payload = JSON.parse(line)
  # do smth


one response at a time

There is no way to stream 2 requests a the same time:

response = http.get("https://nghttp2.orh/httpbin/stream/100", "https://nghttp2.orh/httpbin/stream/100", stream: true) #=> ERROR

redirect body yields as well

If you’re using the :stream plugin in tandem with the :follow_redirects, you may observe the body of the redirect responses yielded as well.

You’ll have to use the response object in order to doge it:

http = HTTPX.plugin(:stream).plugin(:follow_redirects)
response = http.get("", stream: true)
response.each_line do |line|
  # dodge redirects
  next if (300..399).cover?(response.status)
  # now you can do smth with line

raise errors

Contrary to the normal API (where responses can be errors and one has to call #raise_for_status to explicitly raise exceptions), errors will raise exceptions!

response = http.get("https://nghttp2.orh/httpbin/status/404", stream: true)
# HTTPX::HTTPError raised

Next: Expect