thin 1.2.3-x86-mswin32
Sign up to get free protection for your applications and to get access to all the features.
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>
|