Class: Puma::Client

### Home Classes Methods

### In Files

- lib/puma/client.rb

### Parent

Object

### Methods

- ::new
- #call
- #close
- #eagerly_finish
- #finish
- #in_data_phase
- #inspect
- #jruby_start_try_to_finish
- #read_body
- #reset
- #set_timeout
- #setup_body
- #try_to_finish
- #write_400
- #write_408
- #write_500

### Included Modules

- Puma::Const

### Files

- Manifest.txt

### Class/Module Index

Quicksearch

- Puma
- Puma::App
- Puma::App::Status
- Puma::Binder
- Puma::CLI
- Puma::Client
- Puma::Cluster
- Puma::Cluster::Worker
- Puma::CommonLogger
- Puma::ConfigDefault
- Puma::Configuration
- Puma::Configuration::ConfigMiddleware
- Puma::ConnectionError
- Puma::Const
- Puma::ControlCLI
- Puma::DSL
- Puma::Delegation
- Puma::Events
- Puma::Events::DefaultFormatter
- Puma::Events::PidFormatter
- Puma::IOBuffer
- Puma::JRubyRestart
- Puma::JavaIOBuffer
- Puma::MiniSSL
- Puma::MiniSSL::Context
- Puma::MiniSSL::SSLError
- Puma::MiniSSL::Server
- Puma::MiniSSL::Socket
- Puma::NullIO
- Puma::Rack
- Puma::Rack::Builder
- Puma::Rack::Options
- Puma::Rack::URLMap
- Puma::Reactor
- Puma::Runner
- Puma::Server
- Puma::Single
- Puma::TCPLogger
- Puma::ThreadPool
- Puma::ThreadPool::AutoTrim
- Puma::ThreadPool::Reaper
- Puma::UnsupportedOption
- Puma::Util
- Puma::Util::HeaderHash
- OpenSSL
- OpenSSL::SSL
- OpenSSL::SSL::SSLServer
- Rack
- Rack::Handler
- Rack::Handler::Puma
- IO
- IO::WaitReadable
- Object
- Process
- String

No matching classes.

# Puma::Client

### Constants

EmptyBody

  The object used for a request with no body. All requests with no body share this one object since it has no state.

### Attributes

body[R]
env[R]
hijacked[R]
io[R]
ready[R]
tempfile[R]
timeout_at[R]
to_io[R]

### Public Class Methods

new(io, env=nil) click to toggle source

    # File lib/puma/client.rb, line 25
    def initialize(io, env=nil)
      @io = io
      @to_io = io.to_io
      @proto_env = env
      if !env
        @env = nil
      else
        @env = env.dup
      end

      @parser = HttpParser.new
      @parsed_bytes = 0
      @read_header = true
      @ready = false

      @body = nil
      @buffer = nil
      @tempfile = nil

      @timeout_at = nil

      @requests_served = 0
      @hijacked = false
    end

### Public Instance Methods

call() click to toggle source

For the hijack protocol (allows us to just put the Client object into the env)

    # File lib/puma/client.rb, line 59
    def call
      @hijacked = true
      env[HIJACK_IO] ||= @io
    end

close() click to toggle source

    # File lib/puma/client.rb, line 98
    def close
      begin
        @io.close
      rescue IOError
      end
    end

eagerly_finish() click to toggle source

    # File lib/puma/client.rb, line 209
    def eagerly_finish
      return true if @ready

      if @io.kind_of? OpenSSL::SSL::SSLSocket
        return true if jruby_start_try_to_finish
      end

      return false unless IO.select([@to_io], nil, nil, 0)
      try_to_finish
    end

finish() click to toggle source

    # File lib/puma/client.rb, line 229
    def finish
      return true if @ready
      until try_to_finish
        IO.select([@to_io], nil, nil)
      end
      true
    end

in_data_phase() click to toggle source

    # File lib/puma/client.rb, line 64
    def in_data_phase
      !@read_header
    end

inspect() click to toggle source

    # File lib/puma/client.rb, line 53
    def inspect
      "#<Puma::Client:0x#{object_id.to_s(16)} @ready=#{@ready.inspect}>"
    end

