Class: Thin::Server

Class Thin::Server < Object

(in files lib/thin/server.rb )

The uterly famous Thin HTTP server. It listen for incoming request through a given backend and forward all request to app.

TCP server

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)

UNIX domain server

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)

Using a custom backend

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)

Rack application (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].

Building an app in place

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

Controlling with signals

Disable signals by passing :signals => false

Includes

Methods

Public Class new(*args, &block)

     # File lib/thin/server.rb, line 94
 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

Public Class start(*args, &block)

Lil’ shortcut to turn this:

  Server.new(...).start

into this:

  Server.start(...)
     # File lib/thin/server.rb, line 141
141:     def self.start(*args, &block)
142:       new(*args, &block).start!
143:     end

Public Instance config()

Configure the server

The process might need to have superuser privilege to configure server with optimal options.

     # File lib/thin/server.rb, line 190
190:     def config
191:       @backend.config
192:     end

Public Instance name()

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 196
196:     def name
197:       "thin server (#{@backend})" + (tag ? " [#{tag}]" : "")
198:     end

Public Instance running?()

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 204
204:     def running?
205:       @backend.running?
206:     end

Public Instance start()

Start the server and listen for connections.

     # File lib/thin/server.rb, line 146
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

Public Instance start!()

Alias for start

Public Instance stop()

Gracefull shutdown

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 165
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

Public Instance stop!()

Force shutdown

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 181
181:     def stop!
182:       log ">> Stopping ..."
183: 
184:       @backend.stop!
185:     end

Public Instance to_s()

Alias for name

Protected Instance load_cgi_multipart_eof_fix()

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 234
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

Protected Instance select_backend(host, port, options)

     # File lib/thin/server.rb, line 218
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

Protected Instance setup_signals()

Register signals:

  • INT calls stop to shutdown gracefully.
  • TERM calls stop! to force shutdown.
     # File lib/thin/server.rb, line 212
212:       def setup_signals
213:         trap('QUIT') { stop }  unless Thin.win?
214:         trap('INT')  { stop! }
215:         trap('TERM') { stop! }
216:       end