unicorn.git  about / heads / tags
Rack HTTP server for Unix and fast clients
blob 358748f0579e9064dfb36f633dfc08d94bb40027 4187 bytes (raw)
$ git show 4.x-stable:lib/unicorn.rb	# shows this blob on the CLI

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
 
# -*- encoding: binary -*-
require 'fcntl'
require 'etc'
require 'stringio'
require 'rack'
require 'kgio'

# :stopdoc:
# Unicorn module containing all of the classes (include C extensions) for
# running a Unicorn web server.  It contains a minimalist HTTP server with just
# enough functionality to service web application requests fast as possible.
# :startdoc:

# \Unicorn exposes very little of an user-visible API and most of its
# internals are subject to change.  \Unicorn is designed to host Rack
# applications, so applications should be written against the Rack SPEC
# and not \Unicorn internals.
module Unicorn

  # Raised inside TeeInput when a client closes the socket inside the
  # application dispatch.  This is always raised with an empty backtrace
  # since there is nothing in the application stack that is responsible
  # for client shutdowns/disconnects.  This exception is visible to Rack
  # applications unless PrereadInput middleware is loaded.
  class ClientShutdown < EOFError
  end

  # :stopdoc:

  # This returns a lambda to pass in as the app, this does not "build" the
  # app (which we defer based on the outcome of "preload_app" in the
  # Unicorn config).  The returned lambda will be called when it is
  # time to build the app.
  def self.builder(ru, op)
    # allow Configurator to parse cli switches embedded in the ru file
    op = Unicorn::Configurator::RACKUP.merge!(:file => ru, :optparse => op)

    # Op is going to get cleared before the returned lambda is called, so
    # save this value so that it's still there when we need it:
    no_default_middleware = op[:no_default_middleware]

    # always called after config file parsing, may be called after forking
    lambda do ||
      inner_app = case ru
      when /\.ru$/
        raw = File.read(ru)
        raw.sub!(/^__END__\n.*/, '')
        eval("Rack::Builder.new {(\n#{raw}\n)}.to_app", TOPLEVEL_BINDING, ru)
      else
        require ru
        Object.const_get(File.basename(ru, '.rb').capitalize)
      end

      pp({ :inner_app => inner_app }) if $DEBUG

      return inner_app if no_default_middleware

      # return value, matches rackup defaults based on env
      # Unicorn does not support persistent connections, but Rainbows!
      # and Zbatery both do.  Users accustomed to the Rack::Server default
      # middlewares will need ContentLength/Chunked middlewares.
      case ENV["RACK_ENV"]
      when "development"
        Rack::Builder.new do
          use Rack::ContentLength
          use Rack::Chunked
          use Rack::CommonLogger, $stderr
          use Rack::ShowExceptions
          use Rack::Lint
          use Rack::TempfileReaper if Rack.const_defined?(:TempfileReaper)
          run inner_app
        end.to_app
      when "deployment"
        Rack::Builder.new do
          use Rack::ContentLength
          use Rack::Chunked
          use Rack::CommonLogger, $stderr
          use Rack::TempfileReaper if Rack.const_defined?(:TempfileReaper)
          run inner_app
        end.to_app
      else
        inner_app
      end
    end
  end

  # returns an array of strings representing TCP listen socket addresses
  # and Unix domain socket paths.  This is useful for use with
  # Raindrops::Middleware under Linux: http://raindrops.bogomips.org/
  def self.listener_names
    Unicorn::HttpServer::LISTENERS.map do |io|
      Unicorn::SocketHelper.sock_name(io)
    end + Unicorn::HttpServer::NEW_LISTENERS
  end

  def self.log_error(logger, prefix, exc)
    message = exc.message
    message = message.dump if /[[:cntrl:]]/ =~ message
    logger.error "#{prefix}: #{message} (#{exc.class})"
    exc.backtrace.each { |line| logger.error(line) }
  end

  # remove this when we only support Ruby >= 2.0
  def self.pipe # :nodoc:
    Kgio::Pipe.new.each { |io| io.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) }
  end
  # :startdoc:
end
# :enddoc:
require 'unicorn/const'
require 'unicorn/socket_helper'
require 'unicorn/stream_input'
require 'unicorn/tee_input'
require 'unicorn/http_request'
require 'unicorn/configurator'
require 'unicorn/tmpio'
require 'unicorn/util'
require 'unicorn/http_response'
require 'unicorn/worker'
require 'unicorn/http_server'

git clone https://yhbt.net/unicorn.git