How do I safely join relative url segments?

前端 未结 11 1838
南方客
南方客 2020-12-30 19:27

I\'m trying to find a robust method of joining partial url path segments together. Is there a quick way to do this?

I tried the following:

puts URI::         


        
相关标签:
11条回答
  • 2020-12-30 20:23

    You can use this:

    URI.join('http://exemple.com', '/a/', 'b/', 'c/', 'd')
    => #<URI::HTTP http://exemple.com/a/b/c/d>
    URI.join('http://exemple.com', '/a/', 'b/', 'c/', 'd').to_s
    => "http://exemple.com/a/b/c/d"
    

    See: http://ruby-doc.org/stdlib-2.4.1/libdoc/uri/rdoc/URI.html#method-c-join-label-Synopsis

    0 讨论(0)
  • 2020-12-30 20:24

    Have uri as URI::Generic or subclass of thereof

    uri.path += '/123' 
    

    Enjoy!

    06/25/2016 UPDATE for skeptical folk

    require 'uri'
    uri = URI('http://ioffe.net/boris')
    uri.path += '/123'
    p uri
    

    Outputs

     <URI::HTTP:0x2341a58 URL:http://ioffe.net/boris/123>
    

    Run me

    0 讨论(0)
  • 2020-12-30 20:26

    You can use File.join('resource/', '/edit', '12?option=test')

    0 讨论(0)
  • 2020-12-30 20:27

    My understanding of URI::join is that it thinks like a web browser does.

    To evaluate it, point your mental web browser to the first parameter, and keep clicking links until you browse to the last parameter.

    For example, URI::join('http://example.com/resource/', '/edit', '12?option=test'), you would browse like this:

    • http://example.com/resource/, click a link to /edit (a file at the root of the site)
    • http://example.com/edit, click a link to 12?option=test (a file in the same directory as edit)
    • http://example.com/12?option=test

    If the first link were /edit/ (with a trailing slash), or /edit/foo, then the next link would be relative to /edit/ rather than /.

    This page possibly explains it better than I can: Why is URI.join so counterintuitive?

    0 讨论(0)
  • 2020-12-30 20:29

    I improved @Maximo Mussini's script to make it works gracefully:

    SmartURI.join('http://example.com/subpath', 'hello', query: { token: secret })
    => "http://example.com/subpath/hello?token=secret"
    

    https://gist.github.com/zernel/0f10c71f5a9e044653c1a65c6c5ad697

    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
    
    0 讨论(0)
提交回复
热议问题