module Ronin::Support::Network::HTTP::Request

Handles building HTTP request objects.

@api private

@since 1.0.0

Constants

METHODS

Request methods and ‘Net::HTTP` request classes.

MIME_TYPES

Common MIME types.

@since 1.1.0

Public Class Methods

build(method,path, query: nil, query_params: nil, user: nil, password: nil, headers: nil, content_type: nil, accept: nil, user_agent: nil, cookie: nil, body: nil, form_data: nil, json: nil) click to toggle source

Creates a new ‘Net::HTTP` request.

@param [:copy, :delete, :get, :head, :lock, :mkcol, :move,

      :options, :patch, :post, :propfind, :proppatch, :put,
      :trace, :unlock] method
The HTTP request method to use.

@param [String] path

@param [String, nil] query

The query-string to append to the request path.

@param [Hash, nil] query_params

The query-params to append to the request path.

@param [String, nil] user

The user to authenticate as.

@param [String, nil] password

The password to authenticate with.

@param [Hash{Symbol => String}, Hash{String => String}, nil] headers

Additional HTTP header names and values to add to the request.

@param [String, :text, :xml, :html, :json, nil] content_type

The `Content-Type` header value for the request.
If a Symbol is given it will be resolved to a common MIME type:
* `:text` - `text/plain`
* `:xml` - `text/xml`
* `:html` - `text/html`
* `:json` - `application/json`

@param [String, :text, :xml, :html, :json, nil] accept

The `Accept` header value for the request.
If a Symbol is given it will be resolved to a common MIME type:
* `:text` - `text/plain`
* `:xml` - `text/xml`
* `:html` - `text/html`
* `:json` - `application/json`

@param [String, :random, :chrome, :chrome_linux, :chrome_macos,

    :chrome_windows, :chrome_iphone, :chrome_ipad,
    :chrome_android, :firefox, :firefox_linux, :firefox_macos,
    :firefox_windows, :firefox_iphone, :firefox_ipad,
    :firefox_android, :safari, :safari_macos, :safari_iphone,
    :safari_ipad, :edge, :linux, :macos, :windows, :iphone,
    :ipad, :android, nil] user_agent
The `User-Agent` header value for the request.

@param [String, Hash{String => String}, Cookie, nil] cookie

Additional `Cookie` header. If a `Hash` is given, it will be
converted to a `String` using {Cookie}. If the cookie value is
empty, the `Cookie` header will not be set.

@param [String, nil] body

The body of the request.

@param [Hash, String, nil] form_data

The form data that may be sent in the body of the request.

@param [#to_json, nil] json

The JSON data that will be sent in the body of the request.
Will also default the `Content-Type` header to `application/json`,
unless already set.

@return [Net::HTTP::Copy,

       Net::HTTP::Delete,
       Net::HTTP::Get,
       Net::HTTP::Head,
       Net::HTTP::Lock,
       Net::HTTP::Mkcol,
       Net::HTTP::Move,
       Net::HTTP::Options,
       Net::HTTP::Patch,
       Net::HTTP::Post,
       Net::HTTP::Propfind,
       Net::HTTP::Proppatch,
       Net::HTTP::Put,
       Net::HTTP::Trace,
       Net::HTTP::Unlock]
The built HTTP request object.
# File lib/ronin/support/network/http/request.rb, line 212
def self.build(method,path, # query string keyword arguments
                            query:        nil,
                            query_params: nil,
                            # Basic-Auth keyword arguments
                            user:     nil,
                            password: nil,
                            # Header keyword arguments
                            headers:      nil,
                            content_type: nil,
                            accept:       nil,
                            user_agent:   nil,
                            cookie:       nil,
                            # request body keyword arguments
                            body:      nil,
                            form_data: nil,
                            json:      nil)
  request_class = METHODS.fetch(method) do
    raise(ArgumentError,"unknown HTTP request method: #{method.inspect}")
  end

  request = request_class.new(
    request_uri(path, query: query, query_params: query_params),
    headers
  )

  if user
    user     = user.to_s
    password = password.to_s if password

    request.basic_auth(user,password)
  end

  if content_type
    request['Content-Type'] = mime_type_for(content_type)
  end

  if accept
    request['Accept'] = mime_type_for(accept)
  end

  if user_agent
    request['User-Agent'] = case user_agent
                            when Symbol then UserAgents[user_agent]
                            else             user_agent
                            end
  end

  if cookie && !cookie.empty?
    request['Cookie'] = case cookie
                        when Hash then HTTP::Cookie.new(cookie).to_s
                        else           cookie.to_s
                        end
  end

  if json
    request['Content-Type'] ||= 'application/json'

    request.body = json.to_json
  elsif form_data
    case form_data
    when String
      request['Content-Type'] ||= 'application/x-www-form-urlencoded'

      request.body = form_data
    else
      request.form_data = form_data
    end
  elsif body
    case body
    when IO, StringIO then request.body_stream = body
    else                   request.body        = body
    end
  end

  return request
end
mime_type_for(mime_type) click to toggle source

Resolves the MIME type.

@param [String, :text, :xml, :html, :json, nil] mime_type

The MIME type String or Symbol.
If a Symbol is given it will be resolved to a common MIME type:
* `:text` - `text/plain`
* `:xml` - `text/xml`
* `:html` - `text/html`
* `:json` - `application/json`

@return [String]

The resolved MIME type String.

@raise [ArgumentError]

An unknown Symbol is given.

@since 1.1.0

# File lib/ronin/support/network/http/request.rb, line 118
def self.mime_type_for(mime_type)
  case mime_type
  when Symbol
    MIME_TYPES.fetch(mime_type) do
      raise(ArgumentError,"unsupported MIME type: #{mime_type.inspect}")
    end
  else
    mime_type
  end
end
request_uri(path, query: nil, query_params: nil) click to toggle source

Builds the [Request-URI], aka path + query string, for a HTTP request.

[Request-URI]: www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2

@param [String] path

The path of the request.

@param [String, nil] query

The optional query string for the request.

@param [Hash{Symbol => Object},

      Hash{String => Object}, nil] query_params
Additional query params for the request.

@return [String]

# File lib/ronin/support/network/http/request.rb, line 55
def self.request_uri(path, query: nil, query_params: nil)
  if query_params
    query = URI::QueryParams.dump(query_params)
  end

  if query
    # append the query-string onto the path
    path += if path.include?('?') then "&#{query}"
            else                       "?#{query}"
            end
  end

  return path
end