Last active
February 14, 2020 10:40
-
-
Save st0012/54d846701b6146c4491200ab6ae7258c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module URLHelper | |
IP_HOST_REGEXP = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/ | |
HOST_REGEXP = /(^[^:]+:\/\/)?(\[[^\]]+\]|[^:]+)(?::(\d+$))?/ | |
PROTOCOL_REGEXP = /^([^:]+)(:)?(\/\/)?$/ | |
class << self | |
def url_for(options) | |
if options[:only_path] | |
path_for options | |
else | |
full_url_for options | |
end | |
end | |
def full_url_for(options) | |
host = options[:host] | |
protocol = options[:protocol] | |
port = options[:port] | |
unless host | |
raise ArgumentError, "Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true" | |
end | |
build_host_url(host, port, protocol, options, path_for(options)) | |
end | |
def path_for(options) | |
path = options[:script_name].to_s.chomp("/") | |
path << options[:path] if options.key?(:path) | |
add_trailing_slash(path) if options[:trailing_slash] | |
add_params(path, options[:params]) if options.key?(:params) | |
add_anchor(path, options[:anchor]) if options.key?(:anchor) | |
path | |
end | |
private | |
def add_params(path, params) | |
params = { params: params } unless params.is_a?(Hash) | |
params.reject! { |_, v| v.nil? } | |
query = params.to_query | |
path << "?#{query}" unless query.empty? | |
end | |
def add_anchor(path, anchor) | |
if anchor | |
path << "##{anchor}" | |
end | |
end | |
def extract_domain_from(host, tld_length) | |
host.split(".").last(2 + tld_length).join(".") | |
end | |
def build_host_url(host, port, protocol, options, path) | |
if match = host.match(HOST_REGEXP) | |
protocol ||= match[1] unless protocol == false | |
host = match[2] | |
port = match[3] unless options.key? :port | |
end | |
protocol = normalize_protocol protocol | |
host = normalize_host(host, options) | |
result = protocol.dup | |
result << host | |
normalize_port(port, protocol) { |normalized_port| | |
result << ":#{normalized_port}" | |
} | |
result.concat path | |
end | |
def named_host?(host) | |
!IP_HOST_REGEXP.match?(host) | |
end | |
def normalize_protocol(protocol) | |
case protocol | |
when nil | |
"http://" | |
when false, "//" | |
"//" | |
when PROTOCOL_REGEXP | |
"#{$1}://" | |
else | |
raise ArgumentError, "Invalid :protocol option: #{protocol.inspect}" | |
end | |
end | |
def normalize_host(_host, options) | |
return _host unless named_host?(_host) | |
tld_length = options[:tld_length] || @@tld_length | |
subdomain = options.fetch :subdomain, true | |
domain = options[:domain] | |
host = +"" | |
if subdomain == true | |
return _host if domain.nil? | |
host << extract_subdomains_from(_host, tld_length).join(".") | |
elsif subdomain | |
host << subdomain | |
end | |
host << "." unless host.empty? | |
host << (domain || extract_domain_from(_host, tld_length)) | |
host | |
end | |
def normalize_port(port, protocol) | |
return unless port | |
case protocol | |
when "//" then yield port | |
when "https://" | |
yield port unless port.to_i == 443 | |
else | |
yield port unless port.to_i == 80 | |
end | |
end | |
end | |
end | |
url = URLHelper.url_for(host: "www.ror.co.uk", subdomain: "api", tld_length: 2, path: "/shows", anchor: "title-1") | |
expected_url = "http://api.ror.co.uk/shows#title-1" | |
if url == expected_url | |
puts("It works :-)") | |
else | |
puts("Expect url to be #{expected_url}, got #{url}") | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment