thin 1.2.3-x86-mswin32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of thin might be problematic. Click here for more details.
- data/CHANGELOG +263 -0
 - data/COPYING +18 -0
 - data/README +69 -0
 - data/Rakefile +36 -0
 - data/benchmark/abc +51 -0
 - data/benchmark/benchmarker.rb +80 -0
 - data/benchmark/runner +82 -0
 - data/bin/thin +6 -0
 - data/example/adapter.rb +32 -0
 - data/example/async_app.ru +126 -0
 - data/example/async_chat.ru +247 -0
 - data/example/async_tailer.ru +100 -0
 - data/example/config.ru +22 -0
 - data/example/monit_sockets +20 -0
 - data/example/monit_unixsock +20 -0
 - data/example/myapp.rb +1 -0
 - data/example/ramaze.ru +12 -0
 - data/example/thin.god +80 -0
 - data/example/thin_solaris_smf.erb +36 -0
 - data/example/thin_solaris_smf.readme.txt +150 -0
 - data/example/vlad.rake +64 -0
 - data/ext/thin_parser/common.rl +55 -0
 - data/ext/thin_parser/ext_help.h +14 -0
 - data/ext/thin_parser/extconf.rb +6 -0
 - data/ext/thin_parser/parser.c +452 -0
 - data/ext/thin_parser/parser.h +49 -0
 - data/ext/thin_parser/parser.rl +157 -0
 - data/ext/thin_parser/thin.c +433 -0
 - data/lib/rack/adapter/loader.rb +79 -0
 - data/lib/rack/adapter/rails.rb +181 -0
 - data/lib/thin.rb +46 -0
 - data/lib/thin/backends/base.rb +141 -0
 - data/lib/thin/backends/swiftiply_client.rb +56 -0
 - data/lib/thin/backends/tcp_server.rb +29 -0
 - data/lib/thin/backends/unix_server.rb +51 -0
 - data/lib/thin/command.rb +53 -0
 - data/lib/thin/connection.rb +222 -0
 - data/lib/thin/controllers/cluster.rb +127 -0
 - data/lib/thin/controllers/controller.rb +183 -0
 - data/lib/thin/controllers/service.rb +75 -0
 - data/lib/thin/controllers/service.sh.erb +39 -0
 - data/lib/thin/daemonizing.rb +174 -0
 - data/lib/thin/headers.rb +39 -0
 - data/lib/thin/logging.rb +54 -0
 - data/lib/thin/request.rb +153 -0
 - data/lib/thin/response.rb +101 -0
 - data/lib/thin/runner.rb +209 -0
 - data/lib/thin/server.rb +247 -0
 - data/lib/thin/stats.html.erb +216 -0
 - data/lib/thin/stats.rb +52 -0
 - data/lib/thin/statuses.rb +43 -0
 - data/lib/thin/version.rb +32 -0
 - data/lib/thin_parser.so +0 -0
 - data/spec/backends/swiftiply_client_spec.rb +66 -0
 - data/spec/backends/tcp_server_spec.rb +33 -0
 - data/spec/backends/unix_server_spec.rb +37 -0
 - data/spec/command_spec.rb +25 -0
 - data/spec/configs/cluster.yml +9 -0
 - data/spec/configs/single.yml +9 -0
 - data/spec/connection_spec.rb +106 -0
 - data/spec/controllers/cluster_spec.rb +235 -0
 - data/spec/controllers/controller_spec.rb +129 -0
 - data/spec/controllers/service_spec.rb +50 -0
 - data/spec/daemonizing_spec.rb +192 -0
 - data/spec/headers_spec.rb +40 -0
 - data/spec/logging_spec.rb +46 -0
 - data/spec/perf/request_perf_spec.rb +50 -0
 - data/spec/perf/response_perf_spec.rb +19 -0
 - data/spec/perf/server_perf_spec.rb +39 -0
 - data/spec/rack/loader_spec.rb +29 -0
 - data/spec/rack/rails_adapter_spec.rb +106 -0
 - data/spec/rails_app/app/controllers/application.rb +10 -0
 - data/spec/rails_app/app/controllers/simple_controller.rb +19 -0
 - data/spec/rails_app/app/helpers/application_helper.rb +3 -0
 - data/spec/rails_app/app/views/simple/index.html.erb +15 -0
 - data/spec/rails_app/config/boot.rb +109 -0
 - data/spec/rails_app/config/environment.rb +64 -0
 - data/spec/rails_app/config/environments/development.rb +18 -0
 - data/spec/rails_app/config/environments/production.rb +19 -0
 - data/spec/rails_app/config/environments/test.rb +22 -0
 - data/spec/rails_app/config/initializers/inflections.rb +10 -0
 - data/spec/rails_app/config/initializers/mime_types.rb +5 -0
 - data/spec/rails_app/config/routes.rb +35 -0
 - data/spec/rails_app/public/404.html +30 -0
 - data/spec/rails_app/public/422.html +30 -0
 - data/spec/rails_app/public/500.html +30 -0
 - data/spec/rails_app/public/dispatch.cgi +10 -0
 - data/spec/rails_app/public/dispatch.fcgi +24 -0
 - data/spec/rails_app/public/dispatch.rb +10 -0
 - data/spec/rails_app/public/favicon.ico +0 -0
 - data/spec/rails_app/public/images/rails.png +0 -0
 - data/spec/rails_app/public/index.html +277 -0
 - data/spec/rails_app/public/javascripts/application.js +2 -0
 - data/spec/rails_app/public/javascripts/controls.js +963 -0
 - data/spec/rails_app/public/javascripts/dragdrop.js +972 -0
 - data/spec/rails_app/public/javascripts/effects.js +1120 -0
 - data/spec/rails_app/public/javascripts/prototype.js +4225 -0
 - data/spec/rails_app/public/robots.txt +5 -0
 - data/spec/rails_app/script/about +3 -0
 - data/spec/rails_app/script/console +3 -0
 - data/spec/rails_app/script/destroy +3 -0
 - data/spec/rails_app/script/generate +3 -0
 - data/spec/rails_app/script/performance/benchmarker +3 -0
 - data/spec/rails_app/script/performance/profiler +3 -0
 - data/spec/rails_app/script/performance/request +3 -0
 - data/spec/rails_app/script/plugin +3 -0
 - data/spec/rails_app/script/process/inspector +3 -0
 - data/spec/rails_app/script/process/reaper +3 -0
 - data/spec/rails_app/script/process/spawner +3 -0
 - data/spec/rails_app/script/runner +3 -0
 - data/spec/rails_app/script/server +3 -0
 - data/spec/request/mongrel_spec.rb +39 -0
 - data/spec/request/parser_spec.rb +215 -0
 - data/spec/request/persistent_spec.rb +35 -0
 - data/spec/request/processing_spec.rb +45 -0
 - data/spec/response_spec.rb +91 -0
 - data/spec/runner_spec.rb +168 -0
 - data/spec/server/builder_spec.rb +44 -0
 - data/spec/server/pipelining_spec.rb +110 -0
 - data/spec/server/robustness_spec.rb +34 -0
 - data/spec/server/stopping_spec.rb +55 -0
 - data/spec/server/swiftiply.yml +6 -0
 - data/spec/server/swiftiply_spec.rb +32 -0
 - data/spec/server/tcp_spec.rb +57 -0
 - data/spec/server/threaded_spec.rb +27 -0
 - data/spec/server/unix_socket_spec.rb +26 -0
 - data/spec/server_spec.rb +96 -0
 - data/spec/spec_helper.rb +219 -0
 - data/tasks/announce.rake +22 -0
 - data/tasks/deploy.rake +13 -0
 - data/tasks/email.erb +30 -0
 - data/tasks/gem.rake +74 -0
 - data/tasks/rdoc.rake +25 -0
 - data/tasks/site.rake +15 -0
 - data/tasks/spec.rake +49 -0
 - data/tasks/stats.rake +28 -0
 - metadata +246 -0
 
    
        data/lib/thin/server.rb
    ADDED
    
    | 
         @@ -0,0 +1,247 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Thin
         
     | 
