Module: Skadi::Url

Defined in:
lib/skadi/url.rb

Overview

Helper functions for generating and redacting URLs

Class Method Summary collapse

Class Method Details

.redact_and_normalise_url(url, request: nil) ⇒ String?

Strips non-whitelisted query params and normalises URLs

Parameters:

  • url (String)
  • request (ActionDispatch::Request, nil) (defaults to: nil)

    the current request - used to truncate the current host from URLs

Returns:

  • (String, nil)


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
# File 'lib/skadi/url.rb', line 38

def self.redact_and_normalise_url(url, request: nil)
  return nil unless url.is_a?(String) && url.present?

  uri = URI.parse(url[0, Skadi.configuration.max_url_length])
  return nil if uri.opaque

  query_params = Rack::Utils.parse_nested_query(uri.query) if uri.query.present?
  param_string = whitelist_query_params(query_params).to_query if query_params.present?

  result = +""

  interesting_scheme = uri.scheme.present? && ![ "http", "https" ].include?(uri.scheme)
  # Only record interesting schemes, e.g. "android-app://"
  result += "#{uri.scheme}://" if interesting_scheme

  host_with_port = +""
  if uri.host.present?
    host_with_port << uri.host
    # Only include port if it's non-standard
    host_with_port << ":#{uri.port}" if uri.port != uri.default_port
  end

  is_local = request.present? && host_with_port == request.host_with_port
  result << host_with_port if interesting_scheme || Skadi.configuration.store_domain_in_views || !is_local

  path = uri.path&.start_with?("/") ? uri.path : "/#{uri.path}"
  # Normalise the trailing slash
  result << (path == "/" ? "/" : path.delete_suffix("/"))

  result << (param_string.present? ? "?#{param_string}" : "")

  return result
rescue URI::InvalidURIError, Rack::QueryParser::ParameterTypeError, Rack::QueryParser::QueryLimitError
  return nil
end

.view_path_from_request(request) ⇒ String

Formats the path for Skadi views. Note that the path here uses PATH_INFO, which does not include the query string or fragment.

Parameters:

  • request (ActionDispatch::Request)

Returns:

  • (String)


7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/skadi/url.rb', line 7

def self.view_path_from_request(request)
  path = +""

  if Skadi.configuration.store_domain_in_views
    path << request.host_with_port
  end

  # Normalise the path by removing any trailing slashes
  path << ((request.path == "/" || request.path == "") ? "/" : request.path.chomp("/"))

  path
end

.whitelist_query_params(query_params) ⇒ Hash

Parameters:

  • query_params (Hash, ActiveSupport::HashWithIndifferentAccess)

Returns:

  • (Hash)


22
23
24
25
26
27
28
29
30
31
32
# File 'lib/skadi/url.rb', line 22

def self.whitelist_query_params(query_params)
  # Normalise the input to a Hash with symbolic keys
  query_params = query_params.to_h.symbolize_keys

  return query_params unless Skadi.configuration.use_query_param_whitelist

  whitelist = Skadi.configuration.query_param_whitelist
  return {} if whitelist.empty?

  query_params.slice(*whitelist)
end