1# Copyright (c) 2012 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import base64 6import posixpath 7 8from appengine_wrappers import urlfetch 9from environment import GetAppVersion 10from future import Future 11 12 13def _MakeHeaders(username, password): 14 headers = { 15 'User-Agent': 'Chromium docserver %s' % GetAppVersion(), 16 'Cache-Control': 'max-age=0', 17 } 18 if username is not None and password is not None: 19 headers['Authorization'] = 'Basic %s' % base64.b64encode( 20 '%s:%s' % (username, password)) 21 return headers 22 23 24class AppEngineUrlFetcher(object): 25 """A wrapper around the App Engine urlfetch module that allows for easy 26 async fetches. 27 """ 28 def __init__(self, base_path=None): 29 assert base_path is None or not base_path.endswith('/'), base_path 30 self._base_path = base_path 31 32 def Fetch(self, url, username=None, password=None): 33 """Fetches a file synchronously. 34 """ 35 return urlfetch.fetch(self._FromBasePath(url), 36 headers=_MakeHeaders(username, password)) 37 38 def FetchAsync(self, url, username=None, password=None): 39 """Fetches a file asynchronously, and returns a Future with the result. 40 """ 41 rpc = urlfetch.create_rpc() 42 urlfetch.make_fetch_call(rpc, 43 self._FromBasePath(url), 44 headers=_MakeHeaders(username, password)) 45 return Future(callback=lambda: rpc.get_result()) 46 47 def _FromBasePath(self, url): 48 assert not url.startswith('/'), url 49 if self._base_path is not None: 50 url = posixpath.join(self._base_path, url) if url else self._base_path 51 return url 52