| 
      
 2 
     | 
    
         
            +
              # The uterly famous Thin HTTP server.
         
     | 
| 
      
 3 
     | 
    
         
            +
              # It listen for incoming request through a given +backend+
         
     | 
| 
      
 4 
     | 
    
         
            +
              # and forward all request to +app+.
         
     | 
| 
      
 5 
     | 
    
         
            +
              #
         
     | 
| 
      
 6 
     | 
    
         
            +
              # == TCP server
         
     | 
| 
      
 7 
     | 
    
         
            +
              # Create a new TCP server on bound to <tt>host:port</tt> by specifiying +host+
         
     | 
| 
      
 8 
     | 
    
         
            +
              # and +port+ as the first 2 arguments.
         
     | 
| 
      
 9 
     | 
    
         
            +
              #
         
     | 
| 
      
 10 
     | 
    
         
            +
              #   Thin::Server.start('0.0.0.0', 3000, app)
         
     | 
| 
      
 11 
     | 
    
         
            +
              #
         
     | 
| 
      
 12 
     | 
    
         
            +
              # == UNIX domain server
         
     | 
| 
      
 13 
     | 
    
         
            +
              # Create a new UNIX domain socket bound to +socket+ file by specifiying a filename
         
     | 
| 
      
 14 
     | 
    
         
            +
              # as the first argument. Eg.: /tmp/thin.sock. If the first argument contains a <tt>/</tt>
         
     | 
| 
      
 15 
     | 
    
         
            +
              # it will be assumed to be a UNIX socket. 
         
     | 
| 
      
 16 
     | 
    
         
            +
              #
         
     | 
| 
      
 17 
     | 
    
         
            +
              #   Thin::Server.start('/tmp/thin.sock', app)
         
     | 
| 
      
 18 
     | 
    
         
            +
              #
         
     | 
| 
      
 19 
     | 
    
         
            +
              # == Using a custom backend
         
     | 
| 
      
 20 
     | 
    
         
            +
              # You can implement your own way to connect the server to its client by creating your
         
     | 
| 
      
 21 
     | 
    
         
            +
              # own Backend class and pass it as the :backend option.
         
     | 
| 
      
 22 
     | 
    
         
            +
              #
         
     | 
| 
      
 23 
     | 
    
         
            +
              #   Thin::Server.start('galaxy://faraway', 1345, app, :backend => Thin::Backends::MyFancyBackend)
         
     | 
| 
      
 24 
     | 
    
         
            +
              #
         
     | 
| 
      
 25 
     | 
    
         
            +
              # == Rack application (+app+)
         
     | 
| 
      
 26 
     | 
    
         
            +
              # All requests will be processed through +app+ that must be a valid Rack adapter.
         
     | 
| 
      
 27 
     | 
    
         
            +
              # A valid Rack adapter (application) must respond to <tt>call(env#Hash)</tt> and
         
     | 
| 
      
 28 
     | 
    
         
            +
              # return an array of <tt>[status, headers, body]</tt>.
         
     | 
| 
      
 29 
     | 
    
         
            +
              #
         
     | 
| 
      
 30 
     | 
    
         
            +
              # == Building an app in place
         
     | 
| 
      
 31 
     | 
    
         
            +
              # If a block is passed, a <tt>Rack::Builder</tt> instance
         
     | 
| 
      
 32 
     | 
    
         
            +
              # will be passed to build the +app+. So you can do cool stuff like this:
         
     | 
| 
      
 33 
     | 
    
         
            +
              # 
         
     | 
| 
      
 34 
     | 
    
         
            +
              #   Thin::Server.start('0.0.0.0', 3000) do
         
     | 
| 
      
 35 
     | 
    
         
            +
              #     use Rack::CommonLogger
         
     | 
| 
      
 36 
     | 
    
         
            +
              #     use Rack::ShowExceptions
         
     | 
| 
      
 37 
     | 
    
         
            +
              #     map "/lobster" do
         
     | 
| 
      
 38 
     | 
    
         
            +
              #       use Rack::Lint
         
     | 
| 
      
 39 
     | 
    
         
            +
              #       run Rack::Lobster.new
         
     | 
| 
      
 40 
     | 
    
         
            +
              #     end
         
     | 
| 
      
 41 
     | 
    
         
            +
              #   end
         
     | 
| 
      
 42 
     | 
    
         
            +
              #
         
     | 
| 
      
 43 
     | 
    
         
            +
              # == Controlling with signals
         
     | 
| 
      
 44 
     | 
    
         
            +
              # * QUIT: Gracefull shutdown (see Server#stop)
         
     | 
| 
      
 45 
     | 
    
         
            +
              # * INT and TERM: Force shutdown (see Server#stop!)
         
     | 
| 
      
 46 
     | 
    
         
            +
              # Disable signals by passing <tt>:signals => false</tt>
         
     | 
| 
      
 47 
     | 
    
         
            +
              # 
         
     | 
| 
      
 48 
     | 
    
         
            +
              class Server
         
     | 
