Package yadis :: Module discover
[hide private]
[frames] | no frames]

Source Code for Module yadis.discover

  1  # -*- test-case-name: yadis.test.test_discover -*- 
  2  __all__ = ['discover', 'DiscoveryResult', 'DiscoveryFailure'] 
  3   
  4  from cStringIO import StringIO 
  5   
  6  from urljr import fetchers 
  7   
  8  from yadis.constants import \ 
  9       YADIS_HEADER_NAME, YADIS_CONTENT_TYPE, YADIS_ACCEPT_HEADER 
 10  from yadis.parsehtml import MetaNotFound, findHTMLMeta 
 11   
12 -class DiscoveryFailure(Exception):
13 """Raised when a YADIS protocol error occurs in the discovery process""" 14 identity_url = None 15
16 - def __init__(self, message, http_response):
17 Exception.__init__(self, message) 18 self.http_response = http_response
19
20 -class DiscoveryResult(object):
21 """Contains the result of performing Yadis discovery on a URI""" 22 23 # The URI that was passed to the fetcher 24 request_uri = None 25 26 # The result of following redirects from the request_uri 27 normalized_uri = None 28 29 # The URI from which the response text was returned (set to 30 # None if there was no XRDS document found) 31 xrds_uri = None 32 33 # The content-type returned with the response_text 34 content_type = None 35 36 # The document returned from the xrds_uri 37 response_text = None 38
39 - def __init__(self, request_uri):
40 """Initialize the state of the object 41 42 sets all attributes to None except the request_uri 43 """ 44 self.request_uri = request_uri
45
46 - def usedYadisLocation(self):
47 """Was the Yadis protocol's indirection used?""" 48 return self.normalized_uri == self.xrds_uri
49
50 - def isXRDS(self):
51 """Is the response text supposed to be an XRDS document?""" 52 return (self.usedYadisLocation() or 53 self.content_type == YADIS_CONTENT_TYPE)
54
55 -def discover(uri):
56 """Discover services for a given URI. 57 58 @param uri: The identity URI as a well-formed http or https 59 URI. The well-formedness and the protocol are not checked, but 60 the results of this function are undefined if those properties 61 do not hold. 62 63 @return: DiscoveryResult object 64 65 @raises Exception: Any exception that can be raised by fetching a URL with 66 the given fetcher. 67 """ 68 result = DiscoveryResult(uri) 69 resp = fetchers.fetch(uri, headers={'Accept': YADIS_ACCEPT_HEADER}) 70 if resp.status != 200: 71 raise DiscoveryFailure( 72 'HTTP Response status from identity URL host is not 200. ' 73 'Got status %r' % (resp.status,), resp) 74 75 # Note the URL after following redirects 76 result.normalized_uri = resp.final_url 77 78 # Attempt to find out where to go to discover the document 79 # or if we already have it 80 result.content_type = resp.headers.get('content-type') 81 82 # According to the spec, the content-type header must be an exact 83 # match, or else we have to look for an indirection. 84 if (result.content_type and 85 result.content_type.split(';', 1)[0].lower() == YADIS_CONTENT_TYPE): 86 result.xrds_uri = result.normalized_uri 87 else: 88 # Try the header 89 yadis_loc = resp.headers.get(YADIS_HEADER_NAME.lower()) 90 91 if not yadis_loc: 92 # Parse as HTML if the header is missing. 93 # 94 # XXX: do we want to do something with content-type, like 95 # have a whitelist or a blacklist (for detecting that it's 96 # HTML)? 97 try: 98 yadis_loc = findHTMLMeta(StringIO(resp.body)) 99 except MetaNotFound: 100 pass 101 102 # At this point, we have not found a YADIS Location URL. We 103 # will return the content that we scanned so that the caller 104 # can try to treat it as an XRDS if it wishes. 105 if yadis_loc: 106 result.xrds_uri = yadis_loc 107 resp = fetchers.fetch(yadis_loc) 108 if resp.status != 200: 109 exc = DiscoveryFailure( 110 'HTTP Response status from Yadis host is not 200. ' 111 'Got status %r' % (resp.status,), resp) 112 exc.identity_url = result.normalized_uri 113 raise exc 114 result.content_type = resp.headers.get('content-type') 115 116 result.response_text = resp.body 117 return result
118