2010-08-13 3 views
5

У нас есть два приложения, которые работают в Google App Engine. App1 делает запросы к app2 аутентифицированным пользователем. Аутентификация работает, запрашивая токен аутентификации из Google ClientLogin, который обменивается на файл cookie. Затем cookie используется для последующих запросов (как описано here). App1 работает следующий код:Ошибка при загрузке Ошибка приложения 2 в Google App Engine

class AuthConnection: 

    def __init__(self):    
     self.cookie_jar = cookielib.CookieJar()  
     self.opener = urllib2.OpenerDirector() 
     self.opener.add_handler(urllib2.ProxyHandler()) 
     self.opener.add_handler(urllib2.UnknownHandler()) 
     self.opener.add_handler(urllib2.HTTPHandler()) 
     self.opener.add_handler(urllib2.HTTPRedirectHandler()) 
     self.opener.add_handler(urllib2.HTTPDefaultErrorHandler()) 
     self.opener.add_handler(urllib2.HTTPSHandler()) 
     self.opener.add_handler(urllib2.HTTPErrorProcessor()) 
     self.opener.add_handler(urllib2.HTTPCookieProcessor(self.cookie_jar)) 
     self.headers = {'User-Agent': 'Mozilla/5.0 (Windows; U; ' +\ 
             'Windows NT 6.1; en-US; rv:1.9.1.2) ' +\ 
             'Gecko/20090729 Firefox/3.5.2 ' +\ 
             '(.NET CLR 3.5.30729)' 
         } 

    def fetch(self, url, method, payload=None): 
     self.__updateJar(url) 
     request = urllib2.Request(url) 
     request.get_method = lambda: method 
     for key, value in self.headers.iteritems(): 
      request.add_header(key, value) 
     response = self.opener.open(request) 
     return response.read() 

    def __updateJar(self, url): 

     cache = memcache.Client() 
     cookie = cache.get('auth_cookie') 

     if cookie: 
      self.cookie_jar.set_cookie(cookie) 
     else: 
      cookie = self.__retrieveCookie(url=url) 
      cache.set('auth_cookie', cookie, 5000) 


    def __getCookie(self, url): 
     auth_url = 'https://www.google.com/accounts/ClientLogin' 
     auth_data = urllib.urlencode({'Email': USER_NAME, 
             'Passwd': PASSPHRASE, 
             'service': 'ah', 
             'source': 'app1', 
             'accountType': 'HOSTED_OR_GOOGLE' }) 
     auth_request = urllib2.Request(auth_url, data=auth_data) 
     auth_response_body = self.opener.open(auth_request).read() 
     auth_response_dict = dict(x.split('=') 
       for x in auth_response_body.split('\n') if x) 
     cookie_args = {} 
     cookie_args['continue'] = url 
     cookie_args['auth'] = auth_response_dict['Auth'] 
     cookie_url = 'https://%s/_ah/login?%s' %\ 
       ('app2.appspot.com', (urllib.urlencode(cookie_args))) 
     cookie_request = urllib2.Request(cookie_url) 

     for key, value in self.headers.iteritems(): 
      cookie_request.add_header(key, value) 

     try: 
      self.opener.open(cookie_request) 
     except: 
      pass 

     for cookie in self.cookie_jar:       
      if cookie.domain == 'app2domain': 
       return cookie 

Для 10-30% от запросов в DownloadError поднимается:

Error fetching https://app2/Resource 
Traceback (most recent call last): 
    File "/base/data/home/apps/app1/5.344034030246386521/source/main/connection/authenticate.py", line 112, in fetch 
    response = self.opener.open(request) 
    File "/base/python_runtime/python_dist/lib/python2.5/urllib2.py", line 381, in open 
    response = self._open(req, data) 
    File "/base/python_runtime/python_dist/lib/python2.5/urllib2.py", line 399, in _open 
    '_open', req) 
    File "/base/python_runtime/python_dist/lib/python2.5/urllib2.py", line 360, in _call_chain 
    result = func(*args) 
    File "/base/python_runtime/python_dist/lib/python2.5/urllib2.py", line 1115, in https_open 
    return self.do_open(httplib.HTTPSConnection, req) 
    File "/base/python_runtime/python_dist/lib/python2.5/urllib2.py", line 1080, in do_open 
    r = h.getresponse() 
    File "/base/python_runtime/python_dist/lib/python2.5/httplib.py", line 197, in getresponse 
    self._allow_truncated, self._follow_redirects) 
    File "/base/data/home/apps/app1/5.344034030246386521/source/main/connection/monkeypatch_urlfetch_deadline.py", line 18, in new_fetch 
    follow_redirects, deadline, *args, **kwargs) 
    File "/base/python_runtime/python_lib/versions/1/google/appengine/api/urlfetch.py", line 241, in fetch 
    return rpc.get_result() 
    File "/base/python_runtime/python_lib/versions/1/google/appengine/api/apiproxy_stub_map.py", line 501, in get_result 
    return self.__get_result_hook(self) 
    File "/base/python_runtime/python_lib/versions/1/google/appengine/api/urlfetch.py", line 325, in _get_fetch_result 
    raise DownloadError(str(err)) 
DownloadError: ApplicationError: 2 

Запросе журналы для app2 ("сервер"), кажется, хорошо, как и ожидалось (в соответствии с документами DownloadError только повышается, если не было действительного ответа HTTP).

Почему возникает исключение?

ответ

3

увидеть это: http://bitbucket.org/guilin/gae-rproxy/src/tip/gae_rproxy/niceurllib.py

из URLLIB и urllib2 по умолчанию для обработки HTTP 302 код, и автоматически перенаправлять на то, что сказал это сервер. Но при перенаправлении он не содержит куки-файлы, которые сервер сказал ему.

, например:

  1. запрос urllib2 // сервер/вход
  2. ответа сервера 302, // сервер/профиль, Set-Cookie: сеанс ID: хххй
  3. запрос urllib2 // сервер/профиль
  4. ответ сервера не ошибка входа или 500 ошибка причина нет session-id найден.
  5. ошибка urllib2 бросок

так, нет никаких шансов для вас, чтобы установить печенье.

self.opener.add_handler (urllib2.HTTPRedirectHandler())

Я думаю, вы должны удалить эту строку и добавить свой собственный HTTPRedirectHandler какую ошибку neighter броска, ни автоматического перенаправления, просто возвращает код HTTP и заголовки, так что вы есть возможность установить cookie.

Смежные вопросы