Class: Nonnative::HTTPProxy

Inherits:
Sinatra::Application
  • Object
show all
Defined in:
lib/nonnative/http_proxy_server.rb

Overview

Sinatra application implementing a simple forward proxy.

The upstream host is configured via Sinatra settings (see HTTPProxyServer).

Supported HTTP verbs: GET, POST, PUT, PATCH, DELETE.

Constant Summary collapse

NON_FORWARDABLE_HEADERS =
%w[
  Host
  Accept-Encoding
  Version
  Proxy-Authenticate
  Proxy-Authorization
].freeze

Instance Method Summary collapse

Instance Method Details

#api_response(method:, url:, headers:, payload: nil) ⇒ RestClient::Response

Executes the upstream request and returns the response.

Parameters:

  • method (Symbol)

    HTTP verb name (e.g. ‘:get`)

  • url (String)

    upstream URL

  • headers (Hash)

    request headers

  • payload (String, nil) (defaults to: nil)

    request payload

Returns:

  • (RestClient::Response)

    response for error statuses, otherwise RestClient return value



66
67
68
69
70
71
72
73
# File 'lib/nonnative/http_proxy_server.rb', line 66

def api_response(method:, url:, headers:, payload: nil)
  options = { method:, url:, headers: }
  options[:payload] = payload unless payload.nil?

  RestClient::Request.execute(options)
rescue RestClient::Exception => e
  e.response
end

#build_url(request, settings) ⇒ String

Builds the upstream URL for the given request.

Parameters:

  • request (Sinatra::Request)

    the incoming request

  • settings (Sinatra::Base)

    Sinatra settings, expected to include ‘host`

Returns:

  • (String)

    HTTPS URL for the upstream request



55
56
57
# File 'lib/nonnative/http_proxy_server.rb', line 55

def build_url(request, settings)
  URI::HTTPS.build(host: settings.host, path: request.path_info, query: request.query_string).to_s
end

#retrieve_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.

Parameters:

  • request (Sinatra::Request)

    the incoming request

Returns:

  • (Hash{String=>String})

    headers to forward to the upstream



40
41
42
43
44
45
46
47
48
# File 'lib/nonnative/http_proxy_server.rb', line 40

def retrieve_headers(request)
  headers = request.env.each_with_object({}) do |(header, value), result|
    next unless forward_header?(header)

    result[normalized_header_name(header)] = value
  end

  headers.except(*NON_FORWARDABLE_HEADERS)
end

#retrieve_payload(request, verb) ⇒ String?

Extracts the request payload for verbs that can carry a body.

Parameters:

  • request (Sinatra::Request)

    the incoming request

  • verb (String)

    HTTP verb name (e.g. ‘“post”`)

Returns:

  • (String, nil)

    request payload for body-carrying verbs



80
81
82
83
84
85
# File 'lib/nonnative/http_proxy_server.rb', line 80

def retrieve_payload(request, verb)
  return unless %w[post put patch delete].include?(verb)

  payload = request.body.read
  payload unless payload.empty?
end