require "net/http" require "net/https" require 'uri' require 'cgi' require 'forwardable' require "delegate" files = %w{ version helper_classes handlers response } files.each { |f| require File.join(File.dirname(__FILE__),'url',f) } # Main class for managing urls # url = URL.new('https://mail.google.com/mail/?shva=1#mbox') # url.params # => {:shva => '1'} # url.scheme # => 'https' # url.host # => 'mail.google.com' # url.domain # => 'google.com' # url.subdomain # => ['mail'] # url.path # => '/mail/' # url.hash # => 'mbox' # # url.subdomain = ['my','mail'] # url.params[:foo] = 'bar' # url.to_s # => 'https://my.mail.google.com/mail/?foo=bar&shva=1#mbox' class URL extend Forwardable attr_reader :string # The params for the request # @returns [URL::ParamsHash] attr_reader :params # Set the params for the request # Allows for url.params |= {:foo => 'bar'} # @returns [URL::ParamsHash] def params= p raise ArgumentError, 'Params must be a URL::ParamsHash' unless p.is_a?(ParamsHash) @params = p end # Attributes of the URL which are editable # @returns [String] attr_accessor :domain, :scheme, :format, :port, :hash # The path for the request # @returns [URL::Path] attr_reader :path # Set the path for the request def path=str if str.nil? || str.empty? str = '/' end @path = str end def add_to_path val unless @path[-1] == 47 # '/' @path << '/' end @path << val.sub(/^\//,'') @path end # Returns array of subdomains # @returns [URL::Subdomain] attr_reader :subdomain alias_method :subdomains, :subdomain # @param [Array,String] subdomain An array or string for subdomain def subdomain=(s) if s.is_a?(String) s = s.split('.') end @subdomain = s end alias_method :subdomains=, :subdomain= # Creates a new URL object # @param [String] URL the starting url to work with def initialize str @string = str sp = URI.split(@string) @scheme = sp[0] @port = sp[3] self.path = sp[5] @format = @path.gsub(/(.+\.)/,'') @hash = sp[8] if sp[2] host_parts = sp[2].split('.') if host_parts[-2] == 'co' @domain = host_parts[-3,3].join('.') @subdomain = host_parts.first(host_parts.length-3) else begin @domain = host_parts[-2,2].join('.') @subdomain = host_parts.first(host_parts.length-2) rescue # if there arent at least 2 parts eg: localhost @domain = host_parts.join('.') end end else @domain = nil @subdomain = nil end @params = ParamsHash.new if sp[7] sp[7].gsub('?','').split('&').each do |myp| key,value = myp.split('=') value = CGI.unescape(value) if value @params[key.to_sym] = value if key end end end def_delegators :@params, :[], :[]= # The full hostname (not including port) for the URL def host [@subdomain,@domain].flatten.compact.join('.') end # Messed up host/hostname issue :( def host_with_port host<<':'<" end def dup URL.new(to_s) end # The request handler for this # @return [Handler] def req_handler (@req_handler||self.class.req_handler).new(self) end def =~ reg to_s =~ reg end # Sets the handler to use for this request # @param [RequstHandler] # @return [RequstHandler] def req_handler=r raise ArgumentError, 'Must be a subclass of URL::Handler' unless r < RequestHandler @req_handler = r end end