| 
      
 49 
     | 
    
         
            +
                include Logging
         
     | 
| 
      
 50 
     | 
    
         
            +
                include Daemonizable
         
     | 
| 
      
 51 
     | 
    
         
            +
                extend  Forwardable
         
     | 
| 
      
 52 
     | 
    
         
            +
                
         
     | 
| 
      
 53 
     | 
    
         
            +
                # Default values
         
     | 
| 
      
 54 
     | 
    
         
            +
                DEFAULT_TIMEOUT                        = 30 #sec
         
     | 
| 
      
 55 
     | 
    
         
            +
                DEFAULT_HOST                           = '0.0.0.0'
         
     | 
| 
      
 56 
     | 
    
         
            +
                DEFAULT_PORT                           = 3000
         
     | 
| 
      
 57 
     | 
    
         
            +
                DEFAULT_MAXIMUM_CONNECTIONS            = 1024
         
     | 
| 
      
 58 
     | 
    
         
            +
                DEFAULT_MAXIMUM_PERSISTENT_CONNECTIONS = 512
         
     | 
| 
      
 59 
     | 
    
         
            +
                    
         
     | 
| 
      
 60 
     | 
    
         
            +
                # Application (Rack adapter) called with the request that produces the response.
         
     | 
| 
      
 61 
     | 
    
         
            +
                attr_accessor :app
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                # A tag that will show in the process listing
         
     | 
| 
      
 64 
     | 
    
         
            +
                attr_accessor :tag
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                # Backend handling the connections to the clients.
         
     | 
| 
      
 67 
     | 
    
         
            +
                attr_accessor :backend
         
     | 
| 
      
 68 
     | 
    
         
            +
                
         
     | 
| 
      
 69 
     | 
    
         
            +
                # Maximum number of seconds for incoming data to arrive before the connection
         
     | 
| 
      
 70 
     | 
    
         
            +
                # is dropped.
         
     | 
| 
      
 71 
     | 
    
         
            +
                def_delegators :backend, :timeout, :timeout=
         
     | 
| 
      
 72 
     | 
    
         
            +
                
         
     | 
| 
      
 73 
     | 
    
         
            +
                # Maximum number of file or socket descriptors that the server may open.
         
     | 
| 
      
 74 
     | 
    
         
            +
                def_delegators :backend, :maximum_connections, :maximum_connections=
         
     | 
| 
      
 75 
     | 
    
         
            +
                
         
     | 
| 
      
 76 
     | 
    
         
            +
                # Maximum number of connection that can be persistent at the same time.
         
     | 
| 
      
 77 
     | 
    
         
            +
                # Most browser never close the connection so most of the time they are closed
         
     | 
| 
      
 78 
     | 
    
         
            +
                # when the timeout occur. If we don't control the number of persistent connection,
         
     | 
| 
      
 79 
     | 
    
         
            +
                # if would be very easy to overflow the server for a DoS attack.
         
     | 
| 
      
 80 
     | 
    
         
            +
                def_delegators :backend, :maximum_persistent_connections, :maximum_persistent_connections=
         
     | 
| 
      
 81 
     | 
    
         
            +
                
         
     | 
| 
      
 82 
     | 
    
         
            +
                # Allow using threads in the backend.
         
     | 
| 
      
 83 
     | 
    
         
            +
                def_delegators :backend, :threaded?, :threaded=
         
     | 
| 
      
 84 
     | 
    
         
            +
                
         
     | 
| 
      
 85 
     | 
    
         
            +
                # Address and port on which the server is listening for connections.
         
     | 
| 
      
 86 
     | 
    
         
            +
                def_delegators :backend, :host, :port
         
     | 
| 
      
 87 
     | 
    
         
            +
                
         
     | 
| 
      
 88 
     | 
    
         
            +
                # UNIX domain socket on which the server is listening for connections.
         
     | 
| 
      
 89 
     | 
    
         
            +
                def_delegator :backend, :socket
         
     | 
| 
      
 90 
     | 
    
         
            +
                
         
     | 
| 
      
 91 
     | 
    
         
            +
                # Disable the use of epoll under Linux
         
     | 
| 
      
 92 
     | 
    
         
            +
                def_delegators :backend, :no_epoll, :no_epoll=
         
     | 
| 
      
 93 
     | 
    
         
            +
                
         
     | 
| 
      
 94 
     | 
    
         
            +
                def initialize(*args, &block)
         
     | 
| 
      
 95 
     | 
    
         
            +
                  host, port, options = DEFAULT_HOST, DEFAULT_PORT, {}
         
     | 
| 
      
 96 
     | 
    
         
            +
                  
         
     | 
| 
      
 97 
     | 
    
         
            +
                  # Guess each parameter by its type so they can be
         
     | 
| 
      
 98 
     | 
    
         
            +
                  # received in any order.
         
     | 
| 
      
 99 
     | 
    
         
            +
                  args.each do |arg|
         
     | 
| 
      
 100 
     | 
    
         
            +
                    case arg
         
     | 
| 
      
 101 
     | 
    
         
            +
                    when Fixnum, /^\d+$/ then port    = arg.to_i
         
     | 
| 
      
 102 
     | 
    
         
            +
                    when String          then host    = arg
         
     | 
| 
      
 103 
     | 
    
         
            +
                    when Hash            then options = arg
         
     | 
| 
      
 104 
     | 
    
         
            +
                    else
         
     | 
| 
      
 105 
     | 
    
         
            +
                      @app = arg if arg.respond_to?(:call)
         
     | 
| 
      
 106 
     | 
    
         
            +
                    end
         
     | 
| 
      
 107 
     | 
    
         
            +
                  end
         
     | 
| 
      
 108 
     | 
    
         
            +
                  
         
     | 
| 
      
 109 
     | 
    
         
            +
                  # Set tag if needed
         
     | 
| 
      
 110 
     | 
    
         
            +
                  self.tag = options[:tag]
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                  # Try to intelligently select which backend to use.
         
     | 
| 
      
 113 
     | 
    
         
            +
                  @backend = select_backend(host, port, options)
         
     | 
| 
      
 114 
     | 
    
         
            +
                  
         
     | 
| 
      
 115 
     | 
    
         
            +
                  load_cgi_multipart_eof_fix
         
     | 
| 
      
 116 
     | 
    
         
            +
                  
         
     | 
| 
      
 117 
     | 
    
         
            +
                  @backend.server = self
         
     | 
| 
      
 118 
     | 
    
         
            +
                  
         
     | 
