f0ceffe588c83f333a9aedcec2ce168cf2fda11b
[unicorn.git] / lib / unicorn.rb
blobf0ceffe588c83f333a9aedcec2ce168cf2fda11b
1 # -*- encoding: binary -*-
2 require 'fcntl'
3 require 'etc'
4 require 'stringio'
5 require 'rack'
6 require 'kgio'
8 # :stopdoc:
9 # Unicorn module containing all of the classes (include C extensions) for
10 # running a Unicorn web server.  It contains a minimalist HTTP server with just
11 # enough functionality to service web application requests fast as possible.
12 # :startdoc:
14 # \Unicorn exposes very little of an user-visible API and most of its
15 # internals are subject to change.  \Unicorn is designed to host Rack
16 # applications, so applications should be written against the Rack SPEC
17 # and not \Unicorn internals.
18 module Unicorn
20   # Raised inside TeeInput when a client closes the socket inside the
21   # application dispatch.  This is always raised with an empty backtrace
22   # since there is nothing in the application stack that is responsible
23   # for client shutdowns/disconnects.  This exception is visible to Rack
24   # applications unless PrereadInput middleware is loaded.
25   class ClientShutdown < EOFError
26   end
28   # :stopdoc:
30   # This returns a lambda to pass in as the app, this does not "build" the
31   # app (which we defer based on the outcome of "preload_app" in the
32   # Unicorn config).  The returned lambda will be called when it is
33   # time to build the app.
34   def self.builder(ru, op)
35     # allow Configurator to parse cli switches embedded in the ru file
36     op = Unicorn::Configurator::RACKUP.merge!(:file => ru, :optparse => op)
38     # always called after config file parsing, may be called after forking
39     lambda do ||
40       inner_app = case ru
41       when /\.ru$/
42         raw = File.read(ru)
43         raw.sub!(/^__END__\n.*/, '')
44         eval("Rack::Builder.new {(\n#{raw}\n)}.to_app", TOPLEVEL_BINDING, ru)
45       else
46         require ru
47         Object.const_get(File.basename(ru, '.rb').capitalize)
48       end
50       pp({ :inner_app => inner_app }) if $DEBUG
52       return inner_app if op[:no_default_middleware]
54       # return value, matches rackup defaults based on env
55       # Unicorn does not support persistent connections, but Rainbows!
56       # and Zbatery both do.  Users accustomed to the Rack::Server default
57       # middlewares will need ContentLength/Chunked middlewares.
58       case ENV["RACK_ENV"]
59       when "development"
60         Rack::Builder.new do
61           use Rack::ContentLength
62           use Rack::Chunked
63           use Rack::CommonLogger, $stderr
64           use Rack::ShowExceptions
65           use Rack::Lint
66           run inner_app
67         end.to_app
68       when "deployment"
69         Rack::Builder.new do
70           use Rack::ContentLength
71           use Rack::Chunked
72           use Rack::CommonLogger, $stderr
73           run inner_app
74         end.to_app
75       else
76         inner_app
77       end
78     end
79   end
81   # returns an array of strings representing TCP listen socket addresses
82   # and Unix domain socket paths.  This is useful for use with
83   # Raindrops::Middleware under Linux: http://raindrops.bogomips.org/
84   def self.listener_names
85     Unicorn::HttpServer::LISTENERS.map do |io|
86       Unicorn::SocketHelper.sock_name(io)
87     end + Unicorn::HttpServer::NEW_LISTENERS
88   end
90   def self.log_error(logger, prefix, exc)
91     message = exc.message
92     message = message.dump if /[[:cntrl:]]/ =~ message
93     logger.error "#{prefix}: #{message} (#{exc.class})"
94     exc.backtrace.each { |line| logger.error(line) }
95   end
96   # :startdoc:
97 end
98 # :enddoc:
99 require 'unicorn/const'
100 require 'unicorn/socket_helper'
101 require 'unicorn/stream_input'
102 require 'unicorn/tee_input'
103 require 'unicorn/http_request'
104 require 'unicorn/configurator'
105 require 'unicorn/tmpio'
106 require 'unicorn/util'
107 require 'unicorn/http_response'
108 require 'unicorn/worker'
109 require 'unicorn/http_server'