Class: Nonnative::HTTPProxy
- Inherits:
-
HTTPService
- Object
- HTTPService
- Nonnative::HTTPProxy
- Defined in:
- lib/nonnative/http_proxy_server.rb
Overview
HTTP service implementing a simple forward proxy.
The upstream host is configured via service settings (see HTTPProxyServer).
Supported HTTP verbs: GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS.
Constant Summary collapse
- NON_FORWARDABLE_RESPONSE_HEADERS =
%w[ connection content-encoding content-length keep-alive location proxy-authenticate proxy-authorization proxy-authentication-info proxy-connection set-cookie status te trailer transfer-encoding upgrade ].freeze
- NON_FORWARDABLE_REQUEST_HEADERS =
%w[ host accept-encoding version proxy-authenticate proxy-authorization proxy-connection connection keep-alive te trailer transfer-encoding upgrade ].freeze
- GATEWAY_TIMEOUT_ERRORS =
[ RestClient::Exceptions::Timeout ].freeze
- GATEWAY_CONNECTION_ERRORS =
[ RestClient::ServerBrokeConnection, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, SocketError ].freeze
- PATH_ESCAPE_PATTERN =
Match malformed percent escapes and bytes outside RFC 3986's path-safe set. Valid
%HHescapes remain intact; each match is percent-encoded before building the upstream URI. %r{%(?![\da-fA-F]{2})|[^A-Za-z0-9\-._~!$&'()*+,;=:@/%]}
Instance Method Summary collapse
-
#api_response(method:, url:, headers:, payload: nil) ⇒ RestClient::Response
Executes the upstream request and returns the response.
-
#build_url(request, settings) ⇒ String
Builds the upstream URL for the given request.
-
#forward_request_headers(request) ⇒ Hash{String=>String}
Extracts request headers from the Rack environment and normalizes them to standard HTTP names.
-
#retrieve_payload(request, verb) ⇒ String?
Extracts the request payload for verbs that can carry a body.
Instance Method Details
#api_response(method:, url:, headers:, payload: nil) ⇒ RestClient::Response
Executes the upstream request and returns the response.
114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/nonnative/http_proxy_server.rb', line 114 def api_response(method:, url:, headers:, payload: nil) = { method:, url:, headers: } [:payload] = payload unless payload.nil? RestClient::Request.execute() rescue *GATEWAY_TIMEOUT_ERRORS halt 504 rescue *GATEWAY_CONNECTION_ERRORS halt 502 rescue RestClient::Exception => e return e.response if e.response halt 502 end |
#build_url(request, settings) ⇒ String
Builds the upstream URL for the given request.
98 99 100 101 102 103 104 |
# File 'lib/nonnative/http_proxy_server.rb', line 98 def build_url(request, settings) uri_class = settings.scheme == 'http' ? URI::HTTP : URI::HTTPS query = request.query_string path = escape_path(request.path_info) uri_class.build(host: settings.host, port: settings.port, path:, query: query.empty? ? nil : query).to_s end |
#forward_request_headers(request) ⇒ Hash{String=>String}
Extracts request headers from the Rack environment and normalizes them to standard HTTP names.
Certain hop-by-hop or proxy-specific headers are removed.
82 83 84 85 86 87 88 89 90 91 |
# File 'lib/nonnative/http_proxy_server.rb', line 82 def forward_request_headers(request) headers = request.env.each_with_object({}) do |(header, value), result| next unless forward_request_header?(header) result[normalized_request_header_name(header)] = value end connection_headers = request_connection_headers(headers) headers.reject { |header, _| non_forwardable_request_header?(header, connection_headers) } end |
#retrieve_payload(request, verb) ⇒ String?
Extracts the request payload for verbs that can carry a body.
134 135 136 137 138 139 |
# File 'lib/nonnative/http_proxy_server.rb', line 134 def retrieve_payload(request, verb) return unless %w[post put patch delete].include?(verb) payload = request.body.read payload unless payload.empty? end |