The uterly famous Thin HTTP server. It listen
for incoming request through a given backend
and forward all
request to app
.
Create a new TCP server on bound to host:port
by specifiying
host
and port
as the first 2 arguments.
Thin::Server.start('0.0.0.0', 3000, app)
Create a new UNIX domain socket bound to socket
file by
specifiying a filename as the first argument. Eg.: /tmp/thin.sock. If the
first argument contains a /
it will be assumed to be a UNIX
socket.
Thin::Server.start('/tmp/thin.sock', app)
You can implement your own way to connect the server to its client by creating your own Backend class and pass it as the :backend option.
Thin::Server.start('galaxy://faraway', 1345, app, :backend => Thin::Backends::MyFancyBackend)
app
)All requests will be processed through app
that must be a
valid Rack adapter. A valid Rack adapter (application) must respond to
call(env#Hash)
and return an array of [status, headers,
body]
.
If a block is passed, a Rack::Builder
instance will be passed
to build the app
. So you can do cool stuff like this:
Thin::Server.start('0.0.0.0', 3000) do use Rack::CommonLogger use Rack::ShowExceptions map "/lobster" do use Rack::Lint run Rack::Lobster.new end end
Disable signals by passing :signals => false
Default values
Application (Rack adapter) called with the request that produces the response.
Backend handling the connections to the clients.
A tag that will show in the process listing
The process might need to have superuser privilege to configure server with optimal options.
# File lib/thin/server.rb, line 193 def config @backend.config end
Name of the server and type of backend used. This is also the name of the process in which Thin is running as a daemon.
# File lib/thin/server.rb, line 199 def name "thin server (#{@backend})" + (tag ? " [#{tag}]" : "") end
Return true
if the server is running and ready to receive
requests. Note that the server might still be running and return
false
when shuting down and waiting for active connections to
complete.
# File lib/thin/server.rb, line 207 def running? @backend.running? end
Start the server and listen for connections.
# File lib/thin/server.rb, line 149 def start raise ArgumentError, 'app required' unless @app log ">> Thin web server (v#{VERSION::STRING} codename #{VERSION::CODENAME})" debug ">> Debugging ON" trace ">> Tracing ON" log ">> Maximum connections set to #{@backend.maximum_connections}" log ">> Listening on #{@backend}, CTRL+C to stop" @backend.start end
Stops the server after processing all current connections. As soon as this
method is called, the server stops accepting new requests and wait for all
current connections to finish. Calling twice is the equivalent of calling
stop!
.
# File lib/thin/server.rb, line 168 def stop if running? @backend.stop unless @backend.empty? log ">> Waiting for #{@backend.size} connection(s) to finish, " + "can take up to #{timeout} sec, CTRL+C to stop now" end else stop! end end
Stops the server closing all current connections right away. This doesn’t wait for connection to finish their work and send data. All current requests will be dropped.
# File lib/thin/server.rb, line 184 def stop! log ">> Stopping ..." @backend.stop! end
Taken from Mongrel cgi_multipart_eof_fix Ruby 1.8.5 has a security bug in cgi.rb, we need to patch it.
# File lib/thin/server.rb, line 241 def load_cgi_multipart_eof_fix version = RUBY_VERSION.split('.').map { |i| i.to_i } if version[0] <= 1 && version[1] <= 8 && version[2] <= 5 && RUBY_PLATFORM !~ %rjava/ begin require 'cgi_multipart_eof_fix' rescue LoadError log "!! Ruby 1.8.5 is not secure please install cgi_multipart_eof_fix:" log " gem install cgi_multipart_eof_fix" end end end
# File lib/thin/server.rb, line 225 def select_backend(host, port, options) case when options.has_key?(:backend) raise ArgumentError, ":backend must be a class" unless options[:backend].is_a?(Class) options[:backend].new(host, port, options) when options.has_key?(:swiftiply) Backends::SwiftiplyClient.new(host, port, options) when host.include?('/') Backends::UnixServer.new(host) else Backends::TcpServer.new(host, port) end end
Register signals:
TERM & QUIT calls stop
to shutdown gracefully.
INT calls stop!
to force shutdown.
HUP calls restart
to … surprise, restart!
# File lib/thin/server.rb, line 216 def setup_signals trap('INT') { stop! } trap('TERM') { stop } unless Thin.win? trap('QUIT') { stop } trap('HUP') { restart } end end
# File lib/thin/server.rb, line 97 def initialize(*args, &block) host, port, options = DEFAULT_HOST, DEFAULT_PORT, {} # Guess each parameter by its type so they can be # received in any order. args.each do |arg| case arg when Fixnum, %r^\d+$/ then port = arg.to_i when String then host = arg when Hash then options = arg else @app = arg if arg.respond_to?(:call) end end # Set tag if needed self.tag = options[:tag] # Try to intelligently select which backend to use. @backend = select_backend(host, port, options) load_cgi_multipart_eof_fix @backend.server = self # Set defaults @backend.maximum_connections = DEFAULT_MAXIMUM_CONNECTIONS @backend.maximum_persistent_connections = DEFAULT_MAXIMUM_PERSISTENT_CONNECTIONS @backend.timeout = DEFAULT_TIMEOUT # Allow using Rack builder as a block @app = Rack::Builder.new(&block).to_app if block # If in debug mode, wrap in logger adapter @app = Rack::CommonLogger.new(@app) if Logging.debug? setup_signals unless options[:signals].class == FalseClass end
Lil’ shortcut to turn this:
Server.new(...).start
into this:
Server.start(...)
# File lib/thin/server.rb, line 144 def self.start(*args, &block) new(*args, &block).start! end