darwin (owner)

Revisions

gist: 44680 Download_button fork
public
Public Clone URL: git://gist.github.com/44680.git
Embed All Files: show embed
Python #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
from openid import fetchers
from google.appengine.api import urlfetch
import logging
 
# other firepython enabled server should be created like this:
 
# firepython = None
#
# def main():
# app = Application()
# if FIREPYTHON_ENABLED:
# logging.getLogger().name = "other server"
# firepython = app = FirePythonWSGI(app, password=FIREPYTHON_PASSWORD, check_agent=False)
# run_wsgi_app(app)
 
# check_agent=False is needed because of GAE restrictions on headers
# http://code.google.com/appengine/docs/urlfetch/fetchfunction.html
    
class AppEngineFetcher(fetchers.HTTPFetcher):
 
    def __init__(self, firepython=None, firepython_password=None):
        fetchers.HTTPFetcher.__init__(self)
        self.firepython = firepython # current firepython middleware instance
        self.firepython_password = firepython_password # firepython password for other firepython-enabled server we are doing fetch against
 
    """An HTTPFetcher subclass that uses Google App Engine's urlfetch module.
"""
    def fetch(self, url, body=None, headers=None):
        if not fetchers._allowedURL(url):
            raise ValueError('Bad URL scheme: %r' % (url,))
        
        if not headers:
            headers = {}
        
        if body:
            method = urlfetch.POST
            headers['Content-type'] = 'application/x-www-form-urlencoded'
        else:
            method = urlfetch.GET
        
        if self.firepython:
            import firepython.utils
            # note: this USER_AGENT doesn't work for GAE according to note here: http://code.google.com/appengine/docs/urlfetch/fetchfunction.html
            fpua = firepython.utils.get_user_agent()
            ua = headers.get('USER_AGENT')
            if ua is None: ua = ''
            headers['USER_AGENT'] = ua + " " + fpua
            if self.firepython_password is not None:
                ah = firepython.utils.get_auth_header(self.firepython_password)
                headers[ah[0]] = ah[1]
        
        count = 0
        resp = urlfetch.fetch(url, body, method, headers=headers)
        
        # follow redirects for a while
        while resp.status_code in [301,302]:
            count += 1
            if count >= 3:
                raise Exception('too many redirects')
            
            if resp.headers.has_key('location'):
                url = resp.headers['location']
            elif resp.headers.has_key('Location'):
                url = resp.headers['Location']
            else:
                raise Exception('Could not find location in headers: %r' % (resp.headers,))
            
            resp = urlfetch.fetch(url, body, method, headers=headers)
 
        if self.firepython:
            self.firepython.republish(resp.headers)
        
        # normalize headers
        for key, val in resp.headers.items():
            resp.headers[key.lower()] = val
        
        return fetchers.HTTPResponse(url, resp.status_code, resp.headers, resp.content)