【问题标题】:Rack: Why is each middleware called twice on a single request?Rack:为什么每个中间件在一个请求中被调用两次?
【发布时间】:2014-03-09 05:27:30
【问题描述】:

我正在尝试了解 Rack 的工作原理,并且正在测试来自 this rack tutorial 的示例。

该示例创建了一个“hello world”机架应用程序,以及两个微不足道的中间件,然后将它们全部运行:

带有中间件的示例机架应用

这是工作代码,您可以将其保存到名为 app.rb 的文件中,然后在命令行中使用 ruby app.rb 在本地运行它:

require 'rack'
require 'rack/server'

class EnsureJsonResponse
  def initialize(app)
    @app = app
  end

  # Set the 'Accept' header to 'application/json' no matter what.
  # Hopefully the next middleware respects the accept header :)
  def call(env)
    puts "JSON"
    env['HTTP_ACCEPT'] = 'application/json'
    @app.call env
  end
end

class Timer
  def initialize(app)
    @app = app
  end

  def call(env)
    puts "Timer"
    before = Time.now
    status, headers, body = @app.call env

    headers['X-Timing'] = (Time.now - before).to_s

    [status, headers, body]
  end
end

class HelloWorldApp
  def self.call(env)
    puts "HelloWorld"
    [200, {}, ["hello world"]]
  end
end

app = Rack::Builder.new do 
  use Timer # put the timer at the top so it captures everything below it
  use EnsureJsonResponse
  run HelloWorldApp
end

Rack::Server.start :app => app

输出

如果您向网页发出单个请求,您会看到以下内容:

+>ruby app.rb
>> Thin web server (v1.4.1 codename Chromeo)
>> Maximum connections set to 1024
>> Listening on 0.0.0.0:8080, CTRL+C to stop
Timer
JSON
HelloWorld
Timer
JSON
HelloWorld

为什么每个中间件以及底层应用都会在一个请求中被调用两次?

【问题讨论】:

    标签: ruby rack


    【解决方案1】:

    大多数浏览器倾向于请求网站图标。也许您想更改我们的应用程序以找出请求的路径:

    class HelloWorldApp
      def self.call(env)
        puts "HelloWorld"
        puts "requested path: #{env["PATH_INFO"]}"
        [200, {}, ["hello world"]]
      end
    end
    

    【讨论】:

      【解决方案2】:

      我复制了您的应用并在本地运行它。这发生了:

      [2014-03-08 22:01:29] INFO  WEBrick 1.3.1
      [2014-03-08 22:01:29] INFO  ruby 2.0.0 (2013-06-27) [x86_64-darwin13.0.0]
      [2014-03-08 22:01:29] INFO  WEBrick::HTTPServer#start: pid=74593 port=8080
      Timer
      JSON
      HelloWorld
      localhost - - [08/Mar/2014:22:01:33 PST] "GET / HTTP/1.1" 200 11
      - -> /
      Timer
      JSON
      HelloWorld
      localhost - - [08/Mar/2014:22:01:33 PST] "GET /favicon.ico HTTP/1.1" 200 11
      - -> /favicon.ico
      Timer
      JSON
      HelloWorld
      localhost - - [08/Mar/2014:22:01:33 PST] "GET /favicon.ico HTTP/1.1" 200 11
      

      在我看来,您可能看到您的浏览器默默地请求 favicon.ico 文件。这可能吗?


      FWIW,每当我在这么低的级别上调试某些东西时,我总是发现 curl 是一个有用的命令。

      $ curl -i localhost:8080
      HTTP/1.1 200 OK
      X-Timing: 2.7e-05
      Server: WEBrick/1.3.1 (Ruby/2.0.0/2013-06-27)
      Date: Sun, 09 Mar 2014 06:03:58 GMT
      Content-Length: 11
      Connection: Keep-Alive
      
      hello world%
      

      导致服务器打印以下内容:

      [2014-03-08 22:03:49] INFO  WEBrick 1.3.1
      [2014-03-08 22:03:49] INFO  ruby 2.0.0 (2013-06-27) [x86_64-darwin13.0.0]
      [2014-03-08 22:03:49] INFO  WEBrick::HTTPServer#start: pid=74662 port=8080
      Timer
      JSON
      HelloWorld
      localhost - - [08/Mar/2014:22:03:58 PST] "GET / HTTP/1.1" 200 11
      - -> /
      

      嘘!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-08-28
        • 1970-01-01
        • 1970-01-01
        • 2020-05-10
        • 2019-04-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多