Net::HTTP and handling 302 Redirect

Z

zeeboo

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/authori...ite.ning.com/rest/unsupported-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. :)
 
R

Rk Ch

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
 
7

7stud --

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.
 
Z

zeeboo

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

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 ---
 
P

Praveenbhalla Praveenbhalla

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/
 

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

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top