getting file size for all dict files to be downloaded. coming to be 400mb or so.
[worddb.git] / libs / openid / yadis / discover.py
blobed2adfdec6cf8578a47877dc6227153960c9ce30
1 # -*- test-case-name: openid.test.test_yadis_discover -*-
2 __all__ = ['discover', 'DiscoveryResult', 'DiscoveryFailure']
4 from cStringIO import StringIO
6 from openid import fetchers
8 from openid.yadis.constants import \
9 YADIS_HEADER_NAME, YADIS_CONTENT_TYPE, YADIS_ACCEPT_HEADER
10 from openid.yadis.parsehtml import MetaNotFound, findHTMLMeta
12 class DiscoveryFailure(Exception):
13 """Raised when a YADIS protocol error occurs in the discovery process"""
14 identity_url = None
16 def __init__(self, message, http_response):
17 Exception.__init__(self, message)
18 self.http_response = http_response
20 class DiscoveryResult(object):
21 """Contains the result of performing Yadis discovery on a URI"""
23 # The URI that was passed to the fetcher
24 request_uri = None
26 # The result of following redirects from the request_uri
27 normalized_uri = None
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
33 # The content-type returned with the response_text
34 content_type = None
36 # The document returned from the xrds_uri
37 response_text = None
39 def __init__(self, request_uri):
40 """Initialize the state of the object
42 sets all attributes to None except the request_uri
43 """
44 self.request_uri = request_uri
46 def usedYadisLocation(self):
47 """Was the Yadis protocol's indirection used?"""
48 return self.normalized_uri != self.xrds_uri
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)
55 def discover(uri):
56 """Discover services for a given URI.
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.
63 @return: DiscoveryResult object
65 @raises Exception: Any exception that can be raised by fetching a URL with
66 the given fetcher.
67 @raises DiscoveryFailure: When the HTTP response does not have a 200 code.
68 """
69 result = DiscoveryResult(uri)
70 resp = fetchers.fetch(uri, headers={'Accept': YADIS_ACCEPT_HEADER})
71 if resp.status not in (200, 206):
72 raise DiscoveryFailure(
73 'HTTP Response status from identity URL host is not 200. '
74 'Got status %r' % (resp.status,), resp)
76 # Note the URL after following redirects
77 result.normalized_uri = resp.final_url
79 # Attempt to find out where to go to discover the document
80 # or if we already have it
81 result.content_type = resp.headers.get('content-type')
83 result.xrds_uri = whereIsYadis(resp)
85 if result.xrds_uri and result.usedYadisLocation():
86 resp = fetchers.fetch(result.xrds_uri)
87 if resp.status not in (200, 206):
88 exc = DiscoveryFailure(
89 'HTTP Response status from Yadis host is not 200. '
90 'Got status %r' % (resp.status,), resp)
91 exc.identity_url = result.normalized_uri
92 raise exc
93 result.content_type = resp.headers.get('content-type')
95 result.response_text = resp.body
96 return result
100 def whereIsYadis(resp):
101 """Given a HTTPResponse, return the location of the Yadis document.
103 May be the URL just retrieved, another URL, or None, if I can't
104 find any.
106 [non-blocking]
108 @returns: str or None
110 # Attempt to find out where to go to discover the document
111 # or if we already have it
112 content_type = resp.headers.get('content-type')
114 # According to the spec, the content-type header must be an exact
115 # match, or else we have to look for an indirection.
116 if (content_type and
117 content_type.split(';', 1)[0].lower() == YADIS_CONTENT_TYPE):
118 return resp.final_url
119 else:
120 # Try the header
121 yadis_loc = resp.headers.get(YADIS_HEADER_NAME.lower())
123 if not yadis_loc:
124 # Parse as HTML if the header is missing.
126 # XXX: do we want to do something with content-type, like
127 # have a whitelist or a blacklist (for detecting that it's
128 # HTML)?
129 try:
130 yadis_loc = findHTMLMeta(StringIO(resp.body))
131 except MetaNotFound:
132 pass
134 return yadis_loc