代码之家  ›  专栏  ›  技术社区  ›  Jonah

机架:为什么每个中间件在一个请求中调用两次?

  •  0
  • Jonah  · 技术社区  · 10 年前

    我试图了解Rack是如何工作的,我正在测试 this rack tutorial .

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

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

    这是工作代码,您可以将其保存到名为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
    

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

    2 回复  |  直到 10 年前
        1
  •  2
  •   spickermann    10 年前

    大多数浏览器倾向于请求收藏夹图标。也许您想更改我们的应用程序,以了解请求的路径:

    class HelloWorldApp
      def self.call(env)
        puts "HelloWorld"
        puts "requested path: #{env["PATH_INFO"]}"
        [200, {}, ["hello world"]]
      end
    end
    
        2
  •  1
  •   tdooner    10 年前

    我复制了你的应用程序并在本地运行。发生了以下情况:

    [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
    - -> /
    

    呼撒!