class TestClient(object): def __init__(self): self.cookies = SimpleCookie() def get_request(self, path, method="GET", body=None, **extra): env = StubWSGIRequest(path) env['REQUEST_METHOD'] = method env['wsgi.input'] = StringIO(body) env['HTTP_COOKIE'] = self.cookies.output(header='', sep='; ') env.update(extra) return Request.from_wsgi(env) def perform_request(self, request, user): request.website = test_website if user is not None: user = User.from_username(user) # Note that Cookie needs a bytestring. request.headers.cookie[str('session')] = user.session_token response = test_website.handle_safely(request) if response.headers.cookie: self.cookies.update(response.headers.cookie) return response def post(self, path, data, user=None, content_type=MULTIPART_CONTENT, **extra): """Perform a dummy POST request against the test website. :param path: The url to perform the virutal-POST to. :param data: A dictionary or list of tuples to be encoded before being POSTed. :param user: The user id performing the POST. Any additional parameters will be sent as headers. NOTE that in Aspen (request.py make_franken_headers) only headers beginning with ``HTTP`` are included in the request - and those are changed to no longer include ``HTTP``. There are currently 2 exceptions to this: ``'CONTENT_TYPE'``, ``'CONTENT_LENGTH'`` which are explicitly checked for. """ post_data = data if content_type is MULTIPART_CONTENT: post_data = encode_multipart(BOUNDARY, data) request = self.get_request(path, "POST", post_data, CONTENT_TYPE=str(content_type), **extra) return self.perform_request(request, user) def get(self, path, user=None, **extra): request = self.get_request(path, "GET") return self.perform_request(request, user)
class Browser(object): def __init__(self, Visit=None): if Visit is not None: Visit.createTable(ifNotExists=True) self.visit = True else: self.visit = False self.cookie = SimpleCookie() def goto(self, url, **kargs): params = kargs.get('params') if params: s = '&'.join([ '='.join( [urllib.quote_plus(str(k)), urllib.quote_plus(str(v))]) for k, v in params.items() ]) url += '?' + s del kargs['params'] if self.cookie: headers = kargs.get('headers', {}) headers['Cookie'] = self.cookie.output() kargs['headers'] = headers createRequest(url, **kargs) if cherrypy.response.simple_cookie: self.cookie.update(cherrypy.response.simple_cookie) # Try to handle redirects i = 5 # To prevent infinitive redirects while cherrypy.response.status.startswith('302') and i > 0: response = cherrypy.response.body[0] url = response.split('>')[1].split('<')[0] if self.cookie: headers = kargs.get('headers', {}) headers['Cookie'] = self.cookie.output() kargs['headers'] = headers createRequest(url, **kargs) if cherrypy.response.simple_cookie: self.cookie.update(cherrypy.response.simple_cookie) i -= 1 self.url = url self.response = cherrypy.response try: self.body = cherrypy.response.body[0] except: self.body = None if not self.response.status.startswith('200'): raise ValueError(self.body) def response_contains(self, text): return text in self.body
def __init__(self, response): ## self.code = response.code ## self.content = response.content cookies = SimpleCookie() try: cookies.update(response.cookies) cookies.update(response.session.sidcookie) cookies = str(cookies).split()[1] response.heads.set_cookie = cookies except AttributeError: pass ## self.heads = Heads(**kwargs) ## self.heads.content_type = response.content.ctype ## self.heads.content_length = response.content._clen response.heads.content_type = response.content.ctype response.heads.content_length = response.content._clen self.response = response
class HTTPClient(object): def __init__(self, http_client=None): self.http_client = http_client if http_client else \ tornado.httpclient.HTTPClient() self.cookies = SimpleCookie() def get(self, url, data=None, headers={}): if data is not None: if isinstance(data, dict): data = urlencode(data) if '?' in url: url += '&%s' % data else: url += '?%s' % data return self.__fetch(url, 'GET', headers=headers) def post(self, url, data, headers={}): if data is not None: if isinstance(data, dict): data = urlencode(data) return self.__fetch(url, 'POST', data, headers) def __fetch(self, url, method, data=None, headers={}): #Send the cookies that have been previously set if len(self.cookies) > 0: headers["Cookie"] = self.cookies.output(attrs=[], header="",sep=";").strip() response = self.http_client.fetch(url, method=method, body=data, headers=headers) try: #Record any new cookies set self.cookies.update(SimpleCookie(response.headers["Set-Cookie"])) except KeyError: pass return response
class Client(object): """This is the Aspen test client. It is probably useful to you. """ def __init__(self, www_root=None, project_root=None): self.www_root = www_root self.project_root = project_root self.cookie = SimpleCookie() self._website = None def hydrate_website(self, argv=None): if (self._website is None) or (argv is not None): argv = [ '--www_root', self.www_root , '--project_root', self.project_root ] + ([] if argv is None else argv) self._website = Website(argv) return self._website website = property(hydrate_website) def load_resource(self, path): """Given an URL path, return a Resource instance. """ return self.hit('GET', path=path, return_after='get_resource_for_request', want='resource') # HTTP Methods # ============ def GET(self, *a, **kw): return self.hit('GET', *a, **kw) def POST(self, *a, **kw): return self.hit('POST', *a, **kw) def GxT(self, *a, **kw): return self.hxt('GET', *a, **kw) def PxST(self, *a, **kw): return self.hxt('POST', *a, **kw) def hxt(self, *a, **kw): try: self.hit(*a, **kw) except Response as response: return response else: raise DidntRaiseResponse def hit(self, method, path='/', data=None, body=b'', content_type=MULTIPART_CONTENT, raise_immediately=True, return_after=None, want='response', **headers): data = {} if data is None else data if content_type is MULTIPART_CONTENT: body = encode_multipart(BOUNDARY, data) environ = self.build_wsgi_environ(method, path, body, str(content_type), **headers) state = self.website.respond( environ , raise_immediately=raise_immediately , return_after=return_after ) response = state.get('response') if response is not None: if response.headers.cookie: self.cookie.update(response.headers.cookie) attr_path = want.split('.') base = attr_path[0] attr_path = attr_path[1:] out = state[base] for name in attr_path: out = getattr(out, name) return out def build_wsgi_environ(self, method, path, body, content_type, **kw): # NOTE that in Aspen (request.py make_franken_headers) only headers # beginning with ``HTTP`` are included in the request - and those are # changed to no longer include ``HTTP``. There are currently 2 # exceptions to this: ``'CONTENT_TYPE'``, ``'CONTENT_LENGTH'`` which # are explicitly checked for. typecheck(path, (str, unicode), method, unicode, content_type, str, body, str) environ = {} environ[b'CONTENT_TYPE'] = content_type environ[b'HTTP_COOKIE'] = self.cookie.output(header=b'', sep=b'; ') environ[b'HTTP_HOST'] = b'localhost' environ[b'PATH_INFO'] = path if type(path) is str else path.decode('UTF-8') environ[b'REMOTE_ADDR'] = b'0.0.0.0' environ[b'REQUEST_METHOD'] = method.decode('ASCII') environ[b'SERVER_PROTOCOL'] = b'HTTP/1.1' environ[b'wsgi.input'] = StringIO(body) environ[b'HTTP_CONTENT_LENGTH'] = bytes(len(body)) environ.update(kw) return environ
class TestClient(object): def __init__(self): self.cookies = SimpleCookie() def get_request(self, path, method="GET", body=None, **extra): env = StubWSGIRequest(path) env['REQUEST_METHOD'] = method env['wsgi.input'] = StringIO(body) env['HTTP_COOKIE'] = self.cookies.output(header='', sep='; ') env.update(extra) return Request.from_wsgi(env) def perform_request(self, request, user): request.website = test_website if user is not None: user = User.from_id(user) # Note that Cookie needs a bytestring. request.headers.cookie[str('session')] = user.session_token response = test_website.handle_safely(request) if response.headers.cookie: self.cookies.update(response.headers.cookie) return response def post(self, path, data, user=None, content_type=MULTIPART_CONTENT, **extra): """Perform a dummy POST request against the test website. :param path: The url to perform the virutal-POST to. :param data: A dictionary or list of tuples to be encoded before being POSTed. :param user: The user id performing the POST. Any additional parameters will be sent as headers. NOTE that in Aspen (request.py make_franken_headers) only headers beginning with ``HTTP`` are included in the request - and those are changed to no longer include ``HTTP``. There are currently 2 exceptions to this: ``'CONTENT_TYPE'``, ``'CONTENT_LENGTH'`` which are explicitly checked for. """ post_data = data if content_type is MULTIPART_CONTENT: post_data = encode_multipart(BOUNDARY, data) request = self.get_request(path, "POST", post_data, CONTENT_TYPE=str(content_type), **extra) return self.perform_request(request, user) def get(self, path, user=None, **extra): request = self.get_request(path, "GET") return self.perform_request(request, user)
class TestClient(object): """ The Aspen test client. Used in tests to emulate ``GET`` and ``POST`` requests by sending them into a ``Website`` instance's ``handle_safely`` method. Aspen does not define any User data structures or modules. If you want to do anything with users/sessions etc in your tests it is expected that you will subclass this TestClient and add a ``add_cookie_info`` method. For example, in gittip a suitable subclass might be:: class GittipTestClient(TestClient): def add_cookie_info(self, request, cookie_info): if cookie_info: user = cookie_info.get('user') if user is not None: user = User.from_id(user) # Note that Cookie needs a bytestring. request.headers.cookie['session'] = user.session_token Example usage in a test:: def test_api_handles_posts(): client = TestClient(website) # We need to get ourselves a token! response = client.get('/') csrf_token = response.request.context['csrf_token'] # Then, add a $1.50 and $3.00 tip response = client.post("/test_tippee1/tip.json", {'amount': "1.00", 'csrf_token': csrf_token}, cookie_info={'user': '******'}) # Confirm we get back the right amounts in the JSON body. first_data = json.loads(response.body) assert_equal(first_data['amount'], "1.00") """ def __init__(self, website): self.cookies = SimpleCookie() self.test_website = website def get_request(self, path, method="GET", body=None, **extra): env = StubWSGIRequest(path) env["REQUEST_METHOD"] = method env["wsgi.input"] = StringIO(body) env["HTTP_COOKIE"] = self.cookies.output(header="", sep="; ") env.update(extra) return Request.from_wsgi(env) def perform_request(self, request, cookie_info): request.website = self.test_website self.add_cookie_info(request, **(cookie_info or {})) response = self.test_website.handle_safely(request) if response.headers.cookie: self.cookies.update(response.headers.cookie) return response def add_cookie_info(self, request, **cookie_info): """Place holder function that can be replaced in a subclass. For example in gittip.com, it might be of interest to load session information into the cookie like this:: if cookie_info: user = cookie_info.get('user') if user is not None: user = User.from_id(user) # Note that Cookie needs a bytestring. request.headers.cookie['session'] = user.session_token """ pass def post(self, path, data, content_type=MULTIPART_CONTENT, cookie_info=None, **extra): """Perform a dummy POST request against the test website. :param path: The url to perform the virutal-POST to. :param data: A dictionary or list of tuples to be encoded before being POSTed. Any additional parameters will be sent as headers. NOTE that in Aspen (request.py make_franken_headers) only headers beginning with ``HTTP`` are included in the request - and those are changed to no longer include ``HTTP``. There are currently 2 exceptions to this: ``'CONTENT_TYPE'``, ``'CONTENT_LENGTH'`` which are explicitly checked for. """ post_data = data if content_type is MULTIPART_CONTENT: post_data = encode_multipart(BOUNDARY, data) request = self.get_request(path, "POST", post_data, CONTENT_TYPE=str(content_type), **extra) return self.perform_request(request, cookie_info) def get(self, path, cookie_info=None, **extra): request = self.get_request(path, "GET") return self.perform_request(request, cookie_info)
def run(self, environ, start_response): def tuplize(x): l = x.split("=")[:2] if len(l) == 1: l.append(True) return tuple(l) self.environ = environ self.start_response = start_response try: path_info = urllib.unquote_plus(environ["PATH_INFO"]) except KeyError: raise WSGIKeyNotPresentError("PATH_INFO") path = [p for p in path_info.split("/") if p] or [""] if "QUERY_STRING" in environ: query_string = urllib.unquote_plus(environ["QUERY_STRING"]) params = dict([tuplize(x) for x in query_string.split("&") if x]) else: params = {} # a dirty little trick to deny FieldStorage to use QUERY_STRING self.environ["QUERY_STRING"] = "" xenviron = Struct() xenviron.args = path xenviron.kwargs = params try: xenviron.fields = FieldStorage(environ=self.environ, fp=self.environ["wsgi.input"]) except KeyError: raise WSGIKeyNotPresentError("wsgi.input") xenviron.cookies = SimpleCookie(environ.get("HTTP_COOKIE", "")) try: xenviron.cookies, xenviron.session = self.sessionman.get_session(xenviron.cookies) except SessionError: xenviron.session = self.sessionman.new_session() if not path[0]: if not self._index: return self._default_index() app = self._index(xenviron) else: try: name = path[0] app = self._applist[name](xenviron) except KeyError: xenviron.error_code = 404 xenviron.error_message = _(u"Method not found") if self._error: app = self._error(xenviron) else: return self._default_error(xenviron.error_code, xenviron.error_message) app.body.refresh(xenviron) app.body.run() app_xenviron, response = app.body.get() # further process the app_xenviron self.sessionman.update(app_xenviron.session) # return preparations cookies = SimpleCookie() cookies.update(app_xenviron.cookies) cookies.update(app_xenviron.session.sidcookie) cookies = str(cookies).split()[1] response.heads.set_cookie = cookies return self._prepare_response(response)
class TestClient(object): """ The Aspen test client. Used in tests to emulate ``GET`` and ``POST`` requests by sending them into a ``Website`` instance's ``handle_safely`` method. Aspen does not define any User data structures or modules. If you want to do anything with users/sessions etc in your tests it is expected that you will subclass this TestClient and add a ``add_cookie_info`` method. For example, in gittip a suitable subclass might be:: class GittipTestClient(TestClient): def add_cookie_info(self, request, cookie_info): if cookie_info: user = cookie_info.get('user') if user is not None: user = User.from_id(user) # Note that Cookie needs a bytestring. request.headers.cookie['session'] = user.session_token Example usage in a test:: def test_api_handles_posts(): client = TestClient(website) # We need to get ourselves a token! response = client.get('/') csrf_token = response.request.context['csrf_token'] # Then, add a $1.50 and $3.00 tip response = client.post("/test_tippee1/tip.json", {'amount': "1.00", 'csrf_token': csrf_token}, cookie_info={'user': '******'}) # Confirm we get back the right amounts in the JSON body. first_data = json.loads(response.body) assert_equal(first_data['amount'], "1.00") """ def __init__(self, website): self.cookies = SimpleCookie() self.test_website = website def get_request(self, path, method="GET", body=None, **extra): env = StubWSGIRequest(path) env['REQUEST_METHOD'] = method env['wsgi.input'] = StringIO(body) env['HTTP_COOKIE'] = self.cookies.output(header='', sep='; ') env.update(extra) return Request.from_wsgi(env) def perform_request(self, request, cookie_info): request.website = self.test_website self.add_cookie_info(request, **(cookie_info or {})) response = self.test_website.handle_safely(request) if response.headers.cookie: self.cookies.update(response.headers.cookie) return response def add_cookie_info(self, request, **cookie_info): """Place holder function that can be replaced in a subclass. For example in gittip.com, it might be of interest to load session information into the cookie like this:: if cookie_info: user = cookie_info.get('user') if user is not None: user = User.from_id(user) # Note that Cookie needs a bytestring. request.headers.cookie['session'] = user.session_token """ pass def post(self, path, data, content_type=MULTIPART_CONTENT, cookie_info=None, **extra): """Perform a dummy POST request against the test website. :param path: The url to perform the virutal-POST to. :param data: A dictionary or list of tuples to be encoded before being POSTed. Any additional parameters will be sent as headers. NOTE that in Aspen (request.py make_franken_headers) only headers beginning with ``HTTP`` are included in the request - and those are changed to no longer include ``HTTP``. There are currently 2 exceptions to this: ``'CONTENT_TYPE'``, ``'CONTENT_LENGTH'`` which are explicitly checked for. """ post_data = data if content_type is MULTIPART_CONTENT: post_data = encode_multipart(BOUNDARY, data) request = self.get_request(path, "POST", post_data, CONTENT_TYPE=str(content_type), **extra) return self.perform_request(request, cookie_info) def get(self, path, cookie_info=None, **extra): request = self.get_request(path, "GET") return self.perform_request(request, cookie_info)