Class: HTTP::Request::Writer
- Inherits:
-
Object
- Object
- HTTP::Request::Writer
- Defined in:
- lib/http/request/writer.rb
Overview
Streams HTTP requests to a socket
Constant Summary collapse
- CRLF =
CRLF is the universal HTTP delimiter
"\r\n"- ZERO =
Chunked data terminator
"0"- CHUNKED_END =
End of a chunked transfer
"#{ZERO}#{CRLF}#{CRLF}".freeze
Instance Method Summary collapse
-
#add_body_type_headers ⇒ void
Adds content length or transfer encoding headers.
-
#add_headers ⇒ void
Adds headers to the request header array.
-
#chunked? ⇒ Boolean
Returns true if using chunked transfer encoding.
-
#connect_through_proxy ⇒ void
Send headers needed to connect through proxy.
-
#each_chunk {|data| ... } ⇒ void
Yields chunks of request data for the socket.
-
#encode_chunk(chunk) ⇒ String
Returns chunk encoded per Transfer-Encoding header.
-
#initialize(socket, body, headers, headline) ⇒ HTTP::Request::Writer
constructor
Initialize a new request writer.
-
#join_headers ⇒ String
Joins headers into an HTTP request header string.
-
#send_request ⇒ void
Writes HTTP request data into the socket.
-
#stream ⇒ void
Stream the request to a socket.
Constructor Details
#initialize(socket, body, headers, headline) ⇒ HTTP::Request::Writer
Initialize a new request writer
25 26 27 28 29 30 |
# File 'lib/http/request/writer.rb', line 25 def initialize(socket, body, headers, headline) @body = body @socket = socket @headers = headers @request_header = [headline] end |
Instance Method Details
#add_body_type_headers ⇒ void
This method returns an undefined value.
Adds content length or transfer encoding headers
77 78 79 80 81 82 83 84 85 |
# File 'lib/http/request/writer.rb', line 77 def add_body_type_headers return if @headers[Headers::CONTENT_LENGTH] || chunked? || ( @body.source.nil? && %w[GET HEAD DELETE CONNECT].any? do |method| @request_header.fetch(0).start_with?("#{method} ") end ) @request_header << "#{Headers::CONTENT_LENGTH}: #{@body.size}" end |
#add_headers ⇒ void
This method returns an undefined value.
Adds headers to the request header array
39 40 41 42 43 |
# File 'lib/http/request/writer.rb', line 39 def add_headers @headers.each do |field, value| @request_header << "#{field}: #{value}" end end |
#chunked? ⇒ Boolean
Returns true if using chunked transfer encoding
162 163 164 |
# File 'lib/http/request/writer.rb', line 162 def chunked? @headers[Headers::TRANSFER_ENCODING].eql?(Headers::CHUNKED) end |
#connect_through_proxy ⇒ void
This method returns an undefined value.
Send headers needed to connect through proxy
65 66 67 68 |
# File 'lib/http/request/writer.rb', line 65 def connect_through_proxy add_headers write(join_headers) end |
#each_chunk {|data| ... } ⇒ void
This method returns an undefined value.
Yields chunks of request data for the socket
It’s important to send the request in a single write call when possible in order to play nicely with Nagle’s algorithm. Making two writes in a row triggers a pathological case where Nagle is expecting a third write that never happens.
126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/http/request/writer.rb', line 126 def each_chunk data = join_headers @body.each do |chunk| data << encode_chunk(chunk) yield data data.clear end yield data unless data.empty? yield CHUNKED_END if chunked? end |
#encode_chunk(chunk) ⇒ String
Returns chunk encoded per Transfer-Encoding header
147 148 149 150 151 152 153 |
# File 'lib/http/request/writer.rb', line 147 def encode_chunk(chunk) if chunked? chunk.bytesize.to_s(16) << CRLF << chunk << CRLF else chunk end end |
#join_headers ⇒ String
Joins headers into an HTTP request header string
94 95 96 97 98 |
# File 'lib/http/request/writer.rb', line 94 def join_headers # join the headers array with crlfs, stick two on the end because # that ends the request header @request_header.join(CRLF) + (CRLF * 2) end |
#send_request ⇒ void
This method returns an undefined value.
Writes HTTP request data into the socket
107 108 109 110 111 112 |
# File 'lib/http/request/writer.rb', line 107 def send_request each_chunk { |chunk| write chunk } rescue Errno::EPIPE # server doesn't need any more data nil end |
#stream ⇒ void
This method returns an undefined value.
Stream the request to a socket
52 53 54 55 56 |
# File 'lib/http/request/writer.rb', line 52 def stream add_headers add_body_type_headers send_request end |