Class: Thin::Connection

### Home Classes Methods

### In Files

- lib/thin/connection.rb

### Parent

EventMachine::Connection

### Methods

- #can_persist!
- #can_persist?
- #close_request_response
- #idle?
- #persistent?
- #post_init
- #post_process
- #pre_process
- #process
- #receive_data
- #remote_address
- #socket_address
- #ssl_verify_peer
- #terminate_request
- #threaded?
- #unbind
- #unexpected_error

### Included Modules

- Thin::Logging

### Class/Module Index

Quicksearch

- Thin
- Thin::Backends
- Thin::Backends::Base
- Thin::Backends::SwiftiplyClient
- Thin::Backends::TcpServer
- Thin::Backends::UnixServer
- Thin::Command
- Thin::Connection
- Thin::Controllers
- Thin::Controllers::Cluster
- Thin::Controllers::Controller
- Thin::Controllers::Service
- Thin::Daemonizable
- Thin::Daemonizable::ClassMethods
- Thin::Headers
- Thin::InvalidOption
- Thin::InvalidRequest
- Thin::Logging
- Thin::Logging::SimpleFormatter
- Thin::OptionRequired
- Thin::PidFileExist
- Thin::PidFileNotFound
- Thin::PlatformNotSupported
- Thin::Request
- Thin::Response
- Thin::RestartTimeout
- Thin::Runner
- Thin::RunnerError
- Thin::Server
- Thin::Stats
- Thin::Stats::Adapter
- Thin::SwiftiplyConnection
- Thin::UnixConnection
- Rack
- Rack::Adapter
- Rack::Adapter::Rails
- Rack::Adapter::Rails::CGIWrapper
- Rack::Adapter::Rails::CgiApp
- Rack::AdapterNotFound
- Process

No matching classes.

# Thin::Connection

Connection between the server and client. This class is instanciated by EventMachine on each new connection that is opened.

### Constants

AsyncResponse

  This is a template async response. N.B. Can't use string for body on 1.9

### Attributes

app[RW]

Rack application (adapter) served by this connection.

backend[RW]

Backend to the server

request[RW]

Current request served by the connection

response[RW]

Next response sent through the connection

threaded[W]

Calling the application in a threaded allowing concurrent processing of requests.

### Public Instance Methods

can_persist!() click to toggle source

Allows this connection to be persistent.

    # File lib/thin/connection.rb, line 172
    def can_persist!
      @can_persist = true
    end

can_persist?() click to toggle source

Return `true` if this connection is allowed to stay open and be persistent.

    # File lib/thin/connection.rb, line 177
    def can_persist?
      @can_persist
    end

close_request_response() click to toggle source

    # File lib/thin/connection.rb, line 139
    def close_request_response
      @request.async_close.succeed if @request.async_close
      @request.close  rescue nil
      @response.close rescue nil
    end

idle?() click to toggle source

Return `true` if the connection is open but is not processing any user requests

    # File lib/thin/connection.rb, line 189
    def idle?
      @idle
    end

persistent?() click to toggle source

Return `true` if the connection must be left open and ready to be reused for another request.

    # File lib/thin/connection.rb, line 183
    def persistent?
      @can_persist && @response.persistent?
    end

post_init() click to toggle source

Get the connection ready to process a request.

    # File lib/thin/connection.rb, line 30
    def post_init
      @request  = Request.new
      @response = Response.new
    end

post_process(result) click to toggle source

    # File lib/thin/connection.rb, line 95
    def post_process(result)
      return unless result
      result = result.to_a

      # Status code -1 indicates that we're going to respond later (async).
      return if result.first == AsyncResponse.first

      @response.status, @response.headers, @response.body = *result

      log_error("Rack application returned nil body. "                  "Probably you wanted it to be an empty string?") if @response.body.nil?

      # HEAD requests should not return a body.
      @response.skip_body! if @request.head?

      # Make the response persistent if requested by the client
      @response.persistent! if @request.persistent?

      # Send the response
      @response.each do |chunk|
        trace chunk
        send_data chunk
      end

    rescue Exception => e
      unexpected_error(e)
      # Close connection since we can't handle response gracefully
      close_connection
    ensure
      # If the body is being deferred, then terminate afterward.
      if @response.body.respond_to?(:callback) && @response.body.respond_to?(:errback)
        @response.body.callback { terminate_request }
        @response.body.errback  { terminate_request }
      else
        # Don't terminate the response if we're going async.
        terminate_request unless result && result.first == AsyncResponse.first
      end
    end

