如何让Ruby OpenURI允许HTTPS到HTTP的重定向?求非猴子补丁方案
解决OpenURI禁止HTTPS到HTTP重定向的替代方案
1. 用Net::HTTP手动实现重定向逻辑
直接借助Ruby标准库的Net::HTTP,完全自定义重定向规则,避开OpenURI的限制。示例代码:
require 'net/http' require 'uri' def fetch_allow_https_to_http(url) uri = URI.parse(url) response = nil Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http| request = Net::HTTP::Get.new(uri) response = http.request(request) # 循环处理重定向,明确允许HTTPS跳转到HTTP while response.is_a?(Net::HTTPRedirection) redirect_uri = URI.parse(response['location']) # 重置请求目标为重定向地址,继续请求 response = http.request(Net::HTTP::Get.new(redirect_uri)) end end response.body end # 使用示例 content = fetch_allow_https_to_http('https://example.com/redirect-to-http')
这种方式完全由自己控制重定向的判断逻辑,可根据需求调整允许的重定向类型。
2. 采用Faraday第三方库(维护活跃)
Faraday是一款灵活的HTTP客户端,支持自定义重定向策略,比手动写Net::HTTP更简洁,且项目处于活跃维护状态。
先在Gemfile添加依赖:
gem 'faraday'
然后编写代码实现允许HTTPS到HTTP的重定向:
require 'faraday' require 'faraday_middleware' # 简单配置:允许所有重定向(含HTTPS到HTTP) conn = Faraday.new do |faraday| faraday.use FaradayMiddleware::FollowRedirects, limit: 5 faraday.adapter Faraday.default_adapter end response = conn.get('https://example.com/redirect-to-http') puts response.body
如果需要更精细的控制,可自定义重定向判断逻辑:
conn = Faraday.new do |faraday| faraday.response :follow_redirects do |cfg| cfg.redirect_limit = 5 cfg.on_redirect do |response, env| from_scheme = URI(env[:url]).scheme to_scheme = URI(response['location']).scheme # 仅允许HTTPS到HTTP的重定向,其余按默认规则判断 unless (from_scheme == 'https' && to_scheme == 'http') || FaradayMiddleware::FollowRedirects.redirectable?(response) raise "Redirection forbidden: #{env[:url]} -> #{response['location']}" end end end faraday.adapter Faraday.default_adapter end
3. 临时覆盖OpenURI的redirectable?方法(非全局猴子补丁)
如果不想全局修改OpenURI的行为,可以在需要的代码块内临时覆盖方法,作用范围仅限当前代码块:
require 'open-uri' def with_https_to_http_redirect_allowed # 保存原始方法 original_method = OpenURI.method(:redirectable?) # 临时修改重定向判断逻辑 OpenURI.define_singleton_method(:redirectable?) do |uri1, uri2| original_method.call(uri1, uri2) || (uri1.scheme == 'https' && uri2.scheme == 'http') end # 执行需要允许重定向的代码 yield ensure # 恢复原始方法 OpenURI.define_singleton_method(:redirectable?, original_method) end # 使用示例 with_https_to_http_redirect_allowed do content = URI.open('https://example.com/redirect-to-http').read puts content end
这种方式只会在指定代码块内修改OpenURI的行为,不会影响其他地方的使用,比全局猴子补丁更安全。
内容的提问来源于stack exchange,提问作者Qwertie
相关产品推荐
相关产品推荐

