thin 1.6.3 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG +22 -0
- data/README.md +34 -102
- data/example/async_chat.ru +0 -0
- data/example/async_tailer.ru +0 -0
- data/ext/thin_parser/parser.c +0 -5
- data/ext/thin_parser/parser.h +5 -5
- data/ext/thin_parser/parser.rl +0 -5
- data/ext/thin_parser/thin.c +1 -1
- data/lib/rack/handler/thin.rb +38 -0
- data/lib/thin/backends/base.rb +4 -2
- data/lib/thin/backends/tcp_server.rb +10 -5
- data/lib/thin/connection.rb +1 -1
- data/lib/thin/controllers/controller.rb +1 -1
- data/lib/thin/controllers/service.rb +1 -0
- data/lib/thin/daemonizing.rb +26 -7
- data/lib/thin/logging.rb +7 -2
- data/lib/thin/request.rb +6 -4
- data/lib/thin/runner.rb +4 -1
- data/lib/thin/server.rb +15 -15
- data/lib/thin/statuses.rb +8 -4
- data/lib/thin/version.rb +5 -5
- metadata +30 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 285d7efc73ff2e6e29a8789706c605cc2a2b5a1d25313a53d72954dd5a8adbe7
|
4
|
+
data.tar.gz: 24642b42692477ba60cb63cb0ffa49dcf63cc0634708a349d8fac94d08989b74
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab7de3338f8d8694ed44a04cf785e78a0ce85de874d7bde4d96c6801b1e85190a3cbd33d8fe16a32aedc09eab9f1caad4a37ce51dc5997c32b5550da6d2fcffc
|
7
|
+
data.tar.gz: 19c45bc3a6f403daffe6a6c66b89bca01c597edb5b8c6ada110834c52fac0f639746f9b51ce5a3ca42c8f2fa013c929929b64b3737819ce83e5dff257e8a328a
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
== 1.7.2 Bachmanity
|
2
|
+
* Add config support for ssl_version and ssl_cipher_list [frameworked]
|
3
|
+
|
4
|
+
== 1.7.1 Muffin Mode
|
5
|
+
* Ruby 2.4 support (Fixnum deprecation) [nimish-mehta]
|
6
|
+
* Allow ERB templates in config files [markets]
|
7
|
+
|
8
|
+
== 1.7.0 Dunder Mifflin
|
9
|
+
* Rack 2 support
|
10
|
+
* Ensure Response body.close is called in the same thread
|
11
|
+
Fixes issues with ActiveRecord connection management [#307]
|
12
|
+
* Fix TCP/IP Backend reports incorrect port when asked to bind to 0 [meschbach]
|
13
|
+
* Work with ruby 2.3's --enable-frozen-string-literal [jeremyevans]
|
14
|
+
|
15
|
+
== 1.6.4 Gob Bluth
|
16
|
+
* Increase REQUEST_PATH to 2048 symbols [X2rdas]
|
17
|
+
* Fix warning in logger [tenderlove]
|
18
|
+
* Add :timeout option for Rack::Server.new [sugitak]
|
19
|
+
* When restarting, exit on a next tick so we can send response back to a client [rsamoilov]
|
20
|
+
* Check for empty PID files [z1dane]
|
21
|
+
* Update Event Machine version to 1.0.4, Ruby 2.2.0 fix [freemanoid]
|
22
|
+
|
1
23
|
== 1.6.3 Protein Powder
|
2
24
|
* Add HTTP 422 status code [rajcybage]
|
3
25
|
* Add warning about EM reactor still running when stopping.
|
data/README.md
CHANGED
@@ -1,35 +1,17 @@
|
|
1
|
-
Thin
|
2
|
-
====
|
1
|
+
# Thin
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
Thin is a Ruby web server that glues together 3 of the best Ruby libraries in web history:
|
7
|
-
|
8
|
-
* The Mongrel parser: the root of Mongrel speed and security
|
9
|
-
* Event Machine: a network I/O library with extremely high scalability, performance and stability
|
10
|
-
* Rack: a minimal interface between webservers and Ruby frameworks
|
11
|
-
|
12
|
-
Which makes it, with all humility, the most secure, stable, fast and extensible Ruby web server
|
13
|
-
bundled in an easy to use gem for your own pleasure.
|
14
|
-
|
15
|
-
Site: http://code.macournoyer.com/thin/
|
16
|
-
Group: http://groups.google.com/group/thin-ruby/topics
|
17
|
-
Bugs: http://github.com/macournoyer/thin/issues
|
18
|
-
Code: http://github.com/macournoyer/thin
|
19
|
-
IRC: #thin on freenode
|
3
|
+
A small and fast Ruby web server
|
20
4
|
|
21
5
|
## Installation
|
22
6
|
|
23
|
-
|
24
|
-
|
25
|
-
|
7
|
+
```
|
8
|
+
gem install thin
|
9
|
+
```
|
26
10
|
|
27
|
-
Or
|
11
|
+
Or add `thin` to your `Gemfile`:
|
28
12
|
|
29
|
-
```
|
30
|
-
|
31
|
-
cd thin
|
32
|
-
rake install
|
13
|
+
```ruby
|
14
|
+
gem 'thin'
|
33
15
|
```
|
34
16
|
|
35
17
|
## Usage
|
@@ -37,18 +19,30 @@ rake install
|
|
37
19
|
A +thin+ script offers an easy way to start your Rack application:
|
38
20
|
|
39
21
|
```
|
40
|
-
cd to/your/app
|
41
22
|
thin start
|
42
23
|
```
|
43
24
|
|
44
|
-
|
45
|
-
|
25
|
+
Browse the `example` directory for sample applications.
|
26
|
+
|
27
|
+
## Usage with Rails Action Cable
|
28
|
+
|
29
|
+
To use Thin with Action Cable, add the following to your `Gemfile`:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
gem 'faye-websocket'
|
33
|
+
gem 'thin' # If not already done
|
34
|
+
```
|
35
|
+
|
36
|
+
Create a `config/initializers/thin_action_cable.rb`:
|
46
37
|
|
47
|
-
|
38
|
+
```ruby
|
39
|
+
Rails.application.config.action_cable.use_faye = true
|
40
|
+
Faye::WebSocket.load_adapter 'thin'
|
41
|
+
```
|
48
42
|
|
49
|
-
###
|
43
|
+
### CLI
|
50
44
|
|
51
|
-
Use a rackup file and bind to localhost port 8080:
|
45
|
+
Use a rackup (config.ru) file and bind to localhost port 8080:
|
52
46
|
|
53
47
|
```
|
54
48
|
thin -R config.ru -a 127.0.0.1 -p 8080 start
|
@@ -60,11 +54,15 @@ Store the server process ID, log to a file and daemonize:
|
|
60
54
|
thin -p 9292 -P tmp/pids/thin.pid -l logs/thin.log -d start
|
61
55
|
```
|
62
56
|
|
63
|
-
Thin is quite flexible in that many options can be specified at the command line (see
|
57
|
+
Thin is quite flexible in that many options can be specified at the command line (see `thin -h` for more).
|
64
58
|
|
65
59
|
### Configuration files
|
66
60
|
|
67
|
-
You can create configuration
|
61
|
+
You can create a configuration file using `thin config -C config/thin.yml`.
|
62
|
+
|
63
|
+
You can then use it with all commands, such as: `thin start -C config/thin.yml`.
|
64
|
+
|
65
|
+
Here is an example config file:
|
68
66
|
|
69
67
|
```yaml
|
70
68
|
---
|
@@ -87,79 +85,13 @@ chdir: /path/to/your/apps/root
|
|
87
85
|
tag: a-name-to-show-up-in-ps aux
|
88
86
|
```
|
89
87
|
|
90
|
-
### Command Line Options
|
91
|
-
|
92
|
-
This is the usage for the thin command which can be obtained by running `thin -h` at the command line.
|
93
|
-
|
94
|
-
```sh
|
95
|
-
Usage: thin [options] start|stop|restart|config|install
|
96
|
-
|
97
|
-
Server options:
|
98
|
-
-a, --address HOST bind to HOST address (default: 0.0.0.0)
|
99
|
-
-p, --port PORT use PORT (default: 3000)
|
100
|
-
-S, --socket FILE bind to unix domain socket
|
101
|
-
-y, --swiftiply [KEY] Run using swiftiply
|
102
|
-
-A, --adapter NAME Rack adapter to use (default: autodetect)
|
103
|
-
(rack, rails, ramaze, merb, file)
|
104
|
-
-R, --rackup FILE Load a Rack config file instead of Rack adapter
|
105
|
-
-c, --chdir DIR Change to dir before starting
|
106
|
-
--stats PATH Mount the Stats adapter under PATH
|
107
|
-
|
108
|
-
SSL options:
|
109
|
-
--ssl Enables SSL
|
110
|
-
--ssl-key-file PATH Path to private key
|
111
|
-
--ssl-cert-file PATH Path to certificate
|
112
|
-
--ssl-disable-verify Disables (optional) client cert requests
|
113
|
-
|
114
|
-
Adapter options:
|
115
|
-
-e, --environment ENV Framework environment (default: development)
|
116
|
-
--prefix PATH Mount the app under PATH (start with /)
|
117
|
-
|
118
|
-
Daemon options:
|
119
|
-
-d, --daemonize Run daemonized in the background
|
120
|
-
-l, --log FILE File to redirect output (default: /home/robert/log/thin.log)
|
121
|
-
-P, --pid FILE File to store PID (default: tmp/pids/thin.pid)
|
122
|
-
-u, --user NAME User to run daemon as (use with -g)
|
123
|
-
-g, --group NAME Group to run daemon as (use with -u)
|
124
|
-
--tag NAME Additional text to display in process listing
|
125
|
-
|
126
|
-
Cluster options:
|
127
|
-
-s, --servers NUM Number of servers to start
|
128
|
-
-o, --only NUM Send command to only one server of the cluster
|
129
|
-
-C, --config FILE Load options from config file
|
130
|
-
--all [DIR] Send command to each config files in DIR
|
131
|
-
-O, --onebyone Restart the cluster one by one (only works with restart command)
|
132
|
-
-w, --wait NUM Maximum wait time for server to be started in seconds (use with -O)
|
133
|
-
|
134
|
-
Tuning options:
|
135
|
-
-b, --backend CLASS Backend to use, full classname
|
136
|
-
-t, --timeout SEC Request or command timeout in sec (default: 30)
|
137
|
-
-f, --force Force the execution of the command
|
138
|
-
--max-conns NUM Maximum number of open file descriptors (default: 1024)
|
139
|
-
Might require sudo to set higher than 1024
|
140
|
-
--max-persistent-conns NUM Maximum number of persistent connections
|
141
|
-
(default: 100)
|
142
|
-
--threaded Call the Rack application in threads [experimental]
|
143
|
-
--threadpool-size NUM Sets the size of the EventMachine threadpool.
|
144
|
-
(default: 20)
|
145
|
-
--no-epoll Disable the use of epoll
|
146
|
-
|
147
|
-
Common options:
|
148
|
-
-r, --require FILE require the library
|
149
|
-
-q, --quiet Silence all logging
|
150
|
-
-D, --debug Enable debug logging
|
151
|
-
-V, --trace Set tracing on (log raw request/response)
|
152
|
-
-h, --help Show this message
|
153
|
-
-v, --version Show version
|
154
|
-
```
|
155
|
-
|
156
88
|
## License
|
157
89
|
|
158
90
|
Ruby License, http://www.ruby-lang.org/en/LICENSE.txt.
|
159
91
|
|
160
92
|
## Credits
|
161
93
|
|
162
|
-
The parser was
|
94
|
+
The parser was originally from Mongrel http://mongrel.rubyforge.org by Zed Shaw.
|
163
95
|
Mongrel is copyright 2007 Zed A. Shaw and contributors. It is licensed under
|
164
96
|
the Ruby license and the GPL2.
|
165
97
|
|
@@ -167,4 +99,4 @@ Thin is copyright Marc-Andre Cournoyer <macournoyer@gmail.com>
|
|
167
99
|
|
168
100
|
Get help at http://groups.google.com/group/thin-ruby/
|
169
101
|
Report bugs at https://github.com/macournoyer/thin/issues
|
170
|
-
and major security issues directly to me macournoyer@gmail.com.
|
102
|
+
and major security issues directly to me at macournoyer@gmail.com.
|
data/example/async_chat.ru
CHANGED
File without changes
|
data/example/async_tailer.ru
CHANGED
File without changes
|
data/ext/thin_parser/parser.c
CHANGED
@@ -1437,11 +1437,6 @@ int thin_http_parser_is_finished(http_parser *parser) {
|
|
1437
1437
|
|
1438
1438
|
int thin_http_parser_finish(http_parser *parser)
|
1439
1439
|
{
|
1440
|
-
int cs = parser->cs;
|
1441
|
-
|
1442
|
-
|
1443
|
-
parser->cs = cs;
|
1444
|
-
|
1445
1440
|
if (thin_http_parser_has_error(parser) ) {
|
1446
1441
|
return -1;
|
1447
1442
|
} else if (thin_http_parser_is_finished(parser) ) {
|
data/ext/thin_parser/parser.h
CHANGED
@@ -38,11 +38,11 @@ typedef struct http_parser {
|
|
38
38
|
|
39
39
|
} http_parser;
|
40
40
|
|
41
|
-
int
|
42
|
-
int
|
43
|
-
size_t
|
44
|
-
int
|
45
|
-
int
|
41
|
+
int thin_http_parser_init(http_parser *parser);
|
42
|
+
int thin_http_parser_finish(http_parser *parser);
|
43
|
+
size_t thin_http_parser_execute(http_parser *parser, const char *data, size_t len, size_t off);
|
44
|
+
int thin_http_parser_has_error(http_parser *parser);
|
45
|
+
int thin_http_parser_is_finished(http_parser *parser);
|
46
46
|
|
47
47
|
#define http_parser_nread(parser) (parser)->nread
|
48
48
|
|
data/ext/thin_parser/parser.rl
CHANGED
@@ -142,11 +142,6 @@ int thin_http_parser_is_finished(http_parser *parser) {
|
|
142
142
|
|
143
143
|
int thin_http_parser_finish(http_parser *parser)
|
144
144
|
{
|
145
|
-
int cs = parser->cs;
|
146
|
-
|
147
|
-
|
148
|
-
parser->cs = cs;
|
149
|
-
|
150
145
|
if (thin_http_parser_has_error(parser) ) {
|
151
146
|
return -1;
|
152
147
|
} else if (thin_http_parser_is_finished(parser) ) {
|
data/ext/thin_parser/thin.c
CHANGED
@@ -67,7 +67,7 @@ DEF_MAX_LENGTH(FIELD_NAME, 256);
|
|
67
67
|
DEF_MAX_LENGTH(FIELD_VALUE, 80 * 1024);
|
68
68
|
DEF_MAX_LENGTH(REQUEST_URI, 1024 * 12);
|
69
69
|
DEF_MAX_LENGTH(FRAGMENT, 1024); /* Don't know if this length is specified somewhere or not */
|
70
|
-
DEF_MAX_LENGTH(REQUEST_PATH,
|
70
|
+
DEF_MAX_LENGTH(REQUEST_PATH, 2048);
|
71
71
|
DEF_MAX_LENGTH(QUERY_STRING, (1024 * 10));
|
72
72
|
DEF_MAX_LENGTH(HEADER, (1024 * (80 + 32)));
|
73
73
|
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "thin"
|
4
|
+
require "thin/server"
|
5
|
+
require "thin/logging"
|
6
|
+
require "thin/backends/tcp_server"
|
7
|
+
|
8
|
+
module Rack
|
9
|
+
module Handler
|
10
|
+
class Thin
|
11
|
+
def self.run(app, **options)
|
12
|
+
environment = ENV['RACK_ENV'] || 'development'
|
13
|
+
default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
|
14
|
+
|
15
|
+
host = options.delete(:Host) || default_host
|
16
|
+
port = options.delete(:Port) || 8080
|
17
|
+
args = [host, port, app, options]
|
18
|
+
|
19
|
+
server = ::Thin::Server.new(*args)
|
20
|
+
yield server if block_given?
|
21
|
+
|
22
|
+
server.start
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.valid_options
|
26
|
+
environment = ENV['RACK_ENV'] || 'development'
|
27
|
+
default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
|
28
|
+
|
29
|
+
{
|
30
|
+
"Host=HOST" => "Hostname to listen on (default: #{default_host})",
|
31
|
+
"Port=PORT" => "Port to listen on (default: 8080)",
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
register :thin, ::Rack::Handler::Thin
|
37
|
+
end
|
38
|
+
end
|
data/lib/thin/backends/base.rb
CHANGED
@@ -3,7 +3,7 @@ module Thin
|
|
3
3
|
# A Backend connects the server to the client. It handles:
|
4
4
|
# * connection/disconnection to the server
|
5
5
|
# * initialization of the connections
|
6
|
-
# *
|
6
|
+
# * monitoring of the active connections.
|
7
7
|
#
|
8
8
|
# == Implementing your own backend
|
9
9
|
# You can create your own minimal backend by inheriting this class and
|
@@ -51,9 +51,11 @@ module Thin
|
|
51
51
|
@maximum_connections = Server::DEFAULT_MAXIMUM_CONNECTIONS
|
52
52
|
@maximum_persistent_connections = Server::DEFAULT_MAXIMUM_PERSISTENT_CONNECTIONS
|
53
53
|
@no_epoll = false
|
54
|
+
@running = false
|
54
55
|
@ssl = nil
|
55
|
-
@threaded = nil
|
56
56
|
@started_reactor = false
|
57
|
+
@stopping = false
|
58
|
+
@threaded = nil
|
57
59
|
end
|
58
60
|
|
59
61
|
# Start the backend and connect it.
|
@@ -4,26 +4,31 @@ module Thin
|
|
4
4
|
class TcpServer < Base
|
5
5
|
# Address and port on which the server is listening for connections.
|
6
6
|
attr_accessor :host, :port
|
7
|
-
|
7
|
+
|
8
8
|
def initialize(host, port)
|
9
9
|
@host = host
|
10
10
|
@port = port
|
11
11
|
super()
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
# Connect the server
|
15
15
|
def connect
|
16
16
|
@signature = EventMachine.start_server(@host, @port, Connection, &method(:initialize_connection))
|
17
|
+
binary_name = EventMachine.get_sockname( @signature )
|
18
|
+
port_name = Socket.unpack_sockaddr_in( binary_name )
|
19
|
+
@port = port_name[0]
|
20
|
+
@host = port_name[1]
|
21
|
+
@signature
|
17
22
|
end
|
18
|
-
|
23
|
+
|
19
24
|
# Stops the server
|
20
25
|
def disconnect
|
21
26
|
EventMachine.stop_server(@signature)
|
22
27
|
end
|
23
|
-
|
28
|
+
|
24
29
|
def to_s
|
25
30
|
"#{@host}:#{@port}"
|
26
31
|
end
|
27
32
|
end
|
28
33
|
end
|
29
|
-
end
|
34
|
+
end
|
data/lib/thin/connection.rb
CHANGED
@@ -55,7 +55,7 @@ module Thin
|
|
55
55
|
# ssl support
|
56
56
|
if @options[:ssl]
|
57
57
|
server.ssl = true
|
58
|
-
server.ssl_options = { :private_key_file => @options[:ssl_key_file], :cert_chain_file => @options[:ssl_cert_file], :verify_peer => !@options[:ssl_disable_verify] }
|
58
|
+
server.ssl_options = { :private_key_file => @options[:ssl_key_file], :cert_chain_file => @options[:ssl_cert_file], :verify_peer => !@options[:ssl_disable_verify], :ssl_version => @options[:ssl_version], :cipher_list => @options[:ssl_cipher_list]}
|
59
59
|
end
|
60
60
|
|
61
61
|
# Detach the process, after this line the current process returns
|
data/lib/thin/daemonizing.rb
CHANGED
@@ -30,11 +30,17 @@ module Thin
|
|
30
30
|
def self.included(base)
|
31
31
|
base.extend ClassMethods
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
def pid
|
35
|
-
File.exist?(pid_file) ? open(pid_file).read.to_i : nil
|
35
|
+
File.exist?(pid_file) && !File.zero?(pid_file) ? open(pid_file).read.to_i : nil
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
|
+
def kill(timeout = 60)
|
39
|
+
if File.exist?(@pid_file)
|
40
|
+
self.class.kill(@pid_file, timeout)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
38
44
|
# Turns the current script into a daemon process that detaches from the console.
|
39
45
|
def daemonize
|
40
46
|
raise PlatformNotSupported, 'Daemonizing is not supported on Windows' if Thin.win?
|
@@ -78,6 +84,10 @@ module Thin
|
|
78
84
|
Process.initgroups(user, target_gid)
|
79
85
|
Process::GID.change_privilege(target_gid)
|
80
86
|
Process::UID.change_privilege(target_uid)
|
87
|
+
|
88
|
+
# Correct environment variables
|
89
|
+
ENV.store('USER', user)
|
90
|
+
ENV.store('HOME', File.expand_path("~#{user}"))
|
81
91
|
end
|
82
92
|
rescue Errno::EPERM => e
|
83
93
|
log_info "Couldn't change user and group to #{user}:#{group}: #{e}"
|
@@ -95,7 +105,7 @@ module Thin
|
|
95
105
|
stop
|
96
106
|
remove_pid_file
|
97
107
|
@on_restart.call
|
98
|
-
exit!
|
108
|
+
EM.next_tick { exit! }
|
99
109
|
end
|
100
110
|
end
|
101
111
|
|
@@ -116,14 +126,23 @@ module Thin
|
|
116
126
|
def restart(pid_file)
|
117
127
|
send_signal('HUP', pid_file)
|
118
128
|
end
|
119
|
-
|
129
|
+
|
130
|
+
def monotonic_time
|
131
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
132
|
+
end
|
133
|
+
|
120
134
|
# Send a +signal+ to the process which PID is stored in +pid_file+.
|
121
135
|
def send_signal(signal, pid_file, timeout=60)
|
122
136
|
if pid = read_pid_file(pid_file)
|
123
137
|
Logging.log_info "Sending #{signal} signal to process #{pid} ... "
|
138
|
+
|
124
139
|
Process.kill(signal, pid)
|
125
|
-
|
126
|
-
|
140
|
+
|
141
|
+
# This loop seems kind of racy to me...
|
142
|
+
started_at = monotonic_time
|
143
|
+
while Process.running?(pid)
|
144
|
+
sleep 0.1
|
145
|
+
raise Timeout::Error if (monotonic_time - started_at) > timeout
|
127
146
|
end
|
128
147
|
else
|
129
148
|
raise PidFileNotFound, "Can't stop process, no PID found in #{pid_file}"
|
data/lib/thin/logging.rb
CHANGED
@@ -13,10 +13,12 @@ module Thin
|
|
13
13
|
# Taken from ActiveSupport
|
14
14
|
class SimpleFormatter < Logger::Formatter
|
15
15
|
def call(severity, timestamp, progname, msg)
|
16
|
-
"#{String === msg ? msg : msg.inspect}\n"
|
16
|
+
"#{timestamp} #{String === msg ? msg : msg.inspect}\n"
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
@trace_logger = nil
|
21
|
+
|
20
22
|
class << self
|
21
23
|
attr_reader :logger
|
22
24
|
attr_reader :trace_logger
|
@@ -152,7 +154,10 @@ module Thin
|
|
152
154
|
|
153
155
|
# Log a message at ERROR level (and maybe a backtrace)
|
154
156
|
def log_error(msg, e=nil)
|
155
|
-
log_msg = msg
|
157
|
+
log_msg = msg
|
158
|
+
if e
|
159
|
+
log_msg += ": #{e}\n\t" + e.backtrace.join("\n\t") + "\n"
|
160
|
+
end
|
156
161
|
Logging.log_msg(log_msg, Logger::ERROR)
|
157
162
|
end
|
158
163
|
module_function :log_error
|
data/lib/thin/request.rb
CHANGED
@@ -13,9 +13,9 @@ module Thin
|
|
13
13
|
BODY_TMPFILE = 'thin-body'.freeze
|
14
14
|
MAX_HEADER = 1024 * (80 + 32)
|
15
15
|
|
16
|
-
INITIAL_BODY =
|
16
|
+
INITIAL_BODY = String.new
|
17
17
|
# Force external_encoding of request's body to ASCII_8BIT
|
18
|
-
INITIAL_BODY.encode!(Encoding::ASCII_8BIT) if INITIAL_BODY.respond_to?(:encode!)
|
18
|
+
INITIAL_BODY.encode!(Encoding::ASCII_8BIT) if INITIAL_BODY.respond_to?(:encode!) && defined?(Encoding::ASCII_8BIT)
|
19
19
|
|
20
20
|
# Freeze some HTTP header names & values
|
21
21
|
SERVER_SOFTWARE = 'SERVER_SOFTWARE'.freeze
|
@@ -52,7 +52,7 @@ module Thin
|
|
52
52
|
|
53
53
|
def initialize
|
54
54
|
@parser = Thin::HttpParser.new
|
55
|
-
@data =
|
55
|
+
@data = String.new
|
56
56
|
@nparsed = 0
|
57
57
|
@body = StringIO.new(INITIAL_BODY.dup)
|
58
58
|
@env = {
|
@@ -75,7 +75,9 @@ module Thin
|
|
75
75
|
# Raises an +InvalidRequest+ if invalid.
|
76
76
|
# Returns +true+ if the parsing is complete.
|
77
77
|
def parse(data)
|
78
|
-
if
|
78
|
+
if data.size > 0 && finished? # headers and body already fully satisfied. more data is erroneous.
|
79
|
+
raise InvalidRequest, 'Content longer than specified'
|
80
|
+
elsif @parser.finished? # Header finished, can only be some more body
|
79
81
|
@body << data
|
80
82
|
else # Parse more header using the super parser
|
81
83
|
@data << data
|
data/lib/thin/runner.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'logger'
|
2
2
|
require 'optparse'
|
3
3
|
require 'yaml'
|
4
|
+
require 'erb'
|
4
5
|
|
5
6
|
module Thin
|
6
7
|
# CLI runner.
|
@@ -80,6 +81,8 @@ module Thin
|
|
80
81
|
opts.on( "--ssl-key-file PATH", "Path to private key") { |path| @options[:ssl_key_file] = path }
|
81
82
|
opts.on( "--ssl-cert-file PATH", "Path to certificate") { |path| @options[:ssl_cert_file] = path }
|
82
83
|
opts.on( "--ssl-disable-verify", "Disables (optional) client cert requests") { @options[:ssl_disable_verify] = true }
|
84
|
+
opts.on( "--ssl-version VERSION", "TLSv1, TLSv1_1, TLSv1_2") { |version| @options[:ssl_version] = version }
|
85
|
+
opts.on( "--ssl-cipher-list STRING", "Example: HIGH:!ADH:!RC4:-MEDIUM:-LOW:-EXP:-CAMELLIA") { |cipher| @options[:ssl_cipher_list] = cipher }
|
83
86
|
|
84
87
|
opts.separator ""
|
85
88
|
opts.separator "Adapter options:"
|
@@ -219,7 +222,7 @@ module Thin
|
|
219
222
|
private
|
220
223
|
def load_options_from_config_file!
|
221
224
|
if file = @options.delete(:config)
|
222
|
-
YAML.
|
225
|
+
YAML.load(ERB.new(File.read(file)).result).each { |key, value| @options[key.to_sym] = value }
|
223
226
|
end
|
224
227
|
end
|
225
228
|
|
data/lib/thin/server.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
module Thin
|
2
|
-
# The
|
3
|
-
# It
|
4
|
-
# and
|
2
|
+
# The utterly famous Thin HTTP server.
|
3
|
+
# It listens for incoming requests through a given +backend+
|
4
|
+
# and forwards all requests to +app+.
|
5
5
|
#
|
6
6
|
# == TCP server
|
7
|
-
# Create a new TCP server
|
7
|
+
# Create a new TCP server bound to <tt>host:port</tt> by specifiying +host+
|
8
8
|
# and +port+ as the first 2 arguments.
|
9
9
|
#
|
10
10
|
# Thin::Server.start('0.0.0.0', 3000, app)
|
@@ -18,12 +18,12 @@ module Thin
|
|
18
18
|
#
|
19
19
|
# == Using a custom backend
|
20
20
|
# You can implement your own way to connect the server to its client by creating your
|
21
|
-
# own Backend class and
|
21
|
+
# own Backend class and passing it as the :backend option.
|
22
22
|
#
|
23
23
|
# Thin::Server.start('galaxy://faraway', 1345, app, :backend => Thin::Backends::MyFancyBackend)
|
24
24
|
#
|
25
25
|
# == Rack application (+app+)
|
26
|
-
# All requests will be processed through +app
|
26
|
+
# All requests will be processed through +app+, which must be a valid Rack adapter.
|
27
27
|
# A valid Rack adapter (application) must respond to <tt>call(env#Hash)</tt> and
|
28
28
|
# return an array of <tt>[status, headers, body]</tt>.
|
29
29
|
#
|
@@ -76,10 +76,10 @@ module Thin
|
|
76
76
|
# Maximum number of file or socket descriptors that the server may open.
|
77
77
|
def_delegators :backend, :maximum_connections, :maximum_connections=
|
78
78
|
|
79
|
-
# Maximum number of
|
80
|
-
# Most
|
81
|
-
# when the timeout
|
82
|
-
#
|
79
|
+
# Maximum number of connections that can be persistent at the same time.
|
80
|
+
# Most browsers never close the connection so most of the time they are closed
|
81
|
+
# when the timeout occurs. If we don't control the number of persistent connections,
|
82
|
+
# it would be very easy to overflow the server for a DoS attack.
|
83
83
|
def_delegators :backend, :maximum_persistent_connections, :maximum_persistent_connections=
|
84
84
|
|
85
85
|
# Allow using threads in the backend.
|
@@ -104,9 +104,9 @@ module Thin
|
|
104
104
|
# received in any order.
|
105
105
|
args.each do |arg|
|
106
106
|
case arg
|
107
|
-
when
|
108
|
-
when String
|
109
|
-
when Hash
|
107
|
+
when 0.class, /^\d+$/ then port = arg.to_i
|
108
|
+
when String then host = arg
|
109
|
+
when Hash then options = arg
|
110
110
|
else
|
111
111
|
@app = arg if arg.respond_to?(:call)
|
112
112
|
end
|
@@ -125,7 +125,7 @@ module Thin
|
|
125
125
|
# Set defaults
|
126
126
|
@backend.maximum_connections = DEFAULT_MAXIMUM_CONNECTIONS
|
127
127
|
@backend.maximum_persistent_connections = DEFAULT_MAXIMUM_PERSISTENT_CONNECTIONS
|
128
|
-
@backend.timeout = DEFAULT_TIMEOUT
|
128
|
+
@backend.timeout = options[:timeout] || DEFAULT_TIMEOUT
|
129
129
|
|
130
130
|
# Allow using Rack builder as a block
|
131
131
|
@app = Rack::Builder.new(&block).to_app if block
|
@@ -166,7 +166,7 @@ module Thin
|
|
166
166
|
# == Gracefull shutdown
|
167
167
|
# Stops the server after processing all current connections.
|
168
168
|
# As soon as this method is called, the server stops accepting
|
169
|
-
# new requests and
|
169
|
+
# new requests and waits for all current connections to finish.
|
170
170
|
# Calling twice is the equivalent of calling <tt>stop!</tt>.
|
171
171
|
def stop
|
172
172
|
if running?
|
data/lib/thin/statuses.rb
CHANGED
@@ -33,12 +33,16 @@ module Thin
|
|
33
33
|
413 => 'Request Entity Too Large',
|
34
34
|
414 => 'Request-URI Too Large',
|
35
35
|
415 => 'Unsupported Media Type',
|
36
|
-
422 => 'Unprocessable Entity',
|
37
|
-
|
36
|
+
422 => 'Unprocessable Entity',
|
37
|
+
428 => 'Precondition Required',
|
38
|
+
429 => 'Too Many Requests',
|
39
|
+
431 => 'Request Header Fields Too Large',
|
40
|
+
500 => 'Internal Server Error',
|
38
41
|
501 => 'Not Implemented',
|
39
42
|
502 => 'Bad Gateway',
|
40
43
|
503 => 'Service Unavailable',
|
41
44
|
504 => 'Gateway Time-out',
|
42
|
-
505 => 'HTTP Version not supported'
|
45
|
+
505 => 'HTTP Version not supported',
|
46
|
+
511 => 'Network Authentication Required'
|
43
47
|
}
|
44
|
-
end
|
48
|
+
end
|
data/lib/thin/version.rb
CHANGED
@@ -1,22 +1,22 @@
|
|
1
|
-
module Thin
|
1
|
+
module Thin
|
2
2
|
# Raised when a feature is not supported on the
|
3
3
|
# current platform.
|
4
4
|
class PlatformNotSupported < RuntimeError; end
|
5
5
|
|
6
6
|
module VERSION #:nodoc:
|
7
7
|
MAJOR = 1
|
8
|
-
MINOR =
|
9
|
-
TINY =
|
8
|
+
MINOR = 8
|
9
|
+
TINY = 0
|
10
10
|
|
11
11
|
STRING = [MAJOR, MINOR, TINY].join('.')
|
12
12
|
|
13
|
-
CODENAME = "
|
13
|
+
CODENAME = "Possessed Pickle".freeze
|
14
14
|
|
15
15
|
RACK = [1, 0].freeze # Rack protocol version
|
16
16
|
end
|
17
17
|
|
18
18
|
NAME = 'thin'.freeze
|
19
|
-
SERVER = "#{NAME} #{VERSION::STRING} codename #{VERSION::CODENAME}".freeze
|
19
|
+
SERVER = "#{NAME} #{VERSION::STRING} codename #{VERSION::CODENAME}".freeze
|
20
20
|
|
21
21
|
def self.win?
|
22
22
|
RUBY_PLATFORM =~ /mswin|mingw/
|
metadata
CHANGED
@@ -1,29 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marc-Andre Cournoyer
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-11-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1
|
19
|
+
version: '1'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '3'
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
|
-
- - "
|
27
|
+
- - ">="
|
25
28
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1
|
29
|
+
version: '1'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '3'
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
34
|
name: eventmachine
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -31,6 +37,9 @@ dependencies:
|
|
31
37
|
- - "~>"
|
32
38
|
- !ruby/object:Gem::Version
|
33
39
|
version: '1.0'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 1.0.4
|
34
43
|
type: :runtime
|
35
44
|
prerelease: false
|
36
45
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -38,6 +47,9 @@ dependencies:
|
|
38
47
|
- - "~>"
|
39
48
|
- !ruby/object:Gem::Version
|
40
49
|
version: '1.0'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 1.0.4
|
41
53
|
- !ruby/object:Gem::Dependency
|
42
54
|
name: daemons
|
43
55
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,7 +70,7 @@ dependencies:
|
|
58
70
|
- - ">="
|
59
71
|
- !ruby/object:Gem::Version
|
60
72
|
version: 1.0.9
|
61
|
-
description:
|
73
|
+
description:
|
62
74
|
email: macournoyer@gmail.com
|
63
75
|
executables:
|
64
76
|
- thin
|
@@ -92,6 +104,7 @@ files:
|
|
92
104
|
- ext/thin_parser/thin.c
|
93
105
|
- lib/rack/adapter/loader.rb
|
94
106
|
- lib/rack/adapter/rails.rb
|
107
|
+
- lib/rack/handler/thin.rb
|
95
108
|
- lib/thin.rb
|
96
109
|
- lib/thin/backends/base.rb
|
97
110
|
- lib/thin/backends/swiftiply_client.rb
|
@@ -114,12 +127,14 @@ files:
|
|
114
127
|
- lib/thin/stats.rb
|
115
128
|
- lib/thin/statuses.rb
|
116
129
|
- lib/thin/version.rb
|
117
|
-
homepage:
|
130
|
+
homepage: https://github.com/macournoyer/thin
|
118
131
|
licenses:
|
119
|
-
-
|
120
|
-
- Ruby
|
121
|
-
metadata:
|
122
|
-
|
132
|
+
- GPL-2.0+
|
133
|
+
- Ruby
|
134
|
+
metadata:
|
135
|
+
source_code_uri: https://github.com/macournoyer/thin
|
136
|
+
changelog_uri: https://github.com/macournoyer/thin/blob/master/CHANGELOG
|
137
|
+
post_install_message:
|
123
138
|
rdoc_options: []
|
124
139
|
require_paths:
|
125
140
|
- lib
|
@@ -134,9 +149,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
134
149
|
- !ruby/object:Gem::Version
|
135
150
|
version: '0'
|
136
151
|
requirements: []
|
137
|
-
|
138
|
-
|
139
|
-
signing_key:
|
152
|
+
rubygems_version: 3.1.2
|
153
|
+
signing_key:
|
140
154
|
specification_version: 4
|
141
155
|
summary: A thin and fast web server
|
142
156
|
test_files: []
|