jruby_start_try_to_finish() click to toggle source

    # File lib/puma/client.rb, line 181
    def jruby_start_try_to_finish
      return read_body unless @read_header

      begin
        data = @io.sysread_nonblock(CHUNK_SIZE)
      rescue OpenSSL::SSL::SSLError => e
        return false if e.kind_of? IO::WaitReadable
        raise e
      end

      if @buffer
        @buffer << data
      else
        @buffer = data
      end

      @parsed_bytes = @parser.execute(@env, @buffer, @parsed_bytes)

      if @parser.finished?
        return setup_body
      elsif @parsed_bytes >= MAX_HEADER
        raise HttpParserError,
          "HEADER is longer than allowed, aborting client early."
      end

      false
    end

read_body() click to toggle source

    # File lib/puma/client.rb, line 237
    def read_body
      # Read an odd sized chunk so we can read even sized ones
      # after this
      remain = @body_remain

      if remain > CHUNK_SIZE
        want = CHUNK_SIZE
      else
        want = remain
      end

      begin
        chunk = @io.read_nonblock(want)
      rescue Errno::EAGAIN
        return false
      rescue SystemCallError, IOError
        raise ConnectionError, "Connection error detected during read"
      end

      # No chunk means a closed socket
      unless chunk
        @body.close
        @buffer = nil
        @requests_served += 1
        @ready = true
        raise EOFError
      end

      remain -= @body.write(chunk)

      if remain <= 0
        @body.rewind
        @buffer = nil
        @requests_served += 1
        @ready = true
        return true
      end

      @body_remain = remain

      false
    end

reset(fast_check=true) click to toggle source

    # File lib/puma/client.rb, line 72
    def reset(fast_check=true)
      @parser.reset
      @read_header = true
      @env = @proto_env.dup
      @body = nil
      @tempfile = nil
      @parsed_bytes = 0
      @ready = false

      if @buffer
        @parsed_bytes = @parser.execute(@env, @buffer, @parsed_bytes)

        if @parser.finished?
          return setup_body
        elsif @parsed_bytes >= MAX_HEADER
          raise HttpParserError,
            "HEADER is longer than allowed, aborting client early."
        end

        return false
      elsif fast_check &&
            IO.select([@to_io], nil, nil, FAST_TRACK_KA_TIMEOUT)
        return try_to_finish
      end
    end

set_timeout(val) click to toggle source

    # File lib/puma/client.rb, line 68
    def set_timeout(val)
      @timeout_at = Time.now + val
    end

setup_body() click to toggle source

    # File lib/puma/client.rb, line 109
    def setup_body
      @in_data_phase = true
      body = @parser.body
      cl = @env[CONTENT_LENGTH]

      unless cl
        @buffer = body.empty? ? nil : body
        @body = EmptyBody
        @requests_served += 1
        @ready = true
        return true
      end

      remain = cl.to_i - body.bytesize

      if remain <= 0
        @body = StringIO.new(body)
        @buffer = nil
        @requests_served += 1
        @ready = true
        return true
      end

      if remain > MAX_BODY
        @body = Tempfile.new(Const::PUMA_TMP_BASE)
        @body.binmode
        @tempfile = @body
      else
        # The body[0,0] trick is to get an empty string in the same
        # encoding as body.
        @body = StringIO.new body[0,0]
      end

      @body.write body

      @body_remain = remain

      @read_header = false

      return false
    end

try_to_finish() click to toggle source

    # File lib/puma/client.rb, line 151
    def try_to_finish
      return read_body unless @read_header

      begin
        data = @io.read_nonblock(CHUNK_SIZE)
      rescue Errno::EAGAIN
        return false
      rescue SystemCallError, IOError
        raise ConnectionError, "Connection error detected during read"
      end

      if @buffer
        @buffer << data
      else
        @buffer = data
      end

      @parsed_bytes = @parser.execute(@env, @buffer, @parsed_bytes)

      if @parser.finished?
        return setup_body
      elsif @parsed_bytes >= MAX_HEADER
        raise HttpParserError,
          "HEADER is longer than allowed, aborting client early."
      end

      false
    end

write_400() click to toggle source

    # File lib/puma/client.rb, line 280
    def write_400
      begin
        @io << ERROR_400_RESPONSE
      rescue StandardError
      end
    end

write_408() click to toggle source

    # File lib/puma/client.rb, line 287
    def write_408
      begin
        @io << ERROR_408_RESPONSE
      rescue StandardError
      end
    end

write_500() click to toggle source

    # File lib/puma/client.rb, line 294
    def write_500
      begin
        @io << ERROR_500_RESPONSE
      rescue StandardError
      end
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.