Module: Syntropy::HTTP::ProtocolMethods
- Defined in:
- lib/syntropy/http/io_extensions.rb
Overview
HTTP protocol extensions for UringMachine::IO
Constant Summary collapse
- RE_REQUEST_LINE =
/^(get|head|options|trace|put|delete|post|patch|connect)\s+([^\s]+)\s+HTTP\/([019\.]{1,3})/i- RE_RESPONSE_LINE =
/^HTTP\/1\.1\s+(\d{3})(\s+.+)?$/i- RE_HEADER_LINE =
/^([a-z0-9\-]+):\s+(.+)/i- MAX_REQUEST_LINE_LEN =
16KB
1 << 14
- MAX_RESPONSE_LINE_LEN =
256
1 << 8
- MAX_HEADER_LINE_LEN =
8KB
1 << 13
- MAX_CHUNK_SIZE_LEN =
16
Instance Method Summary collapse
-
#http_read_body(headers) ⇒ String
Reads an HTTP request/response body.
-
#http_read_body_chunk(headers) ⇒ String?
Reads an HTTP body chunk.
-
#http_read_request_headers ⇒ Hash
Reads HTTP request headers.
-
#http_read_response_headers ⇒ Hash
Reads HTTP response headers.
-
#http_skip_body(headers) ⇒ void
Skips an HTTP reuqest/response body.
-
#http_write_request_headers(headers) ⇒ void
Writes HTTP request headers.
Instance Method Details
#http_read_body(headers) ⇒ String
Reads an HTTP request/response body.
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/syntropy/http/io_extensions.rb', line 86 def http_read_body(headers) content_length = headers['content-length'] if content_length content_length = content_length.to_i return nil if content_length == 0 chunk = read(content_length.to_i) return chunk end chunked_encoding = headers['transfer-encoding']&.downcase == 'chunked' if chunked_encoding buf = +'' while (chunk = http_read_cte_chunk(nil)) buf << chunk end return buf end nil end |
#http_read_body_chunk(headers) ⇒ String?
Reads an HTTP body chunk. If no chunks remain to be read, returns nil.
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/syntropy/http/io_extensions.rb', line 132 def http_read_body_chunk(headers) content_length = headers['content-length'] if content_length content_length = content_length.to_i return nil if content_length == 0 chunk = read(content_length.to_i) return chunk end chunked_encoding = headers['transfer-encoding']&.downcase == 'chunked' return http_read_cte_chunk(nil) if chunked_encoding nil end |
#http_read_request_headers ⇒ Hash
Reads HTTP request headers.
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 |
# File 'lib/syntropy/http/io_extensions.rb', line 21 def http_read_request_headers line = read_line(MAX_REQUEST_LINE_LEN) return nil if !line m = line.match(RE_REQUEST_LINE) raise ProtocolError, 'Invalid request line' if !m http_version = m[3] raise UnsupportedHTTPVersionError, 'HTTP version not supported' if http_version != '1.1' headers = { ':method' => m[1].downcase, ':path' => m[2] } loop do line = read_line(MAX_HEADER_LINE_LEN) break if line.nil? || line.empty? m = line.match(RE_HEADER_LINE) raise ProtocolError, "Invalid header: #{line[0..2047].inspect}" if !m headers[m[1].downcase] = m[2] end headers end |
#http_read_response_headers ⇒ Hash
Reads HTTP response headers.
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 |
# File 'lib/syntropy/http/io_extensions.rb', line 52 def http_read_response_headers line = read_line(MAX_RESPONSE_LINE_LEN) return nil if !line m = line.match(RE_RESPONSE_LINE) raise ProtocolError, 'Invalid response line' if !m headers = { ':status' => m[1].to_i } loop do line = read_line(MAX_HEADER_LINE_LEN) break if line.nil? || line.empty? m = line.match(RE_HEADER_LINE) raise ProtocolError, "Invalid header: #{line[0..2047].inspect}" if !m k = m[1].downcase if (h = headers[k]) (h = headers[k] = [h]) if !h.is_a?(Array) h << m[2] else headers[k] = m[2] end end headers end |
#http_skip_body(headers) ⇒ void
This method returns an undefined value.
Skips an HTTP reuqest/response body.
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/syntropy/http/io_extensions.rb', line 112 def http_skip_body(headers) content_length = headers['content-length'] if content_length content_length = content_length.to_i return if content_length == 0 return skip(content_length.to_i) end chunked_encoding = headers['transfer-encoding']&.downcase == 'chunked' if chunked_encoding while http_skip_cte_chunk end end end |
#http_write_request_headers(headers) ⇒ void
This method returns an undefined value.
Writes HTTP request headers.
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/syntropy/http/io_extensions.rb', line 152 def http_write_request_headers(headers) method = headers[':method'] || (raise BadRequestError) path = headers[':path'] || (raise BadRequestError) lines = ["#{method} #{path} HTTP/1.1\r\n"] headers.each do |k, v| next if k =~ /^\:/ if v.is_a?(Array) v.each { lines << "#{k}: #{it}\r\n" } else lines << "#{k}: #{v}\r\n" end end lines << "\r\n" write(*lines) end |