107 lines
2.8 KiB
Ruby
107 lines
2.8 KiB
Ruby
|
require "cgi"
|
||
|
require "openid/yadis/xri"
|
||
|
require "openid/yadis/xrds"
|
||
|
require "openid/fetchers"
|
||
|
|
||
|
module OpenID
|
||
|
|
||
|
module Yadis
|
||
|
|
||
|
module XRI
|
||
|
|
||
|
class XRIHTTPError < StandardError; end
|
||
|
|
||
|
class ProxyResolver
|
||
|
|
||
|
DEFAULT_PROXY = 'http://proxy.xri.net/'
|
||
|
|
||
|
def initialize(proxy_url=nil)
|
||
|
if proxy_url
|
||
|
@proxy_url = proxy_url
|
||
|
else
|
||
|
@proxy_url = DEFAULT_PROXY
|
||
|
end
|
||
|
|
||
|
@proxy_url += '/' unless @proxy_url.match('/$')
|
||
|
end
|
||
|
|
||
|
def query_url(xri, service_type=nil)
|
||
|
# URI normal form has a leading xri://, but we need to strip
|
||
|
# that off again for the QXRI. This is under discussion for
|
||
|
# XRI Resolution WD 11.
|
||
|
qxri = XRI.to_uri_normal(xri)[6..-1]
|
||
|
hxri = @proxy_url + qxri
|
||
|
args = {'_xrd_r' => 'application/xrds+xml'}
|
||
|
if service_type
|
||
|
args['_xrd_t'] = service_type
|
||
|
else
|
||
|
# don't perform service endpoint selection
|
||
|
args['_xrd_r'] += ';sep=false'
|
||
|
end
|
||
|
|
||
|
return XRI.append_args(hxri, args)
|
||
|
end
|
||
|
|
||
|
def query(xri, service_types)
|
||
|
# these can be query args or http headers, needn't be both.
|
||
|
# headers = {'Accept' => 'application/xrds+xml;sep=true'}
|
||
|
canonicalID = nil
|
||
|
|
||
|
services = service_types.collect { |service_type|
|
||
|
url = self.query_url(xri, service_type)
|
||
|
begin
|
||
|
response = OpenID.fetch(url)
|
||
|
rescue
|
||
|
raise XRIHTTPError, ["Could not fetch #{xri}", $!]
|
||
|
end
|
||
|
raise XRIHTTPError, "Could not fetch #{xri}" if response.nil?
|
||
|
|
||
|
xrds = Yadis::parseXRDS(response.body)
|
||
|
canonicalID = Yadis::get_canonical_id(xri, xrds)
|
||
|
|
||
|
Yadis::services(xrds) unless xrds.nil?
|
||
|
}
|
||
|
# TODO:
|
||
|
# * If we do get hits for multiple service_types, we're almost
|
||
|
# certainly going to have duplicated service entries and
|
||
|
# broken priority ordering.
|
||
|
services = services.inject([]) { |flatter, some_services|
|
||
|
flatter += some_services unless some_services.nil?
|
||
|
}
|
||
|
|
||
|
return canonicalID, services
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def self.urlencode(args)
|
||
|
a = []
|
||
|
args.each do |key, val|
|
||
|
a << (CGI::escape(key) + "=" + CGI::escape(val))
|
||
|
end
|
||
|
a.join("&")
|
||
|
end
|
||
|
|
||
|
def self.append_args(url, args)
|
||
|
return url if args.length == 0
|
||
|
|
||
|
# rstrip question marks
|
||
|
rstripped = url.dup
|
||
|
while rstripped[-1].chr == '?'
|
||
|
rstripped = rstripped[0...rstripped.length-1]
|
||
|
end
|
||
|
|
||
|
if rstripped.index('?')
|
||
|
sep = '&'
|
||
|
else
|
||
|
sep = '?'
|
||
|
end
|
||
|
|
||
|
return url + sep + XRI.urlencode(args)
|
||
|
end
|
||
|
|
||
|
end
|
||
|
|
||
|
end
|
||
|
|
||
|
end
|