Skip to content

Instantly share code, notes, and snippets.

@zernel
Created August 25, 2017 08:20
Show Gist options
  • Save zernel/0f10c71f5a9e044653c1a65c6c5ad697 to your computer and use it in GitHub Desktop.
Save zernel/0f10c71f5a9e044653c1a65c6c5ad697 to your computer and use it in GitHub Desktop.

Revisions

  1. zernel created this gist Aug 25, 2017.
    43 changes: 43 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,43 @@
    # Why do we need KudeURI? Because the URI.join method doing something stupid:
    #
    # URI.join('http://example.com/subpath', 'hello', '?token=secret')
    # => “http://example.com/hello?token=secret”
    #
    # But what I expected is “http://example.com/subpath/hello?token=secret", the subpath is gone.
    # By using SmartURI, you can handle the case above gracefully:
    #
    # SmartURI.join('http://example.com/subpath', 'hello', query: { token: secret })
    # => "http://example.com/subpath/hello?token=secret"

    require 'uri'

    module SmartURI
    SEPARATOR = '/'

    def self.join(*paths, query: nil)
    paths = paths.compact.reject(&:empty?)
    last = paths.length - 1
    url = paths.each_with_index.map { |path, index|
    _expand(path, index, last)
    }.join
    if query.nil?
    return url
    elsif query.is_a? Hash
    return url + "?#{URI.encode_www_form(query.to_a)}"
    else
    raise "Unexpected input type for query: #{query}, it should be a hash."
    end
    end

    def self._expand(path, current, last)
    if path.starts_with?(SEPARATOR) && current != 0
    path = path[1..-1]
    end

    unless path.ends_with?(SEPARATOR) || current == last
    path = [path, SEPARATOR]
    end

    path
    end
    end