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.



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

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



149
150
151
# File 'lib/uv-rays/http/parser.rb', line 149

def reason
  @reason
end

#requestObject (readonly)

Returns the value of attribute request.



40
41
42
# File 'lib/uv-rays/http/parser.rb', line 40

def request
  @request
end

Instance Method Details

#eofObject



150
151
152
153
154
155
156
157
158
159
160
# File 'lib/uv-rays/http/parser.rb', line 150

def eof
    return if @request.nil?

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

#new_request(request) ⇒ Object



43
44
45
46
47
48
# File 'lib/uv-rays/http/parser.rb', line 43

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

#on_body(parser, data) ⇒ Object



127
128
129
130
131
132
133
# File 'lib/uv-rays/http/parser.rb', line 127

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

#on_header_field(parser, data) ⇒ Object



83
84
85
# File 'lib/uv-rays/http/parser.rb', line 83

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

#on_header_value(parser, data) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/uv-rays/http/parser.rb', line 87

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'

    end

    # Duplicate headers we'll place into an array
    current = @headers[@header]
    if current
        arr = @headers[@header] = Array(current)
        arr << data
    else
        @headers[@header] = data
    end
end

#on_headers_complete(parser) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/uv-rays/http/parser.rb', line 112

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:



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

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

#on_message_complete(parser) ⇒ Object



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

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



72
73
74
75
76
77
78
79
80
81
# File 'lib/uv-rays/http/parser.rb', line 72

def on_status(parser, data)
    @headers.reason_phrase = data

    # Different HTTP versions have different defaults
    if @state.http_minor == 0
        @close_connection = true
    else
        @close_connection = false
    end
end

#received(data) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/uv-rays/http/parser.rb', line 50

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

    false
end