pre_process() click to toggle source

    # File lib/thin/connection.rb, line 63
    def pre_process
      # Add client info to the request env
      @request.remote_address = remote_address

      # Connection may be closed unless the App#call response was a [-1, ...]
      # It should be noted that connection objects will linger until this
      # callback is no longer referenced, so be tidy!
      @request.async_callback = method(:post_process)

      if @backend.ssl?
        @request.env["rack.url_scheme"] = "https"

        if cert = get_peer_cert
          @request.env['rack.peer_cert'] = cert
        end
      end

      # When we're under a non-async framework like rails, we can still spawn
      # off async responses using the callback info, so there's little point
      # in removing this.
      response = AsyncResponse
      catch(:async) do
        # Process the request calling the Rack adapter
        response = @app.call(@request.env)
      end
      response
    rescue Exception => e
      unexpected_error(e)
      # Pass through error response
      can_persist? && @request.persistent? ? Response::PERSISTENT_ERROR : Response::ERROR
    end

process() click to toggle source

Called when all data was received and the request is ready to be processed.

    # File lib/thin/connection.rb, line 47
    def process
      if threaded?
        @request.threaded = true
        EventMachine.defer(method(:pre_process), method(:post_process))
      else
        @request.threaded = false
        post_process(pre_process)
      end
    end

receive_data(data) click to toggle source

Called when data is received from the client.

    # File lib/thin/connection.rb, line 36
    def receive_data(data)
      @idle = false
      trace data
      process if @request.parse(data)
    rescue InvalidRequest => e
      log_error("Invalid request", e)
      post_process Response::BAD_REQUEST
    end

remote_address() click to toggle source

IP Address of the remote client.

    # File lib/thin/connection.rb, line 201
    def remote_address
      socket_address
    rescue Exception => e
      log_error('Could not infer remote address', e)
      nil
    end

ssl_verify_peer(cert) click to toggle source

    # File lib/thin/connection.rb, line 57
    def ssl_verify_peer(cert)
      # In order to make the cert available later we have to have made at least
      # a show of verifying it.
      true
    end

terminate_request() click to toggle source

Does request and response cleanup (closes open IO streams and deletes created temporary files). Re-initializes response and request if client supports persistent connection.

    # File lib/thin/connection.rb, line 149
    def terminate_request
      unless persistent?
        close_connection_after_writing rescue nil
        close_request_response
      else
        close_request_response
        # Connection become idle but it's still open
        @idle = true
        # Prepare the connection for another request if the client
        # supports HTTP pipelining (persistent connection).
        post_init
      end
    end

threaded?() click to toggle source

`true` if `app.call` will be called inside a thread. You can set all requests as threaded setting `Connection#threaded=true` or on a per-request case returning `true` in `app.deferred?`.

    # File lib/thin/connection.rb, line 196
    def threaded?
      @threaded || (@app.respond_to?(:deferred?) && @app.deferred?(@request.env))
    end

unbind() click to toggle source

Called when the connection is unbinded from the socket and can no longer be used to process requests.

    # File lib/thin/connection.rb, line 165
    def unbind
      @request.async_close.succeed if @request.async_close
      @response.body.fail if @response.body.respond_to?(:fail)
      @backend.connection_finished(self)
    end

unexpected_error(e) click to toggle source

Logs information about an unexpected exceptional condition

    # File lib/thin/connection.rb, line 135
    def unexpected_error(e)
      log_error("Unexpected error while processing request", e)
    end

### Protected Instance Methods

socket_address() click to toggle source

Returns IP address of peer as a string.

    # File lib/thin/connection.rb, line 210
    def socket_address
      peer = get_peername
      Socket.unpack_sockaddr_in(peer)[1] if peer
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.