Skip to content

Instantly share code, notes, and snippets.

@rafaelsales
Created June 6, 2018 15:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rafaelsales/e9fb9eebc85fb82612cbbb9f194864db to your computer and use it in GitHub Desktop.
Save rafaelsales/e9fb9eebc85fb82612cbbb9f194864db to your computer and use it in GitHub Desktop.
Issues What-The-Fudge

Problem: HTTParty sometimes fail with Mios API

How to reproduce

host='vera-us-oem-relay31.mios.com'
path='/relay/relay/relay/device/45025220/session/000000043F62005B183D2DABD0DD8B175A866F/port_3480/data_request?DeviceNum=3&Variable=PinCodes&id=variableget&serviceId=urn%3Amicasaverde-com%3AserviceId%3ADoorLock1'
HTTParty.get("https://#{host}#{path}")

Investigation

# Common part:
http = Net::HTTP.new(host, 443)
http.set_debug_output $stdout
http.use_ssl = true

# The one that HTTParty uses and often fails with EOF error:
http.request(Net::HTTP::Get.new(path))
# Output: <- "GET <path> HTTP/1.1\r\nAccept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3\r\nAccept: */*\r\nUser-Agent: Ruby\r\nConnection: close\r\nHost: vera-us-oem-relay31.mios.com\r\n\r\n"
# This method is equivalent to: HTTParty.get("https://#{host}#{path}")

# This other method works:
http.start { http.request Net::HTTP::Get.new(path) }
# Output: <- "GET <path> HTTP/1.1\r\nAccept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3\r\nAccept: */*\r\nUser-Agent: Ruby\r\nHost: vera-us-oem-relay31.mios.com\r\n\r\n"

# Yet another method that works - I couldn't figure out how to enable debug with verbose output
Net::HTTP.get(URI("https://#{host}#{path}"))

Solution

So, I noticed the only difference between the method that works and the one that does not is the "Connection: close" header, which really aligns with the error - because the connection is closed before the EOF is read.

When we omit the "Connection" header in an HTTP/1.1 request, the default value is "keep-alive", so both methods below are equivalent and work fine

HTTParty.get("https://#{host}#{path}", headers: { Connection: '' })
HTTParty.get("https://#{host}#{path}", headers: { Connection: 'keep-alive' })

I couldn't come to a conclusion whether this is a client or server bug, but given there are no recent issues reported to HTTParty lib related EOF errors, I think I'd rather believe it's a server issue, where it might close the connection before the entire body is streamed when "Connection: close" header is present.


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment