Ruby Net:: HTTP - после 301 переадресации
Мои пользователи представляют URL-адреса (для микширования на mixcloud.com), и мое приложение использует их для выполнения веб-запросов.
A хороший URL возвращает код состояния 200:
uri = URI.parse("http://www.mixcloud.com/ErolAlkan/hard-summer-mix/")
request = Net::HTTP.get_response(uri)(
#<Net::HTTPOK 200 OK readbody=true>
Но если вы забудете трейлинг-косую черту, тогда в противном случае хороший URL-адрес вернет 301:
uri = "http://www.mixcloud.com/ErolAlkan/hard-summer-mix"
#<Net::HTTPMovedPermanently 301 MOVED PERMANENTLY readbody=true>
То же самое происходит с 404:
# bad path returns a 404
"http://www.mixcloud.com/bad/path/"
# bad path minus trailing slash returns a 301
"http://www.mixcloud.com/bad/path"
- Как я могу "развернуть" в 301, чтобы узнать, приведет ли он нас к действительному ресурсу или странице с ошибкой?
- Есть ли инструмент, предоставляющий всесторонний обзор правил, которые могут применяться определенным доменом к их URL-адресам?
Ответы
Ответ 1
301 переадресации довольно распространены, если вы не вводите URL-адрес точно так, как этого требует веб-сервер. Они происходят гораздо чаще, чем вы думаете, вы просто обычно не замечаете их во время просмотра, потому что браузер делает все это автоматически для вас.
Приходят на ум две альтернативы:
1: используйте open-uri
open-uri
обрабатывает перенаправления автоматически. Так что вам нужно всего лишь:
require 'open-uri'
...
response = open('http://xyz...').read
2: Переадресация дескрипторов с помощью Net::HTTP
def get_response_with_redirect(uri)
r = Net::HTTP.get_response(uri)
if r.code == "301"
r = Net::HTTP.get_response(URI.parse(r.header['location']))
end
r
end
Если вы хотите быть более умным, вы можете попытаться добавить или удалить отсутствующие обратные косые черты к URL-адресу, когда вы получите ответ 404. Вы можете сделать это, создав метод, подобный get_response_smart
, который обрабатывает этот URL-адрес в дополнение к перенаправлению.
Ответ 2
Я не могу понять, как комментировать принятый ответ (этот вопрос может быть закрыт), но я должен отметить, что r.header
теперь устарел, поэтому r.header['location']
следует заменить на r['location']
(per fooobar.com/questions/168741/...)
Ответ 3
rest-client
следует перенаправления для запросов GET
и HEAD
без какой-либо дополнительной настройки. Он работает очень хорошо.
- для кодов результатов между 200 и 207, возвращается RestClient:: Response
- для результирующих кодов 301, 302 или 307 будет выполняться перенаправление, если запрос является GET или HEAD
- для результирующего кода 303, будет выполняться перенаправление, и запрос преобразуется в GET
пример использования:
require 'rest-client'
RestClient.get 'http://example.com/resource'
rest-client README также дает пример следующих переадресаций с запросами POST:
begin
RestClient.post('http://example.com/redirect', 'body')
rescue RestClient::MovedPermanently,
RestClient::Found,
RestClient::TemporaryRedirect => err
err.response.follow_redirection
end
Ответ 4
Вот код, который я придумал (полученный из разных примеров), который выйдет из строя, если слишком много перенаправлений (обратите внимание, что secure_success является необязательным):
require "net/http"
require "uri"
class Net::HTTPResponse
def ensure_success
unless kind_of? Net::HTTPSuccess
warn "Request failed with HTTP #{@code}"
each_header do |h,v|
warn "#{h} => #{v}"
end
abort
end
end
end
def do_request(uri_string)
response = nil
tries = 0
loop do
uri = URI.parse(uri_string)
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri.request_uri)
response = http.request(request)
uri_string = response['location'] if response['location']
unless response.kind_of? Net::HTTPRedirection
response.ensure_success
break
end
if tries == 10
puts "Timing out after 10 tries"
break
end
tries += 1
end
response
end
Ответ 5
Не уверен, что кто-то ищет это точное решение, но если вы пытаетесь загрузить изображение http/https и храните его в переменной
require 'open_uri_redirections'
require 'net/https'
web_contents = open('file_url_goes_here', :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE, :allow_redirections => :all) {|f| f.read }
puts web_contents