J'ai une URL et j'utilise HTTP GET pour transmettre une requête à une page. Que se passe-t-il avec la version la plus récente (en net/http
) est que le script ne va pas au-delà de la réponse 302. J'ai essayé plusieurs solutions différentes; HTTPClient, net/http, Rest-Client, Patron ...
J'ai besoin d'un moyen de continuer à la page finale afin de valider une balise d'attribut sur ces pages html. La redirection est due à un agent utilisateur mobile qui frappe une page qui redirige vers une vue mobile, d'où l'agent utilisateur mobile dans l'en-tête. Voici mon code tel qu'il est aujourd'hui:
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
Toutes les suggestions seraient grandement appréciées!
Pour suivre les redirections, vous pouvez faire quelque chose comme ça ( tiré de Ruby-doc )
Redirection suivante
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, use_ssl: true) { |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/')
J'ai écrit un autre cours pour cela sur la base d'exemples donnés ici, merci beaucoup à tous. J'ai ajouté des cookies, des paramètres et des exceptions et j'ai finalement obtenu ce dont j'ai besoin: 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')
Étant donné une URL qui redirige
url = 'http://httpbin.org/redirect-to?url=http%3A%2F%2Fhttpbin.org%2Fredirect-to%3Furl%3Dhttp%3A%2F%2Fexample.org'
UNE. Net::HTTP
begin
response = Net::HTTP.get_response(URI.parse(url))
url = response['location']
end while response.is_a?(Net::HTTPRedirection)
Assurez-vous de gérer le cas lorsqu'il y a trop de redirections.
B. OpenURI
open(url).read
OpenURI::OpenRead#open
suit les redirections par défaut, mais il ne limite pas le nombre de redirections.
La référence qui a fonctionné pour moi est ici: http://shadow-file.blogspot.co.uk/2009/03/handling-http-redirection-in-Ruby.html
Comparé à la plupart des exemples (y compris la réponse acceptée ici), il est plus robuste car il gère les URL qui ne sont qu'un domaine ( http://example.com - doit ajouter un /), gère spécifiquement SSL , ainsi que des URL relatives.
Bien sûr, il serait préférable d'utiliser une bibliothèque comme RESTClient dans la plupart des cas, mais parfois les détails de bas niveau sont nécessaires.
Vous pouvez peut-être utiliser curb-fu gem ici https://github.com/gdi/curb-f la seule chose est un code supplémentaire pour le faire suivre la redirection. J'ai déjà utilisé ce qui suit. J'espère que ça aide.
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
Si vous n'avez pas besoin de vous soucier des détails à chaque redirection, vous pouvez utiliser la bibliothèque Mechanize
require 'mechanize'
agent = Mechanize.new
begin
response = @agent.get(url)
rescue Mechanize::ResponseCodeError
// response codes other than 200, 301, or 302
rescue Timeout::Error
rescue Mechanize::RedirectLimitReachedError
rescue StandardError
end
Il renverra la page de destination. Ou vous pouvez désactiver la redirection par ceci:
agent.redirect_ok = false
Ou vous pouvez éventuellement modifier certains paramètres à la demande
agent.user_agent = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Mobile Safari/537.36"