| 
      
 119 
     | 
    
         
            +
                  # Set defaults
         
     | 
| 
      
 120 
     | 
    
         
            +
                  @backend.maximum_connections            = DEFAULT_MAXIMUM_CONNECTIONS
         
     | 
| 
      
 121 
     | 
    
         
            +
                  @backend.maximum_persistent_connections = DEFAULT_MAXIMUM_PERSISTENT_CONNECTIONS
         
     | 
| 
      
 122 
     | 
    
         
            +
                  @backend.timeout                        = DEFAULT_TIMEOUT
         
     | 
| 
      
 123 
     | 
    
         
            +
                  
         
     | 
| 
      
 124 
     | 
    
         
            +
                  # Allow using Rack builder as a block
         
     | 
| 
      
 125 
     | 
    
         
            +
                  @app = Rack::Builder.new(&block).to_app if block
         
     | 
| 
      
 126 
     | 
    
         
            +
                  
         
     | 
| 
      
 127 
     | 
    
         
            +
                  # If in debug mode, wrap in logger adapter
         
     | 
| 
      
 128 
     | 
    
         
            +
                  @app = Rack::CommonLogger.new(@app) if Logging.debug?
         
     | 
| 
      
 129 
     | 
    
         
            +
                  
         
     | 
| 
      
 130 
     | 
    
         
            +
                  setup_signals unless options[:signals].class == FalseClass
         
     | 
| 
      
 131 
     | 
    
         
            +
                end
         
     | 
| 
      
 132 
     | 
    
         
            +
                
         
     | 
| 
      
 133 
     | 
    
         
            +
                # Lil' shortcut to turn this:
         
     | 
| 
      
 134 
     | 
    
         
            +
                # 
         
     | 
| 
      
 135 
     | 
    
         
            +
                #   Server.new(...).start
         
     | 
| 
      
 136 
     | 
    
         
            +
                # 
         
     | 
| 
      
 137 
     | 
    
         
            +
                # into this:
         
     | 
| 
      
 138 
     | 
    
         
            +
                # 
         
     | 
| 
      
 139 
     | 
    
         
            +
                #   Server.start(...)
         
     | 
| 
      
 140 
     | 
    
         
            +
                # 
         
     | 
| 
      
 141 
     | 
    
         
            +
                def self.start(*args, &block)
         
     | 
| 
      
 142 
     | 
    
         
            +
                  new(*args, &block).start!
         
     | 
| 
      
 143 
     | 
    
         
            +
                end
         
     | 
| 
      
 144 
     | 
    
         
            +
                    
         
     | 
| 
      
 145 
     | 
    
         
            +
                # Start the server and listen for connections.
         
     | 
| 
      
 146 
     | 
    
         
            +
                def start
         
     | 
| 
      
 147 
     | 
    
         
            +
                  raise ArgumentError, 'app required' unless @app
         
     | 
| 
      
 148 
     | 
    
         
            +
                  
         
     | 
| 
      
 149 
     | 
    
         
            +
                  log   ">> Thin web server (v#{VERSION::STRING} codename #{VERSION::CODENAME})"
         
     | 
| 
      
 150 
     | 
    
         
            +
                  debug ">> Debugging ON"
         
     | 
| 
      
 151 
     | 
    
         
            +
                  trace ">> Tracing ON"
         
     | 
| 
      
 152 
     | 
    
         
            +
                  
         
     | 
| 
      
 153 
     | 
    
         
            +
                  log ">> Maximum connections set to #{@backend.maximum_connections}"
         
     | 
| 
      
 154 
     | 
    
         
            +
                  log ">> Listening on #{@backend}, CTRL+C to stop"
         
     | 
| 
      
 155 
     | 
    
         
            +
                  
         
     | 
| 
      
 156 
     | 
    
         
            +
                  @backend.start
         
     | 
| 
      
 157 
     | 
    
         
            +
                end
         
     | 
| 
      
 158 
     | 
    
         
            +
                alias :start! :start
         
     | 
| 
      
 159 
     | 
    
         
            +
                
         
     | 
| 
      
 160 
     | 
    
         
            +
                # == Gracefull shutdown
         
     | 
| 
      
 161 
     | 
    
         
            +
                # Stops the server after processing all current connections.
         
     | 
| 
      
 162 
     | 
    
         
            +
                # As soon as this method is called, the server stops accepting
         
     | 
| 
      
 163 
     | 
    
         
            +
                # new requests and wait for all current connections to finish.
         
     | 
| 
      
 164 
     | 
    
         
            +
                # Calling twice is the equivalent of calling <tt>stop!</tt>.
         
     | 
| 
      
 165 
     | 
    
         
            +
                def stop
         
     | 
| 
      
 166 
     | 
    
         
            +
                  if running?
         
     | 
| 
      
 167 
     | 
    
         
            +
                    @backend.stop
         
     | 
| 
      
 168 
     | 
    
         
            +
                    unless @backend.empty?
         
     | 
| 
      
 169 
     | 
    
         
            +
                      log ">> Waiting for #{@backend.size} connection(s) to finish, " +
         
     | 
| 
      
 170 
     | 
    
         
            +
                             "can take up to #{timeout} sec, CTRL+C to stop now"
         
     | 
| 
      
 171 
     | 
    
         
            +
                    end
         
     | 
| 
      
 172 
     | 
    
         
            +
                  else
         
     | 
| 
      
 173 
     | 
    
         
            +
                    stop!
         
     | 
| 
      
 174 
     | 
    
         
            +
                  end
         
     | 
| 
      
 175 
     | 
    
         
            +
                end
         
     | 
| 
      
 176 
     | 
    
         
            +
                
         
     | 
| 
      
 177 
     | 
    
         
            +
                # == Force shutdown
         
     | 
| 
      
 178 
     | 
    
         
            +
                # Stops the server closing all current connections right away.
         
     | 
| 
      
 179 
     | 
    
         
            +
                # This doesn't wait for connection to finish their work and send data.
         
     | 
| 
      
 180 
     | 
    
         
            +
                # All current requests will be dropped.
         
     | 
| 
      
 181 
     | 
    
         
            +
                def stop!
         
     | 
| 
      
 182 
     | 
    
         
            +
                  log ">> Stopping ..."
         
     | 
| 
      
 183 
     | 
    
         
            +
             
     | 
| 
      
 184 
     | 
    
         
            +
                  @backend.stop!
         
     | 
| 
      
 185 
     | 
    
         
            +
                end
         
     | 
| 
      
 186 
     | 
    
         
            +
                
         
     | 
