1

我正在使用以下方法流式传输数据:

self.response_body = Enumerator.new do |y|
    10_000_000.times do |i|
        y << "This is line #{i}\n"
    end
end

我试图捕捉在 Enumerator 内部生成的任何异常并向用户呈现更好的东西。现在,该应用程序正在呈现一个来自 Torquebox 的丑陋错误页面。例如

Torquebox/Jboss 错误页面.

我尝试了rescue 和redirect_to 以及许多其他方法来捕获异常(包括添加一个中间件类来处理异常)。任何帮助,将不胜感激!。

(该应用是在jruby v1.7.19和torquebox v3.1.1下制作的)

4

1 回答 1

0

我对这个问题有部分解决方案:

  1. 检查外部文件头。该应用程序正在向外部服务器发送标头请求。

    1.1 如果状态为200(成功),则应用程序像以前一样开始检索过程。

    1.2 如果状态是任何其他值,则会显示一个错误页面,其中包含相应的错误消息。

代码如下所示:

uri = URI.parse(link)

net_http = Net::HTTP.new(uri.host, uri.port)
net_http.open_timeout = options[:timeout]
net_http.read_timeout = options[:timeout]
net_http.use_ssl = (uri.scheme == 'https')

if net_http.use_ssl?
  net_http.cert = OpenSSL::X509::Certificate.new(File.read(options[:cert]))
  net_http.key = OpenSSL::PKey::RSA.new(File.read(options[:cert]))
  net_http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end

begin
  request = Net::HTTP::Get.new(uri.request_uri)
  res = net_http.request(request)

  if res.code.to_i == 200
    self.response.headers['Pragma'] = 'no-cache'
    self.response.headers['Cache-Control'] = 'private,max-age=0,must-revalidate,no-store'
    self.response.headers['Last-Modified'] = Time.now.ctime.to_s
    self.response.headers['Accept-Ranges'] = 'bytes'
    self.response.headers['Content-Type'] = type
    self.response.headers['Content-Disposition'] = "attachment; filename=\"#{save_as}\""
    self.response.headers['Content-Transfer-Encoding'] = 'binary'
    self.response.headers['Content-Description'] = 'File Transfer'
    self.response.headers['Content-Length'] = "#{filesize}"

    self.response_body = FileStreamer.new(link, options)
  else
    raise "The requested file is not available at the moment"
  end
rescue SocketError => se
  raise 'It seems the URL is not correct'
rescue Errno::ECONNREFUSED => cr
  raise 'It seems the server refused the connection request'
rescue Errno::EHOSTUNREACH => hu
  raise 'It seems the server cannot be reached'
rescue Errno::ENETUNREACH => nu
  raise 'It seems the network cannot be reached'
rescue Timeout::Error => te
  raise 'Request timed out while connecting to the server'
rescue StandardError => e
  raise e.message
end

FileStreamer 是一个机架中间件,它响应每个方法。

def each
  begin
    @net_http.start do |http|
      http.request_get(@uri.request_uri(), 
        {'User-Agent' => 'FileStreamer'}) do |response|
        case response
          when Net::HTTPSuccess then
            response.read_body do |segment|
              yield segment
            end
          when Net::HTTPRedirection then
            raise 'Redirection not allowed'
          else
            raise "Error trying to retrieve a file:\n" \
              "  URL: #{@uri.to_s}\n" \
              "  Error: #{response.message.to_s}"
        end
      end
    end
  rescue SocketError => se
    raise 'It seems the URL is not correct'
  rescue Errno::ECONNREFUSED => cr
    raise 'It seems the server refused the connection request'
  rescue Errno::EHOSTUNREACH => hu
    raise 'It seems the server cannot be reached'
  rescue Errno::ENETUNREACH => nu
    raise 'It seems the network cannot be reached'
  rescue Timeout::Error => te
    raise 'Request timed out while connecting to the server'
  rescue StandardError => e
    raise e.message
  end
end

请记住,此解决方案不包括在过程中间发生的错误,我猜如果中间发生错误,那么应用程序将显示丑陋的错误页面。

于 2015-07-31T20:43:29.500 回答