Module: Puma::ClientEnv
Relationships & Source Files | |
Extension / Inclusion / Inheritance Descendants | |
Included In:
| |
Super Chains via Extension / Inclusion / Inheritance | |
Instance Chain:
self,
Const
|
|
Defined in: | lib/puma/client_env.rb |
Overview
This module is included in Client
. It contains code to process the env
before it is passed to the app.
Constant Summary
Const
- Included
BANNED_HEADER_KEY, CGI_VER, CHUNKED, CHUNK_SIZE, CLOSE, CLOSE_CHUNKED, CODE_NAME, COLON, CONNECTION_CLOSE, CONNECTION_KEEP_ALIVE, CONTENT_LENGTH, CONTENT_LENGTH2, CONTENT_LENGTH_S, CONTINUE, DQUOTE, EARLY_HINTS, ERROR_RESPONSE, FAST_TRACK_KA_TIMEOUT, GATEWAY_INTERFACE, HALT_COMMAND, HEAD, HIJACK, HIJACK_IO, HIJACK_P, HTTP, HTTPS, HTTPS_KEY, HTTP_10_200, HTTP_11, HTTP_11_100, HTTP_11_200, HTTP_CONNECTION, HTTP_EXPECT, HTTP_HEADER_DELIMITER, HTTP_HOST, HTTP_VERSION, HTTP_X_FORWARDED_FOR, HTTP_X_FORWARDED_PROTO, HTTP_X_FORWARDED_SCHEME, HTTP_X_FORWARDED_SSL, IANA_HTTP_METHODS, ILLEGAL_HEADER_KEY_REGEX, ILLEGAL_HEADER_VALUE_REGEX, KEEP_ALIVE, LINE_END, LOCALHOST, LOCALHOST_IPV4, LOCALHOST_IPV6, MAX_BODY, MAX_HEADER, NEWLINE, PATH_INFO, PORT_443, PORT_80, PROXY_PROTOCOL_V1_REGEX, PUMA_CONFIG, PUMA_PEERCERT, PUMA_SERVER_STRING, PUMA_SOCKET, PUMA_TMP_BASE, PUMA_VERSION, QUERY_STRING, RACK_AFTER_REPLY, RACK_INPUT, RACK_URL_SCHEME, REMOTE_ADDR, REQUEST_METHOD, REQUEST_PATH, REQUEST_URI, RESTART_COMMAND, SERVER_NAME, SERVER_PORT, SERVER_PROTOCOL, SERVER_SOFTWARE, STOP_COMMAND, SUPPORTED_HTTP_METHODS, TRANSFER_ENCODING, TRANSFER_ENCODING2, TRANSFER_ENCODING_CHUNKED, UNMASKABLE_HEADERS, UNSPECIFIED_IPV4, UNSPECIFIED_IPV6, WRITE_TIMEOUT
Instance Method Summary
- #default_server_port ⇒ Puma::Const::PORT_443, Puma::Const::PORT_80
-
#normalize_env
Given a Hash
env
for the request read fromclient
, add and fixup keys to comply with Rack’s env guidelines. -
#req_env_post_parse
Fixup any headers with
,
in the name to have_
now.
Instance Method Details
#default_server_port ⇒ Puma::Const::PORT_443, Puma::Const::PORT_80
# File 'lib/puma/client_env.rb', line 156
def default_server_port if ['on', HTTPS].include?(@env[HTTPS_KEY]) || @env[HTTP_X_FORWARDED_PROTO].to_s[0...5] == HTTPS || @env[HTTP_X_FORWARDED_SCHEME] == HTTPS || @env[HTTP_X_FORWARDED_SSL] == "on" PORT_443 else PORT_80 end end
#normalize_env
Given a Hash env
for the request read from client
, add and fixup keys to comply with Rack’s env guidelines.
# File 'lib/puma/client_env.rb', line 20
def normalize_env if host = @env[HTTP_HOST] # host can be a hostname, ipv4 or bracketed ipv6. Followed by an optional port. if colon = host.rindex("]:") # IPV6 with port @env[SERVER_NAME] = host[0, colon+1] @env[SERVER_PORT] = host[colon+2, host.bytesize] elsif !host.start_with?("[") && colon = host.index(":") # not hostname or IPV4 with port @env[SERVER_NAME] = host[0, colon] @env[SERVER_PORT] = host[colon+1, host.bytesize] else @env[SERVER_NAME] = host @env[SERVER_PORT] = default_server_port end else @env[SERVER_NAME] = LOCALHOST @env[SERVER_PORT] = default_server_port end unless @env[REQUEST_PATH] # it might be a dumbass full host request header uri = begin URI.parse(@env[REQUEST_URI]) rescue URI::InvalidURIError raise Puma::HttpParserError end @env[REQUEST_PATH] = uri.path # A nil env value will cause a LintError (and fatal errors elsewhere), # so only set the env value if there actually is a value. @env[QUERY_STRING] = uri.query if uri.query end @env[PATH_INFO] = @env[REQUEST_PATH].to_s # #to_s in case it's nil # From https://www.ietf.org/rfc/rfc3875 : # "Script authors should be aware that the REMOTE_ADDR and # REMOTE_HOST meta-variables (see sections 4.1.8 and 4.1.9) # may not identify the ultimate source of the request. # They identify the client for the immediate request to the # server; that client may be a proxy, gateway, or other # intermediary acting on behalf of the actual source client." # unless @env.key?(REMOTE_ADDR) begin addr = peerip rescue Errno::ENOTCONN # Client disconnects can result in an inability to get the # peeraddr from the socket; default to unspec. if peer_family == Socket::AF_INET6 addr = UNSPECIFIED_IPV6 else addr = UNSPECIFIED_IPV4 end end # Set unix socket addrs to localhost if addr.empty? addr = peer_family == Socket::AF_INET6 ? LOCALHOST_IPV6 : LOCALHOST_IPV4 end @env[REMOTE_ADDR] = addr end # The legacy HTTP_VERSION header can be sent as a client header. # Rack v4 may remove using HTTP_VERSION. If so, remove this line. @env[HTTP_VERSION] = @env[SERVER_PROTOCOL] @env[PUMA_SOCKET] = @io if @env[HTTPS_KEY] && @io.peercert @env[PUMA_PEERCERT] = @io.peercert end @env[HIJACK_P] = true @env[HIJACK] = self @env[RACK_INPUT] = @body || EmptyBody @env[RACK_URL_SCHEME] ||= default_server_port == PORT_443 ? HTTPS : HTTP end
#req_env_post_parse
If a normalized version of a ,
header already exists, we ignore the ,
version. This prevents clobbering headers managed by proxies but not by clients (Like X-Forwarded-For).
Fixup any headers with ,
in the name to have _
now. We emit headers with ,
in them during the parse phase to avoid ambiguity with the -
to _
conversion for critical headers. But here for compatibility, we’ll convert them back. This code is written to avoid allocation in the common case (ie there are no headers with ,
in their names), that’s why it has the extra conditionals.
# File 'lib/puma/client_env.rb', line 115
def req_env_post_parse to_delete = nil to_add = nil @env.each do |k,v| if k.start_with?("HTTP_") && k.include?(",") && !UNMASKABLE_HEADERS.key?(k) if to_delete to_delete << k else to_delete = [k] end new_k = k.tr(",", "_") if @env.key?(new_k) next end unless to_add to_add = {} end to_add[new_k] = v end end if to_delete # rubocop:disable Style/SafeNavigation to_delete.each { |k| env.delete(k) } end if to_add @env.merge! to_add end # A rack extension. If the app writes #call'ables to this # array, we will invoke them when the request is done. # env[RACK_AFTER_REPLY] ||= [] end