| 
      
 187 
     | 
    
         
            +
                # == Configure the server
         
     | 
| 
      
 188 
     | 
    
         
            +
                # The process might need to have superuser privilege to configure
         
     | 
| 
      
 189 
     | 
    
         
            +
                # server with optimal options.
         
     | 
| 
      
 190 
     | 
    
         
            +
                def config
         
     | 
| 
      
 191 
     | 
    
         
            +
                  @backend.config
         
     | 
| 
      
 192 
     | 
    
         
            +
                end
         
     | 
| 
      
 193 
     | 
    
         
            +
                
         
     | 
| 
      
 194 
     | 
    
         
            +
                # Name of the server and type of backend used.
         
     | 
| 
      
 195 
     | 
    
         
            +
                # This is also the name of the process in which Thin is running as a daemon.
         
     | 
| 
      
 196 
     | 
    
         
            +
                def name
         
     | 
| 
      
 197 
     | 
    
         
            +
                  "thin server (#{@backend})" + (tag ? " [#{tag}]" : "")
         
     | 
| 
      
 198 
     | 
    
         
            +
                end
         
     | 
| 
      
 199 
     | 
    
         
            +
                alias :to_s :name
         
     | 
| 
      
 200 
     | 
    
         
            +
                
         
     | 
| 
      
 201 
     | 
    
         
            +
                # Return +true+ if the server is running and ready to receive requests.
         
     | 
| 
      
 202 
     | 
    
         
            +
                # Note that the server might still be running and return +false+ when
         
     | 
| 
      
 203 
     | 
    
         
            +
                # shuting down and waiting for active connections to complete.
         
     | 
| 
      
 204 
     | 
    
         
            +
                def running?
         
     | 
| 
      
 205 
     | 
    
         
            +
                  @backend.running?
         
     | 
| 
      
 206 
     | 
    
         
            +
                end
         
     | 
| 
      
 207 
     | 
    
         
            +
                
         
     | 
| 
      
 208 
     | 
    
         
            +
                protected
         
     | 
| 
      
 209 
     | 
    
         
            +
                  # Register signals:
         
     | 
| 
      
 210 
     | 
    
         
            +
                  # * INT calls +stop+ to shutdown gracefully.
         
     | 
| 
      
 211 
     | 
    
         
            +
                  # * TERM calls <tt>stop!</tt> to force shutdown.    
         
     | 
| 
      
 212 
     | 
    
         
            +
                  def setup_signals
         
     | 
| 
      
 213 
     | 
    
         
            +
                    trap('QUIT') { stop }  unless Thin.win?
         
     | 
| 
      
 214 
     | 
    
         
            +
                    trap('INT')  { stop! }
         
     | 
| 
      
 215 
     | 
    
         
            +
                    trap('TERM') { stop! }
         
     | 
| 
      
 216 
     | 
    
         
            +
                  end
         
     | 
| 
      
 217 
     | 
    
         
            +
                  
         
     | 
| 
      
 218 
     | 
    
         
            +
                  def select_backend(host, port, options)
         
     | 
| 
      
 219 
     | 
    
         
            +
                    case
         
     | 
| 
      
 220 
     | 
    
         
            +
                    when options.has_key?(:backend)
         
     | 
| 
      
 221 
     | 
    
         
            +
                      raise ArgumentError, ":backend must be a class" unless options[:backend].is_a?(Class)
         
     | 
| 
      
 222 
     | 
    
         
            +
                      options[:backend].new(host, port, options)
         
     | 
| 
      
 223 
     | 
    
         
            +
                    when options.has_key?(:swiftiply)
         
     | 
| 
      
 224 
     | 
    
         
            +
                      Backends::SwiftiplyClient.new(host, port, options)
         
     | 
| 
      
 225 
     | 
    
         
            +
                    when host.include?('/')
         
     | 
| 
      
 226 
     | 
    
         
            +
                      Backends::UnixServer.new(host)
         
     | 
| 
      
 227 
     | 
    
         
            +
                    else
         
     | 
| 
      
 228 
     | 
    
         
            +
                      Backends::TcpServer.new(host, port)
         
     | 
| 
      
 229 
     | 
    
         
            +
                    end
         
     | 
| 
      
 230 
     | 
    
         
            +
                  end
         
     | 
| 
      
 231 
     | 
    
         
            +
                  
         
     | 
| 
      
 232 
     | 
    
         
            +
                  # Taken from Mongrel cgi_multipart_eof_fix
         
     | 
| 
      
 233 
     | 
    
         
            +
                  # Ruby 1.8.5 has a security bug in cgi.rb, we need to patch it.
         
     | 
| 
      
 234 
     | 
    
         
            +
                  def load_cgi_multipart_eof_fix
         
     | 
| 
      
 235 
     | 
    
         
            +
                    version = RUBY_VERSION.split('.').map { |i| i.to_i }
         
     | 
| 
      
 236 
     | 
    
         
            +
                    
         
     | 
| 
      
 237 
     | 
    
         
            +
                    if version[0] <= 1 && version[1] <= 8 && version[2] <= 5 && RUBY_PLATFORM !~ /java/
         
     | 
| 
      
 238 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 239 
     | 
    
         
            +
                        require 'cgi_multipart_eof_fix'
         
     | 
| 
      
 240 
     | 
    
         
            +
                      rescue LoadError
         
     | 
| 
      
 241 
     | 
    
         
            +
                        log "!! Ruby 1.8.5 is not secure please install cgi_multipart_eof_fix:"
         
     | 
| 
      
 242 
     | 
    
         
            +
                        log "   gem install cgi_multipart_eof_fix"
         
     | 
| 
      
 243 
     | 
    
         
            +
                      end
         
     | 
| 
      
 244 
     | 
    
         
            +
                    end
         
     | 
| 
      
 245 
     | 
    
         
            +
                  end
         
     | 
| 
      
 246 
     | 
    
         
            +
              end
         
     | 
| 
      
 247 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,216 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            <%#
         
     | 
| 
      
 2 
     | 
    
         
            +
            # Taken from Rack::ShowException
         
     | 
| 
      
 3 
     | 
    
         
            +
            # adapted from Django <djangoproject.com>
         
     | 
| 
      
 4 
     | 
    
         
            +
            # Copyright (c) 2005, the Lawrence Journal-World
         
     | 
| 
      
 5 
     | 
    
         
            +
            # Used under the modified BSD license:
         
     | 
| 
      
 6 
     | 
    
         
            +
            # http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5
         
     | 
