/
parser.rb
103 lines (82 loc) · 2.22 KB
/
parser.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# frozen_string_literal: true
require "http-parser"
module HTTP
class Response
# @api private
#
# NOTE(ixti): This class is a subject of future refactoring, thus don't
# expect this class API to be stable until this message disappears and
# class is not marked as private anymore.
class Parser
attr_reader :headers
def initialize
@state = HttpParser::Parser.new_instance { |i| i.type = :response }
@parser = HttpParser::Parser.new(self)
reset
end
# @return [self]
def add(data)
# XXX(ixti): API doc of HttpParser::Parser is misleading, it says that
# it returns boolean true if data was parsed successfully, but instead
# it's response tells if there was an error; So when it's `true` that
# means parse failed, and `false` means parse was successful.
# case of success.
return self unless @parser.parse(@state, data)
raise IOError, "Could not parse data"
end
alias << add
def headers?
@finished[:headers]
end
def http_version
@state.http_version
end
def status_code
@state.http_status
end
#
# HTTP::Parser callbacks
#
def on_header_field(_response, field)
@field = field
end
def on_header_value(_response, value)
@headers.add(@field, value) if @field
end
def on_headers_complete(_reposse)
@finished[:headers] = true
end
def on_body(_response, chunk)
if @chunk
@chunk << chunk
else
@chunk = chunk
end
end
def read(size)
return if @chunk.nil?
if @chunk.bytesize <= size
chunk = @chunk
@chunk = nil
else
chunk = @chunk.byteslice(0, size)
@chunk[0, size] = ""
end
chunk
end
def on_message_complete(_response)
@finished[:message] = true
end
def reset
@state.reset!
@finished = Hash.new(false)
@headers = HTTP::Headers.new
@field = nil
@chunk = nil
end
def finished?
@finished[:message]
end
end
end
end