I would guess this is happening because of a theory
error in Rack
in the following code, paired with a theory
error in your Java client invocation of the Ruby server:
# Return the bytesize of String; uses String#size under Ruby 1.8 and
# String#bytesize under 1.9.
if ''.respond_to?(:bytesize)
def bytesize(string)
string.bytesize
end
else
def bytesize(string)
string.size
end
end
module_function :bytesize
That is in the file <rack>lib/rack/utils.rb
... which Sinatra uses, here:
headers["Content-Length"] = body.inject(0) { |l, p| l + Rack::Utils.bytesize(p) }.to_s
That is in the file <sinatra>lib/sinatra/base.rb
in the #finish method, in inside a check which tests calculate_content_length?
...anyway, there is no test for if string
is Nil, in the #bytesize method... it's just doing a test to see whether the Ruby engine itself supports #bytesize.
In other words, I would guess your body is Nil
, or an incompatible kind of Object, which does not have the #bytesize method, since Rack
does not test, it just assumes the data coming into that method is good, and passes the method call onto that object, based purely on the underlying engine... not based on the user_agent. That's Rack
's theory error.
Troubleshooting further, I would guess that there is either something which is user_agent specific in your Java code, not your Ruby code. And not even truly user_agent, because you don't seem to instantiate a 'browser' but just open a socket connection. I'd guess that you need to actually invoke the server through HTTP commands in a formal request, RFC compliant protocol, etc... so you need to send a syntactically correct header and body.
I've seen this sort of thing happen with strange clients, such as obscure crawlers which do not send correct headers, or send no body and only headers. I'd further further further guess that opening a Socket connection is not enough. You need to send headers and a body to the server. I'd finally guess that you could likely use a Java library which is like a curl
or a wget
and not just manipulating a raw socket. That would do the proper protocol chatter for you, and just give you back what you're looking for from your Ruby/Sinatra endpoints. Looking around on here a bit, I found:
cURL equivalent in JAVA