Net::HTTP and handling 302 Redirect

Greetings all. Ruby n00b here.

I'm trying to use Ruby against ning.com's REST api. My code is close
to working, but I don't understand the redirect example provided in
the Net::HTTP code. I'm hoping that someone can point me in the right
direction.

--- Here's my code ---

#create XML message
msg = <<eof
  blah blah
eof
doc = REXML::Document.new( msg )

url = URI.parse("https://mySite.ning.com/xn/atom/1.0/content")

@req = Net::HTTP.new(url.host)
@req.use_ssl = false #not using ssl
@req.set_debug_output $stderr
@req.start() do |req|
    postReq = Net::HTTP::Post.new(url.path)
    postReq.basic_auth('user', 'password')
    postReq['Content-Type']=req.head(url.path)
    postReq.body = doc
    print postReq

    response = req.post(url.path, postReq)
end

This results in the following at the command line when I run:

<- "HEAD /xn/atom/1.0/content HTTP/1.1\r\nAccept: */*\r\nHost:
mySite.ning.com\r\n\r\n"
-> "HTTP/1.1 302 Moved Temporarily\r\n"
-> "Date: Fri, 15 Feb 2008 00:45:18 GMT\r\n"
-> "Server: Ning HTTP Server 2.0\r\n"
-> "Expires: Thu, 01 Jan 1970 00:00:00 GMT\r\n"
-> "Set-Cookie: xn_visitor=438cccb8-1919-404e-874c-
b5791b46c579;Path=/;Domain=.ning.com;Expires=Mon, 12-Feb-18 00:45:18
GMT\r\n"
-> "X-XN-Trace: e1355fab-b1f3-409a-95bc-72488878cf37\r\n"
-> "Date: Fri, 15 Feb 2008 00:45:18 GMT\r\n"
-> "X-XN-Trace: e1355fab-b1f3-409a-95bc-72488878cf37\r\n"
-> "P3P: CP=\"UNI STA LOC CURa OURa COR ALL IND\"\r\n"
-> "Vary: X-XN_APPLICATION\r\n"
-> "Content-Type: text/html; charset=utf-8\r\n"
-> "Content-Language: en\r\n"
-> "Location:
http://mySite.ning.com/main/authorization/signIn?target=http%3A%2F%2FmySite.ning.com%2Frest%2Funsupported-http-method\r\n"
-> "Content-Length: 0\r\n"
-> "\r\n"
Conn keep-alive
#<Net::HTTP::Post:0x2ede408><- "POST /xn/atom/1.0/content HTTP/1.1\r
\nAccept: */*\r\nContent-Type: application/x-www-form-urlencoded\r
\nContent-Length: 3\r\nHost: mySite.ning.com\r\n\r\n"
<- c:/ruby/lib/ruby/1.8/net/protocol.rb:174:in `write0': undefined
method `dump' for #<Net::HTTP::Post POST> (NoMethodError)
        from c:/ruby/lib/ruby/1.8/net/protocol.rb:151:in `write'
        from c:/ruby/lib/ruby/1.8/net/protocol.rb:166:in `writing'
        from c:/ruby/lib/ruby/1.8/net/protocol.rb:150:in `write'
        from c:/ruby/lib/ruby/1.8/net/http.rb:1549:in
`send_request_with_body'
        from c:/ruby/lib/ruby/1.8/net/http.rb:1534:in `exec'
        from c:/ruby/lib/ruby/1.8/net/http.rb:1057:in `request'
        from c:/ruby/lib/ruby/1.8/net/http.rb:854:in `post'
        from ning_send.rb:50
        from c:/ruby/lib/ruby/1.8/net/http.rb:547:in `start'
        from ning_send.rb:39

Anyone have any suggestions? So clueless here. :slight_smile:

I meet two kinds of redirect: "Location" response and <META
HTTP-EQUIV="REFRESH"> tag.

Here's my solution:

···

================================================
require 'net/http'
require 'net/https'

http = Net::HTTP.new('www.microsoft.com', 80)
resp, data = http.get('/',nil)

#1."Location" response redirect...
if resp.response['Location']!=nil then
  puts 'Direct to: ' + resp.response['Location']
  redirectUrl=resp.response['Location']
end

#2.<META HTTP-EQUIV="REFRESH"> tag redirect...
redirectUrl=data.scan(/<META HTTP-EQUIV=\"REFRESH\" CONTENT=\"0;
URL=(.*)\">/).to_s
if redirectUrl!=nil then
  puts 'Direct to: ' +redirectUrl
end
--
Posted via http://www.ruby-forum.com/.

I understands your problem. Here a best service provider in India is
serving a complete webhosting solution and domain name registration. It
have a dedicated team to serve their clients allover India. If you have
any quires log on to the website: http://www.tiainterweb.net/

···

--
Posted via http://www.ruby-forum.com/.

This is my understanding of how redirects work:

The way it's supposed to work is that when you request a web page(by
sending the server a url), and the web page is not at that url, the
server should send back a response which contains a Location header.
The Location header's value is a new url where the web page is located.
A browser would automatically send out a request to the server for the
new url. On the other hand, a ruby program has to do that manually: the
program must extract the Location header, get the url, and then send
back another request to the server for that url. That's the way it's
supposed to work.

Unfortunately, people who own websites don't have to follow the rules;
they can do whatever they want. In particular, they don't have to
include a Location header in the response. The same goes for browser
manufacturers; they aren't required to sell browsers that conform to the
standards. Some browser's are programmed to recognize a Refresh header
as part of a response--even though a Refresh header doesn't technically
exist(according to the standards there is no such header). Therefore,
it's possible that a server will send back a response that contains a
Refresh header instead of a Location header. The Refresh header's value
is the new url for the page you are seeking--just like with the Location
header.

But it gets even worse. Some server side web programmers aren't able to
or don't know how to add headers to the response. As a result, the
response won't contain a Refresh header(nor the standards compliant
Location header) that specifies the new url. To remedy that, the server
side web programmer has another option: he can arrange to send back a
skeleton html page that contains a special html tag. The special html
tag looks like this:

<meta http-equiv="refresh" content="2;url=http://webdesign.about.com">

That tells the browser to pretend like there is a Refresh header in the
response. The new url is specified after the 'content=' part. The
number in front of the url is the number of seconds the browser is
supposed to wait before sending out a request for that url.

To sum up, when the server wants you to go elsewhere to find the web
page you requested, the server can send back a response with:

1) A Location header specifying the new url.
2) A Refresh header specifying the new url.
3) An html tag specifying the new url

Of course it would be a lot easier on client side programmers(you), if
the only option was 1). Instead, you have to check for all three in
order to find the new url.

redirectUrl=data.scan(/<META HTTP-EQUIV=\"REFRESH\" CONTENT=\"0;
URL=(.*)\">/).to_s
if redirectUrl!=nil then
  puts 'Direct to: ' +redirectUrl
end

That regex won't work for any of the following:

1) <meta http-equiv="refresh"
content="2;url=http://webdesign.about.com">

2) <meta http-equiv="refresh"
content="2;url=http://webdesign.about.com">

3) <meta http-equiv = "refresh" content =
"2;url=http://webdesign.about.com">'

so make sure you come up with a regex that can handle all of them.

You also might want to check out Mechanize, etc. which automatically
handles some redirects.

···

--
Posted via http://www.ruby-forum.com/\.

Looks like #1 is all I have to deal with for this particular site. The
code definitely got me further, but still in the dark.

--- Code response ---

postReq object created
#<Net::HTTP::Post:0x2ed8e90>posting to new url..
<- "POST /main/authorization/signIn HTTP/1.1\r\nAccept: */*\r\nContent-
Type: application/x-www-form-urlencoded\r\nContent-Length: 2\r\nHost:
zbcrazy.ning.com\r\n\r\n"
<- c:/ruby/lib/ruby/1.8/net/protocol.rb:174:in `write0': undefined
method `dump' for #<Net::HTTP::Post POST> (NoMethodError)
        from c:/ruby/lib/ruby/1.8/net/protocol.rb:151:in `write'
        from c:/ruby/lib/ruby/1.8/net/protocol.rb:166:in `writing'
        from c:/ruby/lib/ruby/1.8/net/protocol.rb:150:in `write'
        from c:/ruby/lib/ruby/1.8/net/http.rb:1549:in
`send_request_with_body'
        from c:/ruby/lib/ruby/1.8/net/http.rb:1534:in `exec'
        from c:/ruby/lib/ruby/1.8/net/http.rb:1057:in `request'
        from c:/ruby/lib/ruby/1.8/net/http.rb:854:in `post'
        from BACKUPning_send.rb:62
        from c:/ruby/lib/ruby/1.8/net/http.rb:547:in `start'
        from BACKUPning_send.rb:46

--- End Code response ---

···

On Feb 14, 7:48 pm, Rk Ch <rollingwo...@gmail.com> wrote:

I meet two kinds of redirect: "Location" response and <META
HTTP-EQUIV="REFRESH"> tag.

Here's my solution:

require 'net/http'
require 'net/https'

http = Net::HTTP.new('www.microsoft.com', 80)
resp, data = http.get('/',nil)

#1."Location" response redirect...
if resp.response['Location']!=nil then
  puts 'Direct to: ' + resp.response['Location']
  redirectUrl=resp.response['Location']
end

#2.<META HTTP-EQUIV="REFRESH"> tag redirect...
redirectUrl=data.scan(/<META HTTP-EQUIV=\"REFRESH\" CONTENT=\"0;
URL=(.*)\">/).to_s
if redirectUrl!=nil then
  puts 'Direct to: ' +redirectUrl
end
--
Posted viahttp://www.ruby-forum.com/.