Module: Puma::ClientEnv
Overview
This module is included in ‘Client`. It contains code to process the `env` before it is passed to the app.
Constant Summary
Constants included from Const
Puma::Const::BANNED_HEADER_KEY, Puma::Const::CGI_VER, Puma::Const::CHUNKED, Puma::Const::CHUNK_SIZE, Puma::Const::CLOSE, Puma::Const::CLOSE_CHUNKED, Puma::Const::CODE_NAME, Puma::Const::COLON, Puma::Const::CONNECTION_CLOSE, Puma::Const::CONNECTION_KEEP_ALIVE, Puma::Const::CONTENT_LENGTH, Puma::Const::CONTENT_LENGTH2, Puma::Const::CONTENT_LENGTH_S, Puma::Const::CONTINUE, Puma::Const::DQUOTE, Puma::Const::EARLY_HINTS, Puma::Const::ERROR_RESPONSE, Puma::Const::GATEWAY_INTERFACE, Puma::Const::HALT_COMMAND, Puma::Const::HEAD, Puma::Const::HIJACK, Puma::Const::HIJACK_IO, Puma::Const::HIJACK_P, Puma::Const::HTTP, Puma::Const::HTTPS, Puma::Const::HTTPS_KEY, Puma::Const::HTTP_10_200, Puma::Const::HTTP_11, Puma::Const::HTTP_11_100, Puma::Const::HTTP_11_200, Puma::Const::HTTP_CONNECTION, Puma::Const::HTTP_EXPECT, Puma::Const::HTTP_HEADER_DELIMITER, Puma::Const::HTTP_HOST, Puma::Const::HTTP_VERSION, Puma::Const::HTTP_X_FORWARDED_FOR, Puma::Const::HTTP_X_FORWARDED_PROTO, Puma::Const::HTTP_X_FORWARDED_SCHEME, Puma::Const::HTTP_X_FORWARDED_SSL, Puma::Const::IANA_HTTP_METHODS, Puma::Const::ILLEGAL_HEADER_KEY_REGEX, Puma::Const::ILLEGAL_HEADER_VALUE_REGEX, Puma::Const::KEEP_ALIVE, Puma::Const::LINE_END, Puma::Const::LOCALHOST, Puma::Const::LOCALHOST_IPV4, Puma::Const::LOCALHOST_IPV6, Puma::Const::MAX_BODY, Puma::Const::MAX_HEADER, Puma::Const::NEWLINE, Puma::Const::PATH_INFO, Puma::Const::PORT_443, Puma::Const::PORT_80, Puma::Const::PROXY_PROTOCOL_V1_REGEX, Puma::Const::PUMA_CONFIG, Puma::Const::PUMA_PEERCERT, Puma::Const::PUMA_SERVER_STRING, Puma::Const::PUMA_SOCKET, Puma::Const::PUMA_TMP_BASE, Puma::Const::PUMA_VERSION, Puma::Const::QUERY_STRING, Puma::Const::RACK_AFTER_REPLY, Puma::Const::RACK_INPUT, Puma::Const::RACK_RESPONSE_FINISHED, Puma::Const::RACK_URL_SCHEME, Puma::Const::REMOTE_ADDR, Puma::Const::REQUEST_METHOD, Puma::Const::REQUEST_PATH, Puma::Const::REQUEST_URI, Puma::Const::RESTART_COMMAND, Puma::Const::SERVER_NAME, Puma::Const::SERVER_PORT, Puma::Const::SERVER_PROTOCOL, Puma::Const::SERVER_SOFTWARE, Puma::Const::STOP_COMMAND, Puma::Const::SUPPORTED_HTTP_METHODS, Puma::Const::TRANSFER_ENCODING, Puma::Const::TRANSFER_ENCODING2, Puma::Const::TRANSFER_ENCODING_CHUNKED, Puma::Const::UNMASKABLE_HEADERS, Puma::Const::UNSPECIFIED_IPV4, Puma::Const::UNSPECIFIED_IPV6, Puma::Const::WRITE_TIMEOUT
Instance Method Summary collapse
- #default_server_port ⇒ Puma::Const::PORT_443, Puma::Const::PORT_80
-
#normalize_env ⇒ Object
Given a Hash
envfor the request read fromclient, add and fixup keys to comply with Rack’s env guidelines. -
#req_env_post_parse ⇒ Object
Fixup any headers with ‘,` in the name to have `_` now.
Instance Method Details
#default_server_port ⇒ Puma::Const::PORT_443, Puma::Const::PORT_80
160 161 162 163 164 165 166 167 168 169 |
# File 'lib/puma/client_env.rb', line 160 def default_server_port if HTTP_ON_VALUES[@env[HTTPS_KEY]] || @env[HTTP_X_FORWARDED_PROTO]&.start_with?(HTTPS) || @env[HTTP_X_FORWARDED_SCHEME] == HTTPS || @env[HTTP_X_FORWARDED_SSL] == "on" PORT_443 else PORT_80 end end |
#normalize_env ⇒ Object
Given a Hash env for the request read from client, add and fixup keys to comply with Rack’s env guidelines.
20 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 48 49 50 51 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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# 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] if @env_set_http_version @env[PUMA_SOCKET] = @io if @env[HTTPS_KEY] && @io.peercert @env[PUMA_PEERCERT] = @io.peercert end @env[HIJACK_P] = true @env[HIJACK] = method(:full_hijack).to_proc @env[RACK_INPUT] = @body || EmptyBody @env[RACK_URL_SCHEME] ||= default_server_port == PORT_443 ? HTTPS : HTTP end |
#req_env_post_parse ⇒ Object
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.
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# 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] ||= [] env[RACK_RESPONSE_FINISHED] ||= [] end |