| 
      
 7 
     | 
    
         
            +
            %>
         
     | 
| 
      
 8 
     | 
    
         
            +
            <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
         
     | 
| 
      
 9 
     | 
    
         
            +
            <html lang="en">
         
     | 
| 
      
 10 
     | 
    
         
            +
            <head>
         
     | 
| 
      
 11 
     | 
    
         
            +
              <meta http-equiv="content-type" content="text/html; charset=utf-8" />
         
     | 
| 
      
 12 
     | 
    
         
            +
              <meta name="robots" content="NONE,NOARCHIVE" />
         
     | 
| 
      
 13 
     | 
    
         
            +
              <title>Thin Stats</title>
         
     | 
| 
      
 14 
     | 
    
         
            +
              <style type="text/css">
         
     | 
| 
      
 15 
     | 
    
         
            +
                html * { padding:0; margin:0; }
         
     | 
| 
      
 16 
     | 
    
         
            +
                body * { padding:10px 20px; }
         
     | 
| 
      
 17 
     | 
    
         
            +
                body * * { padding:0; }
         
     | 
| 
      
 18 
     | 
    
         
            +
                body { font:small sans-serif; }
         
     | 
| 
      
 19 
     | 
    
         
            +
                body>div { border-bottom:1px solid #ddd; }
         
     | 
| 
      
 20 
     | 
    
         
            +
                h1 { font-weight:normal; }
         
     | 
| 
      
 21 
     | 
    
         
            +
                h2 { margin-bottom:.8em; }
         
     | 
| 
      
 22 
     | 
    
         
            +
                h2 span { font-size:80%; color:#666; font-weight:normal; }
         
     | 
| 
      
 23 
     | 
    
         
            +
                h3 { margin:1em 0 .5em 0; }
         
     | 
| 
      
 24 
     | 
    
         
            +
                h4 { margin:0 0 .5em 0; font-weight: normal; }
         
     | 
| 
      
 25 
     | 
    
         
            +
                table {
         
     | 
| 
      
 26 
     | 
    
         
            +
                    border:1px solid #ccc; border-collapse: collapse; background:white; }
         
     | 
| 
      
 27 
     | 
    
         
            +
                tbody td, tbody th { vertical-align:top; padding:2px 3px; }
         
     | 
| 
      
 28 
     | 
    
         
            +
                thead th {
         
     | 
| 
      
 29 
     | 
    
         
            +
                    padding:1px 6px 1px 3px; background:#fefefe; text-align:left;
         
     | 
| 
      
 30 
     | 
    
         
            +
                    font-weight:normal; font-size:11px; border:1px solid #ddd; }
         
     | 
| 
      
 31 
     | 
    
         
            +
                tbody th { text-align:right; color:#666; padding-right:.5em; }
         
     | 
| 
      
 32 
     | 
    
         
            +
                table.vars { margin:5px 0 2px 40px; }
         
     | 
| 
      
 33 
     | 
    
         
            +
                table.vars td, table.req td { font-family:monospace; }
         
     | 
| 
      
 34 
     | 
    
         
            +
                table td.code { width:100%;}
         
     | 
| 
      
 35 
     | 
    
         
            +
                table td.code div { overflow:hidden; }
         
     | 
| 
      
 36 
     | 
    
         
            +
                table.source th { color:#666; }
         
     | 
| 
      
 37 
     | 
    
         
            +
                table.source td {
         
     | 
| 
      
 38 
     | 
    
         
            +
                    font-family:monospace; white-space:pre; border-bottom:1px solid #eee; }
         
     | 
| 
      
 39 
     | 
    
         
            +
                ul.traceback { list-style-type:none; }
         
     | 
| 
      
 40 
     | 
    
         
            +
                ul.traceback li.frame { margin-bottom:1em; }
         
     | 
| 
      
 41 
     | 
    
         
            +
                div.context { margin: 10px 0; }
         
     | 
| 
      
 42 
     | 
    
         
            +
                div.context ol {
         
     | 
| 
      
 43 
     | 
    
         
            +
                    padding-left:30px; margin:0 10px; list-style-position: inside; }
         
     | 
| 
      
 44 
     | 
    
         
            +
                div.context ol li {
         
     | 
| 
      
 45 
     | 
    
         
            +
                    font-family:monospace; white-space:pre; color:#666; cursor:pointer; }
         
     | 
| 
      
 46 
     | 
    
         
            +
                div.context ol.context-line li { color:black; background-color:#ccc; }
         
     | 
| 
      
 47 
     | 
    
         
            +
                div.context ol.context-line li span { float: right; }
         
     | 
| 
      
 48 
     | 
    
         
            +
                div.commands { margin-left: 40px; }
         
     | 
| 
      
 49 
     | 
    
         
            +
                div.commands a { color:black; text-decoration:none; }
         
     | 
| 
      
 50 
     | 
    
         
            +
                #summary { background: #ffc; }
         
     | 
| 
      
 51 
     | 
    
         
            +
                #summary h2 { font-weight: normal; color: #666; }
         
     | 
| 
      
 52 
     | 
    
         
            +
                #summary ul#quicklinks { list-style-type: none; margin-bottom: 2em; }
         
     | 
| 
      
 53 
     | 
    
         
            +
                #summary ul#quicklinks li { float: left; padding: 0 1em; }
         
     | 
| 
      
 54 
     | 
    
         
            +
                #summary ul#quicklinks>li+li { border-left: 1px #666 solid; }
         
     | 
| 
      
 55 
     | 
    
         
            +
                #explanation { background:#eee; }
         
     | 
| 
      
 56 
     | 
    
         
            +
                #template, #template-not-exist { background:#f6f6f6; }
         
     | 
| 
      
 57 
     | 
    
         
            +
                #template-not-exist ul { margin: 0 0 0 20px; }
         
     | 
| 
      
 58 
     | 
    
         
            +
                #traceback { background:#eee; }
         
     | 
| 
      
 59 
     | 
    
         
            +
                #summary table { border:none; background:transparent; }
         
     | 
| 
      
 60 
     | 
    
         
            +
                #requests { background:#f6f6f6; padding-left:120px; }
         
     | 
| 
      
 61 
     | 
    
         
            +
                #requests h2, #requests h3 { position:relative; margin-left:-100px; }
         
     | 
| 
      
 62 
     | 
    
         
            +
                #requests h3 { margin-bottom:-1em; }
         
     | 
| 
      
 63 
     | 
    
         
            +
                .error { background: #ffc; }
         
     | 
| 
      
 64 
     | 
    
         
            +
                .specific { color:#cc3300; font-weight:bold; }
         
     | 
| 
      
 65 
     | 
    
         
            +
              </style>
         
     | 
| 
      
 66 
     | 
    
         
            +
            </head>
         
     | 
| 
      
 67 
     | 
    
         
            +
            <body>
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
            <div id="summary">
         
     | 
| 
      
 70 
     | 
    
         
            +
              <h1>Server stats</h1>
         
     | 
| 
      
 71 
     | 
    
         
            +
              <h2><%= Thin::SERVER %></h2>
         
     | 
| 
      
 72 
     | 
    
         
            +
              <table>
         
     | 
| 
      
 73 
     | 
    
         
            +
                <tr>
         
     | 
| 
      
 74 
     | 
    
         
            +
                  <th>Uptime</th>
         
     | 
| 
      
 75 
     | 
    
         
            +
                  <td><%= Time.now - @start_time %> sec</td>
         
     | 
| 
      
 76 
     | 
    
         
            +
                </tr>
         
     | 
| 
      
 77 
     | 
    
         
            +
                <tr>
         
     | 
| 
      
 78 
     | 
    
         
            +
                  <th>PID</th>
         
     | 
| 
      
 79 
     | 
    
         
            +
                  <td><%=h Process.pid %></td>
         
     | 
| 
      
 80 
     | 
    
         
            +
                </tr>
         
     | 
| 
      
 81 
     | 
    
         
            +
              </table>
         
     | 
| 
      
 82 
     | 
    
         
            +
              
         
     | 
| 
      
 83 
     | 
    
         
            +
              <% if @last_request %>
         
     | 
| 
      
 84 
     | 
    
         
            +
                <h3>Jump to:</h3>
         
     | 
| 
      
 85 
     | 
    
         
            +
                <ul id="quicklinks">
         
     | 
| 
      
 86 
     | 
    
         
            +
                  <li><a href="#get-info">GET</a></li>
         
     | 
| 
      
 87 
     | 
    
         
            +
                  <li><a href="#post-info">POST</a></li>
         
     | 
| 
      
 88 
     | 
    
         
            +
                  <li><a href="#cookie-info">Cookies</a></li>
         
     | 
| 
      
 89 
     | 
    
         
            +
                  <li><a href="#env-info">ENV</a></li>
         
     | 
| 
      
 90 
     | 
    
         
            +
                </ul>
         
     | 
| 
      
 91 
     | 
    
         
            +
              <% end %>
         
     | 
| 
      
 92 
     | 
    
         
            +
            </div>
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
            <div id="stats">
         
     | 
| 
      
 95 
     | 
    
         
            +
              <h2>Requests</h2>
         
     | 
| 
      
 96 
     | 
    
         
            +
              <h3>Stats</h3>
         
     | 
| 
      
 97 
     | 
    
         
            +
              <table class="req">
         
     | 
| 
      
 98 
     | 
    
         
            +
                <tr>
         
     | 
| 
      
 99 
     | 
    
         
            +
                  <td>Requests</td>
         
     | 
| 
      
 100 
     | 
    
         
            +
                  <td><%= @requests %></td>
         
     | 
| 
      
 101 
     | 
    
         
            +
                </tr>
         
     | 
| 
      
 102 
     | 
    
         
            +
                <tr>
         
     | 
| 
      
 103 
     | 
    
         
            +
                  <td>Finished</td>
         
     | 
| 
      
 104 
     | 
    
         
            +
                  <td><%= @requests_finished %></td>
         
     | 
| 
      
 105 
     | 
    
         
            +
                </tr>
         
     | 
| 
      
 106 
     | 
    
         
            +
                <tr>
         
     | 
| 
      
 107 
     | 
    
         
            +
                  <td>Errors</td>
         
     | 
| 
      
 108 
     | 
    
         
            +
                  <td><%= @requests - @requests_finished %></td>
         
     | 
| 
      
 109 
     | 
    
         
            +
                </tr>
         
     | 
| 
      
 110 
     | 
    
         
            +
                <tr>
         
     | 
| 
      
 111 
     | 
    
         
            +
                  <td>Last request</td>
         
     | 
| 
      
 112 
     | 
    
         
            +
                  <td><%= @last_request_time %> sec</td>
         
     | 
| 
      
 113 
     | 
    
         
            +
                </tr>
         
     | 
| 
      
 114 
     | 
    
         
            +
              </table>
         
     | 
| 
      
 115 
     | 
    
         
            +
            </div>
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
            <% if @last_request %>
         
     | 
| 
      
 118 
     | 
    
         
            +
              <div id="requestinfo">
         
     | 
| 
      
 119 
     | 
    
         
            +
                <h2>Last Request information</h2>
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                <h3 id="get-info">GET</h3>
         
     | 
| 
      
 122 
     | 
    
         
            +
                <% unless @last_request.GET.empty? %>
         
     | 
| 
      
 123 
     | 
    
         
            +
                  <table class="req">
         
     | 
| 
      
 124 
     | 
    
         
            +
                    <thead>
         
     | 
| 
      
 125 
     | 
    
         
            +
                      <tr>
         
     | 
| 
      
 126 
     | 
    
         
            +
                        <th>Variable</th>
         
     | 
| 
      
 127 
     | 
    
         
            +
                        <th>Value</th>
         
     | 
| 
      
 128 
     | 
    
         
            +
                      </tr>
         
     | 
| 
      
 129 
     | 
    
         
            +
                    </thead>
         
     | 
| 
      
 130 
     | 
    
         
            +
                    <tbody>
         
     | 
| 
      
 131 
     | 
    
         
            +
                        <% @last_request.GET.sort_by { |k, v| k.to_s }.each { |key, val| %>
         
     | 
| 
      
 132 
     | 
    
         
            +
                        <tr>
         
     | 
| 
      
 133 
     | 
    
         
            +
                          <td><%=h key %></td>
         
     | 
| 
      
 134 
     | 
    
         
            +
                          <td class="code"><div><%=h val.inspect %></div></td>
         
     | 
| 
      
 135 
     | 
    
         
            +
                        </tr>
         
     | 
| 
      
 136 
     | 
    
         
            +
                        <% } %>
         
     | 
| 
      
 137 
     | 
    
         
            +
                    </tbody>
         
     | 
| 
      
 138 
     | 
    
         
            +
                  </table>
         
     | 
| 
      
 139 
     | 
    
         
            +
                <% else %>
         
     | 
| 
      
 140 
     | 
    
         
            +
                  <p>No GET data.</p>
         
     | 
| 
      
 141 
     | 
    
         
            +
                <% end %>
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
                <h3 id="post-info">POST</h3>
         
     | 
| 
      
 144 
     | 
    
         
            +
                <% unless @last_request.POST.empty? %>
         
     | 
| 
      
 145 
     | 
    
         
            +
                  <table class="req">
         
     | 
| 
      
 146 
     | 
    
         
            +
                    <thead>
         
     | 
| 
      
 147 
     | 
    
         
            +
                      <tr>
         
     | 
| 
      
 148 
     | 
    
         
            +
                        <th>Variable</th>
         
     | 
| 
      
 149 
     | 
    
         
            +
                        <th>Value</th>
         
     | 
| 
      
 150 
     | 
    
         
            +
                      </tr>
         
     | 
| 
      
 151 
     | 
    
         
            +
                    </thead>
         
     | 
| 
      
 152 
     | 
    
         
            +
                    <tbody>
         
     | 
| 
      
 153 
     | 
    
         
            +
                        <% @last_request.POST.sort_by { |k, v| k.to_s }.each { |key, val| %>
         
     | 
| 
      
 154 
     | 
    
         
            +
                        <tr>
         
     | 
| 
      
 155 
     | 
    
         
            +
                          <td><%=h key %></td>
         
     | 
| 
      
 156 
     | 
    
         
            +
                          <td class="code"><div><%=h val.inspect %></div></td>
         
     | 
| 
      
 157 
     | 
    
         
            +
                        </tr>
         
     | 
| 
      
 158 
     | 
    
         
            +
                        <% } %>
         
     | 
| 
      
 159 
     | 
    
         
            +
                    </tbody>
         
     | 
| 
      
 160 
     | 
    
         
            +
                  </table>
         
     | 
| 
      
 161 
     | 
    
         
            +
                <% else %>
         
     | 
| 
      
 162 
     | 
    
         
            +
                  <p>No POST data.</p>
         
     | 
| 
      
 163 
     | 
    
         
            +
                <% end %>
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
                <h3 id="cookie-info">COOKIES</h3>
         
     | 
| 
      
 167 
     | 
    
         
            +
                <% unless @last_request.cookies.empty? %>
         
     | 
| 
      
 168 
     | 
    
         
            +
                  <table class="req">
         
     | 
| 
      
 169 
     | 
    
         
            +
                    <thead>
         
     | 
| 
      
 170 
     | 
    
         
            +
                      <tr>
         
     | 
| 
      
 171 
     | 
    
         
            +
                        <th>Variable</th>
         
     | 
| 
      
 172 
     | 
    
         
            +
                        <th>Value</th>
         
     | 
| 
      
 173 
     | 
    
         
            +
                      </tr>
         
     | 
| 
      
 174 
     | 
    
         
            +
                    </thead>
         
     | 
| 
      
 175 
     | 
    
         
            +
                    <tbody>
         
     | 
| 
      
 176 
     | 
    
         
            +
                      <% @last_request.cookies.each { |key, val| %>
         
     | 
| 
      
 177 
     | 
    
         
            +
                        <tr>
         
     | 
| 
      
 178 
     | 
    
         
            +
                          <td><%=h key %></td>
         
     | 
| 
      
 179 
     | 
    
         
            +
                          <td class="code"><div><%=h val.inspect %></div></td>
         
     | 
| 
      
 180 
     | 
    
         
            +
                        </tr>
         
     | 
| 
      
 181 
     | 
    
         
            +
                      <% } %>
         
     | 
| 
      
 182 
     | 
    
         
            +
                    </tbody>
         
     | 
| 
      
 183 
     | 
    
         
            +
                  </table>
         
     | 
| 
      
 184 
     | 
    
         
            +
                <% else %>
         
     | 
| 
      
 185 
     | 
    
         
            +
                  <p>No cookie data.</p>
         
     | 
| 
      
 186 
     | 
    
         
            +
                <% end %>
         
     | 
| 
      
 187 
     | 
    
         
            +
             
     | 
| 
      
 188 
     | 
    
         
            +
                <h3 id="env-info">Rack ENV</h3>
         
     | 
| 
      
 189 
     | 
    
         
            +
                  <table class="req">
         
     | 
| 
      
 190 
     | 
    
         
            +
                    <thead>
         
     | 
| 
      
 191 
     | 
    
         
            +
                      <tr>
         
     | 
| 
      
 192 
     | 
    
         
            +
                        <th>Variable</th>
         
     | 
| 
      
 193 
     | 
    
         
            +
                        <th>Value</th>
         
     | 
| 
      
 194 
     | 
    
         
            +
                      </tr>
         
     | 
| 
      
 195 
     | 
    
         
            +
                    </thead>
         
     | 
| 
      
 196 
     | 
    
         
            +
                    <tbody>
         
     | 
| 
      
 197 
     | 
    
         
            +
                        <% @last_request.env.sort_by { |k, v| k.to_s }.each { |key, val| %>
         
     | 
| 
      
 198 
     | 
    
         
            +
                        <tr>
         
     | 
| 
      
 199 
     | 
    
         
            +
                          <td><%=h key %></td>
         
     | 
| 
      
 200 
     | 
    
         
            +
                          <td class="code"><div><%=h val %></div></td>
         
     | 
| 
      
 201 
     | 
    
         
            +
                        </tr>
         
     | 
| 
      
 202 
     | 
    
         
            +
                        <% } %>
         
     | 
| 
      
 203 
     | 
    
         
            +
                    </tbody>
         
     | 
| 
      
 204 
     | 
    
         
            +
                  </table>
         
     | 
| 
      
 205 
     | 
    
         
            +
             
     | 
| 
      
 206 
     | 
    
         
            +
              </div>
         
     | 
| 
      
 207 
     | 
    
         
            +
            <% end %>
         
     | 
| 
      
 208 
     | 
    
         
            +
             
     | 
| 
      
 209 
     | 
    
         
            +
            <div id="explanation">
         
     | 
| 
      
 210 
     | 
    
         
            +
              <p>
         
     | 
| 
      
 211 
     | 
    
         
            +
                You're seeing this page because you use <code>Thin::Stats</code>.
         
     | 
| 
      
 212 
     | 
    
         
            +
              </p>
         
     | 
| 
      
 213 
     | 
    
         
            +
            </div>
         
     | 
| 
      
 214 
     | 
    
         
            +
             
     | 
| 
      
 215 
     | 
    
         
            +
            </body>
         
     | 
| 
      
 216 
     | 
    
         
            +
            </html>
         
     |