HTTP POST

N

Noel Mc grath

New to ruby and trying to do a HTTP POST. From looking at documentation
it states
"In version 1.1 (ruby 1.6), this method returns a pair of objects, a
Net::HTTPResponse object and an entity body string. In version 1.2 (ruby
1.8), this method returns a Net::HTTPResponse object."

What does it mean by version 1.1 and 1.2?
I am using ruby version 1.9.2 and the method is returning a pair of
objects:
Net::HTTPResponse
string

I am under the impression I am using version 1.2 of the POST and
therefore should be recieving an object(Net::HTTPResponse)

Can someone clear this up for me, thanks
 
B

Brian Candler

Noel said:
New to ruby and trying to do a HTTP POST. From looking at documentation
it states
"In version 1.1 (ruby 1.6), this method returns a pair of objects, a
Net::HTTPResponse object and an entity body string. In version 1.2 (ruby
1.8), this method returns a Net::HTTPResponse object."

What does it mean by version 1.1 and 1.2?

Of the Net::HTTP API. Look in the source; depending on your system this
may be somewhere like /usr/lib/ruby/1.8/net/http.rb

# == Switching Net::HTTP versions
#
# You can use net/http.rb 1.1 features (bundled with Ruby 1.6)
# by calling HTTP.version_1_1. Calling Net::HTTP.version_1_2
# allows you to use 1.2 features again.
#
# # example
# Net::HTTP.start {|http1| ...(http1 has 1.2 features)... }
#
# Net::HTTP.version_1_1
# Net::HTTP.start {|http2| ...(http2 has 1.1 features)... }
#
# Net::HTTP.version_1_2
# Net::HTTP.start {|http3| ...(http3 has 1.2 features)... }
#
# This function is NOT thread-safe.

This was for backwards-compatibility - something which was taken
seriously between ruby 1.6 and 1.8...
I am using ruby version 1.9.2 and the method is returning a pair of
objects:
Net::HTTPResponse
string

Odd. Here I get:

ruby-1.9.2-p0 > require 'net/http'
=> true
ruby-1.9.2-p0 > Net::HTTP.version_1_1?
=> false
ruby-1.9.2-p0 > Net::HTTP.version_1_2?
=> true
ruby-1.9.2-p0 > RUBY_DESCRIPTION
=> "ruby 1.9.2p0 (2010-08-18 revision 29036) [i686-linux]"
ruby-1.9.2-p0 > res = nil; Net::HTTP.start("www.google.com",80) { |http|
res = http.post "/", "q=ruby" }
=> #<Net::HTTPMethodNotAllowed 405 Method Not Allowed readbody=true>
ruby-1.9.2-p0 > res
=> #<Net::HTTPMethodNotAllowed 405 Method Not Allowed readbody=true>

So although this particular operation fails, you can see I'm only
getting a single object (response), not an array of two objects.

Is it possible that you are loading some other library which is
switching Net::HTTP into its old (1.1) mode?
 
B

Brian Candler

Here's a successful post, and only a single object is returned. What
does this show on your system?

ruby-1.9.2-p0 > res = nil; Net::HTTP.start("chart.apis.google.com",80) {
|http| res = http.post "/chart",
"cht=lc&chtt=This+is+|+my+chart&chs=300x200&chxt=x&chd=t:40,20,50,20,100"
}
=> #<Net::HTTPOK 200 OK readbody=true>
ruby-1.9.2-p0 > res["Content-Type"]
=> "image/png"
ruby-1.9.2-p0 > res.body.size
=> 7094
 
N

Noel Mc grath

Brian said:
Here's a successful post, and only a single object is returned. What
does this show on your system?

ruby-1.9.2-p0 > res = nil; Net::HTTP.start("chart.apis.google.com",80) {
|http| res = http.post "/chart",
"cht=lc&chtt=This+is+|+my+chart&chs=300x200&chxt=x&chd=t:40,20,50,20,100"
}
=> #<Net::HTTPOK 200 OK readbody=true>
ruby-1.9.2-p0 > res["Content-Type"]
=> "image/png"
ruby-1.9.2-p0 > res.body.size
=> 7094

Brian thanks for reply. I tried the code above and am getting the same
result as you.
I must apologize as I meant to say I was using require 'net/https' and
doing a HTTPS call e.g. :
resp, data = http.post(path, data, headers)

This is where the two objects are returned. Does 'net/http' and
'net/https' behave differently?
 
B

Brian Candler

Noel said:
This is where the two objects are returned. Does 'net/http' and
'net/https' behave differently?

I don't think so. Can you show some actual code, preferably something
which POSTs to a public HTTPS server and therefore can be run
standalone?
 
N

Noel Mc grath

Brian said:
I don't think so. Can you show some actual code, preferably something
which POSTs to a public HTTPS server and therefore can be run
standalone?

Brian, I cannot post my example as it is currently posting to an
internal endpoint at work.
The following code sample (changed slightly) from
http://snippets.dzone.com/posts/show/788 is the same as I am using. If
you look at the HTTP response it has the following two objects - resp,
responsedata.
resp represents the HTTP Response class and responsedata represents the
body


require 'net/https'

http = Net::HTTP.new('profil.wp.pl', 443)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

path = '/login.html'

data =
'serwis=wp.pl&url=profil.html&tryLogin=1&countTest=1&logowaniessl=1&login_username=blah&login_password=blah'
headers = {
'Referer' => 'http://profil.wp.pl/login.html',
'Content-Type' => 'application/x-www-form-urlencoded'
}

resp, responsedata = http.post(path, data, headers)

puts 'Code = ' + resp.code
puts
puts 'Message = ' + resp.message
puts
puts 'Response data = ' + responsedata
 
N

Noel Mc grath

From looking at the documentation i dont need to do this:

resp, responsedata = http.post(path, data, headers)

I can do the following:
resp = http.post(path, data, headers)

and to get the response data

puts resp.body.
So as Brian stated, I can work with one object.Thanks Brian I am new to
ruby
 
B

Brian Candler

Noel said:
If
you look at the HTTP response it has the following two objects - resp,
responsedata.

This one had me stumped for a while.

Actually, it returns only one object. But that object has a to_ary
method, which is called in the case of multiple assignment.

So:

res1 = http.post(...)

just gets the response object. But

res1, res2 = http.post(...)

is doing an implicit splat, which calls to_ary, which turns it into
[self, self.body], and those two values get assigned to res1 and res2.

This is extremely sneaky, and the code issues a warning if you run ruby
with the -w flag (which you should always do)

# For backward compatibility.
# To allow Net::HTTP 1.1 style assignment
# e.g.
# response, body = Net::HTTP.get(....)
#
def to_ary
warn "net/http.rb: warning: Net::HTTP v1.1 style assignment found
at #{caller(1)[0]}; use `response = http.get(...)' instead." if $VERBOSE
res = self.dup
class << res
undef to_ary
end
[res, res.body]
end
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,067
Latest member
HunterTere

Latest Threads

Top