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 parses an HTTP/1.x request from the state hash's buffered bytes.
-
.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 parses an HTTP/1.x request from the state hash's buffered bytes.
104 105 106 107 108 |
# File 'lib/raptor/http.rb', line 104 def self.parser_worker(env_template, max_body_size) proc do |data| Raptor::Http1.parse(data, env_template, max_body_size) 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.
121 122 123 124 125 126 127 128 129 |
# File 'lib/raptor/http.rb', line 121 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 |