rails - Ruby-net/http-siguiendo redirecciones
ruby on rails http get request (5)
Dado un URL que redirige
url = ''http://httpbin.org/redirect-to?url=http%3A%2F%2Fhttpbin.org%2Fredirect-to%3Furl%3Dhttp%3A%2F%2Fexample.org''
A. Net::HTTP
begin
response = Net::HTTP.get_response(URI.parse(url))
url = response[''location'']
end while response.is_a?(Net::HTTPRedirection)
Asegúrese de manejar la caja cuando hay demasiados redireccionamientos.
B. OpenURI
open(url).read
OpenURI::OpenRead#open
sigue los redireccionamientos de forma predeterminada, pero no limita la cantidad de redireccionamientos.
Tengo una URL y estoy usando HTTP GET para pasar una consulta a una página. Lo que ocurre con el sabor más reciente (en net/http
) es que el script no va más allá de la respuesta 302. He probado varias soluciones diferentes; HTTPClient, net / http, Rest-Client, Patron ...
Necesito una forma de continuar a la página final para validar una etiqueta de atributo en esas páginas html. La redirección se debe a que un agente de usuario móvil golpea una página que redirige a una vista móvil, por lo tanto, el agente de usuario móvil en el encabezado. Aquí está mi código como lo es hoy:
require ''uri''
require ''net/http''
class Check_Get_Page
def more_http
url = URI.parse(''my_url'')
req, data = Net::HTTP::Get.new(url.path, {
''User-Agent'' => ''Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5''
})
res = Net::HTTP.start(url.host, url.port) {|http|
http.request(req)
}
cookie = res.response[''set-cookie'']
puts ''Body = '' + res.body
puts ''Message = '' + res.message
puts ''Code = '' + res.code
puts "Cookie /n" + cookie
end
end
m = Check_Get_Page.new
m.more_http
¡Cualquier sugerencia sería muy apreciada!
Escribí otra clase para esto en base a los ejemplos que se dan aquí, muchas gracias a todos. Agregué cookies, parámetros y excepciones y finalmente obtuve lo que necesito: https://gist.github.com/sekrett/7dd4177d6c87cf8265cd
require ''uri''
require ''net/http''
require ''openssl''
class UrlResolver
def self.resolve(uri_str, agent = ''curl/7.43.0'', max_attempts = 10, timeout = 10)
attempts = 0
cookie = nil
until attempts >= max_attempts
attempts += 1
url = URI.parse(uri_str)
http = Net::HTTP.new(url.host, url.port)
http.open_timeout = timeout
http.read_timeout = timeout
path = url.path
path = ''/'' if path == ''''
path += ''?'' + url.query unless url.query.nil?
params = { ''User-Agent'' => agent, ''Accept'' => ''*/*'' }
params[''Cookie''] = cookie unless cookie.nil?
request = Net::HTTP::Get.new(path, params)
if url.instance_of?(URI::HTTPS)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
response = http.request(request)
case response
when Net::HTTPSuccess then
break
when Net::HTTPRedirection then
location = response[''Location'']
cookie = response[''Set-Cookie'']
new_uri = URI.parse(location)
uri_str = if new_uri.relative?
url + location
else
new_uri.to_s
end
else
raise ''Unexpected response: '' + response.inspect
end
end
raise ''Too many http redirects'' if attempts == max_attempts
uri_str
# response.body
end
end
puts UrlResolver.resolve(''http://www.ruby-lang.org'')
La referencia que funcionó para mí está aquí: http://shadow-file.blogspot.co.uk/2009/03/handling-http-redirection-in-ruby.html
Comparado con la mayoría de los ejemplos (incluida la respuesta aceptada aquí), es más robusto ya que maneja las URL que son solo un dominio ( http://example.com - necesita agregar un /), maneja SSL específicamente, y también URL relativas.
Por supuesto, sería mejor que utilizaras una biblioteca como RESTClient en la mayoría de los casos, pero a veces los detalles de bajo nivel son necesarios.
Para seguir los redireccionamientos, puedes hacer algo como esto ( tomado de ruby-doc )
Siguiendo la redirección
require ''net/http''
require ''uri''
def fetch(uri_str, limit = 10)
# You should choose better exception.
raise ArgumentError, ''HTTP redirect too deep'' if limit == 0
url = URI.parse(uri_str)
req = Net::HTTP::Get.new(url.path, { ''User-Agent'' => ''Mozilla/5.0 (etc...)'' })
response = Net::HTTP.start(url.host, url.port) { |http| http.request(req) }
case response
when Net::HTTPSuccess then response
when Net::HTTPRedirection then fetch(response[''location''], limit - 1)
else
response.error!
end
end
print fetch(''http://www.ruby-lang.org/'')
Tal vez puedas usar la joya de curb-fu aquí https://github.com/gdi/curb-fu lo único que hay es un código extra para que siga el redireccionamiento. He usado lo siguiente antes. Espero eso ayude.
require ''rubygems''
require ''curb-fu''
module CurbFu
class Request
module Base
def new_meth(url_params, query_params = {})
curb = old_meth url_params, query_params
curb.follow_location = true
curb
end
alias :old_meth :build
alias :build :new_meth
end
end
end
#this should follow the redirect because we instruct
#Curb.follow_location = true
print CurbFu.get(''http://<your path>/'').body