Class: UV::Http::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/uv-rays/http/parser.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeParser

Returns a new instance of Parser.



25
26
27
28
29
30
# File 'lib/uv-rays/http/parser.rb', line 25

def initialize
    @parser = ::HttpParser::Parser.new(self)
    @state = ::HttpParser::Parser.new_instance
    @state.type = :response
    @headers = nil
end

Instance Attribute Details

#reasonObject

We need to flush the response on disconnect if content-length is undefined As per the HTTP spec



133
134
135
# File 'lib/uv-rays/http/parser.rb', line 133

def reason
  @reason
end

#requestObject (readonly)

Returns the value of attribute request.



33
34
35
# File 'lib/uv-rays/http/parser.rb', line 33

def request
  @request
end

Instance Method Details

#eofObject



134
135
136
137
138
139
140
141
142
143
144
# File 'lib/uv-rays/http/parser.rb', line 134

def eof
    return if @request.nil?

    if @headers_complete && @headers[:'Content-Length'].nil?
        on_message_complete(nil)
    else
        # Reject if this is a partial response
        @request.reject(@reason || :partial_response)
        cleanup
    end
end

#new_request(request) ⇒ Object



36
37
38
39
40
41
# File 'lib/uv-rays/http/parser.rb', line 36

def new_request(request)
    @headers = nil
    @request = request
    @headers_complete = false
    @state.reset!
end

#on_body(parser, data) ⇒ Object



111
112
113
114
115
116
117
# File 'lib/uv-rays/http/parser.rb', line 111

def on_body(parser, data)
    if @request.streaming?
        @request.notify(data)
    else
        @body << data
    end
end

#on_header_field(parser, data) ⇒ Object



74
75
76
# File 'lib/uv-rays/http/parser.rb', line 74

def on_header_field(parser, data)
    @header = data.to_sym
end

#on_header_value(parser, data) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/uv-rays/http/parser.rb', line 78

def on_header_value(parser, data)
    case @header
    when :"Set-Cookie"
        @request.set_cookie(data)

    when :Connection
        # Overwrite the default
        @close_connection = data == 'close'

    when :"Transfer-Encoding"
        # If chunked we'll buffer streaming data for notification
        @chunked = data == 'chunked'

    else
        @headers[@header] = data
    end
end

#on_headers_complete(parser) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/uv-rays/http/parser.rb', line 96

def on_headers_complete(parser)
    @headers_complete = true

    # https://github.com/joyent/http-parser indicates we should extract
    # this information here
    @headers.http_version = @state.http_version
    @headers.status = @state.http_status
    @headers.cookies = @request.cookies_hash
    @headers.keep_alive = !@close_connection

    # User code may throw an error
    # Errors will halt the processing and return a PAUSED error
    @request.set_headers(@headers)
end

#on_message_begin(parser) ⇒ Object

Parser Callbacks:



58
59
60
61
62
63
# File 'lib/uv-rays/http/parser.rb', line 58

def on_message_begin(parser)
    @headers = Headers.new
    @body = ''
    @chunked = false
    @close_connection = false
end

#on_message_complete(parser) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
# File 'lib/uv-rays/http/parser.rb', line 119

def on_message_complete(parser)
    @headers.body = @body

    if @request.resolve(@headers)
        cleanup
    else
        req = @request
        cleanup
        new_request(req)
    end
end

#on_status(parser, data) ⇒ Object



65
66
67
68
69
70
71
72
# File 'lib/uv-rays/http/parser.rb', line 65

def on_status(parser, data)
    # Different HTTP versions have different defaults
    if @state.http_minor == 0
        @close_connection = true
    else
        @close_connection = false
    end
end

#received(data) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/uv-rays/http/parser.rb', line 43

def received(data)
    if @parser.parse(@state, data)
        if @request
            @request.reject(@state.error)
            @request = nil
            @response = nil
            return true
        end
    end

    false
end