Module: Raptor::Http
- Defined in:
- lib/raptor/http.rb,
sig/generated/raptor/http.rbs
Overview
Shared HTTP utilities used by both the HTTP/1.x and HTTP/2 handlers: Rack env keys that aren't provided by Rack itself, low-level socket writing, and Common Log Format access-log formatting.
Defined Under Namespace
Classes: WriteError
Constant Summary collapse
- WRITE_TIMEOUT =
5- CONTENT_LENGTH =
"CONTENT_LENGTH"- CONTENT_TYPE =
"CONTENT_TYPE"- HTTP_VERSION =
"HTTP_VERSION"- REMOTE_ADDR =
"REMOTE_ADDR"- REQUEST_URI =
"REQUEST_URI"- SERVER_SOFTWARE =
"SERVER_SOFTWARE"- SERVER_SOFTWARE_VALUE =
"Raptor/#{Raptor::VERSION}".freeze
Class Method Summary collapse
-
.parser_worker(env_template, max_body_size) ⇒ Proc
Returns a Ractor-safe proc that routes each pipeline task to the HTTP/1.x or HTTP/2 handler based on the state hash's
:protocolkey. -
.socket_write(socket, string, timeout: WRITE_TIMEOUT) ⇒ void
Writes
stringin full, retrying on partial writes. -
.socket_writev(socket, strings, timeout: WRITE_TIMEOUT) ⇒ void
Writes
stringsin full via a singlewritev(2)syscall when possible, falling back to per-string writes on partial results. -
.write_access_log(io, env, status, size, remote_addr) ⇒ void
Writes a Common Log Format entry to
io.
Class Method Details
.parser_worker(env_template, max_body_size) ⇒ Proc
Returns a Ractor-safe proc that routes each pipeline task to the
HTTP/1.x or HTTP/2 handler based on the state hash's :protocol key.
104 105 106 107 108 109 110 111 112 |
# File 'lib/raptor/http.rb', line 104 def self.parser_worker(env_template, max_body_size) proc do |data| if data[:protocol] == :http2 Raptor::Http2.process_frames(data) else Raptor::Http1.parse(data, env_template, max_body_size) end end end |
.socket_write(socket, string, timeout: WRITE_TIMEOUT) ⇒ void
This method returns an undefined value.
Writes string in full, retrying on partial writes. Bounded by
timeout so a slow client can't pin the writing thread.
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/raptor/http.rb', line 40 def self.socket_write(socket, string, timeout: WRITE_TIMEOUT) bytes = 0 byte_size = string.bytesize while bytes < byte_size begin bytes += socket.write_nonblock(bytes.zero? ? string : string.byteslice(bytes..-1)) rescue IO::WaitWritable raise WriteError unless socket.wait_writable(timeout) retry rescue IOError raise WriteError end end end |
.socket_writev(socket, strings, timeout: WRITE_TIMEOUT) ⇒ void
This method returns an undefined value.
Writes strings in full via a single writev(2) syscall when possible,
falling back to per-string writes on partial results. Bounded by
timeout so a slow client can't pin the writing thread.
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 |
# File 'lib/raptor/http.rb', line 67 def self.socket_writev(socket, strings, timeout: WRITE_TIMEOUT) total = strings.sum(&:bytesize) return if total.zero? begin written = Raptor::VectorIO.writev_nonblock(socket, strings) rescue IO::WaitWritable raise WriteError unless socket.wait_writable(timeout) retry rescue IOError raise WriteError end return if written == total offset = 0 strings.each do |string| size = string.bytesize if written >= offset + size offset += size else start = written - offset socket_write(socket, start.zero? ? string : string.byteslice(start..-1), timeout: timeout) offset += size written = offset end end end |
.write_access_log(io, env, status, size, remote_addr) ⇒ void
This method returns an undefined value.
Writes a Common Log Format entry to io. Write failures are silently
ignored.
125 126 127 128 129 130 131 132 133 |
# File 'lib/raptor/http.rb', line 125 def self.write_access_log(io, env, status, size, remote_addr) = Time.now.strftime("%d/%b/%Y:%H:%M:%S %z") method = env[Rack::REQUEST_METHOD] query = env[Rack::QUERY_STRING] path = query.empty? ? env[Rack::PATH_INFO] : "#{env[Rack::PATH_INFO]}?#{query}" protocol = env[Rack::SERVER_PROTOCOL] io.puts(%(#{remote_addr} - - [#{}] "#{method} #{path} #{protocol}" #{status} #{size})) rescue nil end |