Class: Reel::Request

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
RequestMixin
Defined in:
lib/reel/request.rb,
lib/reel/request/body.rb,
lib/reel/request/info.rb,
lib/reel/request/parser.rb,
lib/reel/request/state_machine.rb

Defined Under Namespace

Classes: Body, Info, Parser, StateMachine

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from RequestMixin

#[], #fragment, #headers, #method, #path, #query_string, #uri, #url, #version

Constructor Details

#initialize(request_info, connection = nil) ⇒ Request

request_info is a RequestInfo object including the headers and the url, method and http version.

Access it through the RequestMixin methods.



23
24
25
26
27
28
29
30
31
32
# File 'lib/reel/request.rb', line 23

def initialize(request_info, connection = nil)
  @request_info    = request_info
  @connection      = connection
  @finished        = false
  @buffer          = ""
  @finished_read   = false
  @websocket       = nil
  @body            = Request::Body.new(self)
  @response_writer = Response::Writer.new(connection.socket)
end

Instance Attribute Details

#bodyObject (readonly)

Returns the value of attribute body.



17
18
19
# File 'lib/reel/request.rb', line 17

def body
  @body
end

Instance Method Details

#fill_buffer(chunk) ⇒ Object

Fill the request buffer with data as it becomes available



44
45
46
# File 'lib/reel/request.rb', line 44

def fill_buffer(chunk)
  @buffer << chunk
end

#finish_reading!Object

When HTTP Parser marks the message parsing as complete, this will be set.

Raises:



38
39
40
41
# File 'lib/reel/request.rb', line 38

def finish_reading!
  raise StateError, "already finished" if @finished_read
  @finished_read = true
end

#finish_responseObject

Finish the response and reset the response state to header

Raises:



102
103
104
105
106
# File 'lib/reel/request.rb', line 102

def finish_response
  raise StateError, "not in body state" if @connection.response_state != :chunked_body
  @response_writer.finish_response
  @connection.response_state = :headers
end

#finished_reading?Boolean

Returns true if request fully finished reading

Returns:

  • (Boolean)


35
# File 'lib/reel/request.rb', line 35

def finished_reading?; @finished_read; end

#inspectObject

Friendlier inspect



121
122
123
# File 'lib/reel/request.rb', line 121

def inspect
  "#<#{self.class} #{method} #{url} HTTP/#{version} @headers=#{headers.inspect}>"
end

#read(length = nil, buffer = nil) ⇒ Object

Read a number of bytes, looping until they are available or until readpartial returns nil, indicating there are no more bytes to read

Raises:

  • (ArgumentError)


50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/reel/request.rb', line 50

def read(length = nil, buffer = nil)
  raise ArgumentError, "negative length #{length} given" if length && length < 0

  return '' if length == 0
  res = buffer.nil? ? '' : buffer.clear

  chunk_size = length.nil? ? @connection.buffer_size : length
  begin
    while chunk_size > 0
      chunk = readpartial(chunk_size)
      break unless chunk
      res << chunk
      chunk_size = length - res.length unless length.nil?
    end
  rescue EOFError
  end
  return length && res.length == 0 ? nil : res
end

#readpartial(length = nil) ⇒ Object

Read a string up to the given number of bytes, blocking until some data is available but returning immediately if some data is available



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/reel/request.rb', line 71

def readpartial(length = nil)
  if length.nil? && @buffer.length > 0
    slice = @buffer
    @buffer = ""
  else
    unless finished_reading? || (length && length <= @buffer.length)
      @connection.readpartial(length ? length - @buffer.length : @connection.buffer_size)
    end

    if length
      slice = @buffer.slice!(0, length)
    else
      slice = @buffer
      @buffer = ""
    end
  end

  slice && slice.length == 0 ? nil : slice
end

#websocketObject

Return a Reel::WebSocket for this request, hijacking the socket from the underlying connection



113
114
115
116
117
118
# File 'lib/reel/request.rb', line 113

def websocket
  @websocket ||= begin
    raise StateError, "can't upgrade this request to a websocket" unless websocket?
    WebSocket.new(@request_info, @connection.hijack_socket)
  end
end

#websocket?Boolean

Can the current request be upgraded to a WebSocket?

Returns:

  • (Boolean)


109
# File 'lib/reel/request.rb', line 109

def websocket?; @request_info.websocket_request?; end

#write(chunk) ⇒ Object Also known as: <<

Write body chunks directly to the connection



92
93
94
95
96
97
98
# File 'lib/reel/request.rb', line 92

def write(chunk)
  unless @connection.response_state == :chunked_body
    raise StateError, "not in chunked body mode"
  end

  @response_writer.write(chunk)
end