def redirect(location, code=302): """Return a response object (a WSGI application) that, if called, redirects the client to the target location. Supported codes are 301, 302, 303, 305, and 307. 300 is not supported because it's not a real redirect and 304 because it's the answer for a request with a request with defined If-Modified-Since headers. .. versionadded:: 0.6 The location can now be a unicode string that is encoded using the :func:`iri_to_uri` function. :param location: the location the response should redirect to. :param code: the redirect status code. defaults to 302. """ display_location = escape(location) if isinstance(location, str): location = iri_to_uri(location) response = Response( '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">\n' '<title>Redirecting...</title>\n' '<h1>Redirecting...</h1>\n' '<p>You should be redirected automatically to target URL: ' '<a href="%s">%s</a>. If not click the link.' % (escape(location), display_location), code, mimetype="text/html") response.headers["Location"] = location return response
def project_json(app, request, project_name): # fail early if callback is invalid callback = request.args.get("callback") if callback: if not is_valid_json_callback_name(callback): raise BadRequest("invalid JSONP callback name") # Get the real project name for this project project = app.db.packaging.get_project(project_name) if project is None: raise NotFound("{} does not exist".format(project_name)) # we're looking for the latest version versions = app.db.packaging.get_project_versions(project) if not versions: raise NotFound("{} has no releases".format(project)) version = versions[0] rpc = xmlrpc.Interface(app, request) d = dict(info=rpc.release_data(project, version), urls=rpc.release_urls(project, version)) for url in d["urls"]: url["upload_time"] = url["upload_time"].strftime("%Y-%m-%dT%H:%M:%S") data = json.dumps(d, sort_keys=True) # write the JSONP extra crap if necessary if callback: data = "/**/ %s(%s);" % (callback, data) response = Response(data, mimetype="application/json") response.headers["Content-Disposition"] = "inline" return response
def project_json(app, request, project_name, version=None): # fail early if callback is invalid callback = request.args.get('callback') if callback: if not is_valid_json_callback_name(callback): raise BadRequest('invalid JSONP callback name') # Get the real project name for this project project = app.db.packaging.get_project(project_name) if project is None: raise NotFound("{} does not exist".format(project_name)) # we're looking for the latest version versions = app.db.packaging.get_project_versions(project['name']) if version is None: if not versions: raise NotFound("{} has no releases".format(project_name)) version = versions[0] elif version not in versions: raise NotFound("{} has no release {}".format(project_name, version)) rpc = xmlrpc.Interface(app, request) d = dict( info=rpc.release_data(project['name'], version), urls=rpc.release_urls(project['name'], version), releases=rpc.all_release_urls(project['name']), ) time_format = '%Y-%m-%dT%H:%M:%S' for url in d['urls']: url['upload_time'] = url['upload_time'].strftime(time_format) for release, urls in d['releases'].items(): for url in urls: url['upload_time'] = url['upload_time'].strftime(time_format) data = json.dumps(d, sort_keys=True) # write the JSONP extra crap if necessary if callback: data = '/**/ %s(%s);' % (callback, data) serial = app.db.packaging.get_last_serial() response = Response(data, mimetype="application/json") response.headers['Content-Disposition'] = 'inline' response.headers.add("X-PyPI-Last-Serial", serial) return response
def test_response_surrogate_control(): resp = Response() assert "Surrogate-Control" not in resp.headers resp.surrogate_control.public = True resp.surrogate_control.max_age = 120 assert set(resp.headers["Surrogate-Control"].split(", ")) == { "max-age=120", "public", }
def render_response(app, request, template, **variables): template = app.templates.get_template(template) context = { "config": app.config, "gravatar_url": helpers.gravatar_url, "static_url": functools.partial(helpers.static_url, app), "url_for": functools.partial(helpers.url_for, request), } context.update(variables) return Response(template.render(**context), mimetype="text/html")
def test_csrf_already_ensured(self): def fn(self, view, app, request, *args, **kwargs): return view(app, request, *args, **kwargs) view = lambda app, request: Response() view._csrf = True app = pretend.stub() request = pretend.stub(_session={"user.csrf": "1234"}, method="GET") handle_csrf(fn)(pretend.stub(), view, app, request) assert request._session == {"user.csrf": "1234"}
def test_existing_session_no_save(self): def fn(self, view, app, request, *args, **kwargs): return view(app, request, *args, **kwargs) view = lambda app, request: Response() app = pretend.stub(session_store=FakeSessionStore()) request = pretend.stub(cookies={"session_id": "abcd"}, is_secure=False) response = handle_session(fn)(pretend.stub(), view, app, request) assert app.session_store.saved == [] assert response.headers.getlist("Set-Cookie") == []
def test_csrf_disallows_unsafe(self, method): def fn(self, view, app, request, *args, **kwargs): return view(app, request, *args, **kwargs) view = lambda app, request: Response() app = pretend.stub() request = pretend.stub(_session={}, method=method) with pytest.raises(SecurityError) as excinfo: handle_csrf(fn)(pretend.stub(), view, app, request) assert ( excinfo.value.description == "No CSRF protection applied to view")
def handle_request(app, request): '''Wrap an invocation of the XML-RPC dispatcher. ''' dispatcher = SimpleXMLRPCDispatcher() dispatcher.register_instance(Interface(app, request)) # read in the XML-RPC request data, limiting to a sensible size if int(request.headers['Content-Length']) > 10 * 1024 * 1024: raise BadRequest('request data too large') xml_request = request.get_data(cache=False, as_text=True) # errors here are handled by _marshaled_dispatch response = dispatcher._marshaled_dispatch(xml_request) # legacy; remove non-printable ASCII control codes from the response response = re.sub('([\x00-\x08]|[\x0b-\x0c]|[\x0e-\x1f])+', '', response) return Response(response, mimetype="text/xml")
def test_csrf_checks_csrf_unsafe(self, method): def fn(self, view, app, request, *args, **kwargs): return view(app, request, *args, **kwargs) view = lambda app, request: Response() view._csrf = True app = pretend.stub() request = pretend.stub(_session={}, method=method) _verify_origin = pretend.call_recorder(lambda request: None) _verify_token = pretend.call_recorder(lambda request: None) handle_csrf( fn, _verify_origin=_verify_origin, _verify_token=_verify_token, )(pretend.stub(), view, app, request) assert _verify_token.calls == [pretend.call(request)] assert _verify_token.calls == [pretend.call(request)]
def handler(app, request): '''Wrap an invocation of the XML-RPC dispatcher. ''' # unicode strings will be encoded in utf-8 by xmlrpclib dispatcher = SimpleXMLRPCDispatcher() dispatcher.register_instance(Interface(app, request)) # read in the XML-RPC request data, limiting to a sensible size if int(request.headers['Content-Length']) > 10 * 1024 * 1024: raise BadRequest('request data too large') xml_request = request.get_data(cache=False, as_text=True) # errors here are handled by _marshaled_dispatch response = dispatcher._marshaled_dispatch(xml_request) # legacy; remove non-printable ASCII control codes from the response # RJ: disabled this as it's a giant, unreliable hack that doesn't work and # I can't even remember why it's in here to start with # response = re.sub('([\x00-\x08]|[\x0b-\x0c]|[\x0e-\x1f])+', '', response) return Response(response, mimetype="text/xml; charset=utf-8")
def view(app, request): request._session["wat"] = "ok" return Response()
def package(app, request, path): # Get our filename and filepath from the request path filename = os.path.basename(path) filepath = safe_join( os.path.abspath(app.config.paths.packages), path ) # If we cannot safely join the requested path with our directory # return a 404 if filepath is None: raise NotFound("{} was not found".format(filename)) # Open the file and attempt to wrap in the wsgi.file_wrapper if it's # available, otherwise read it directly. try: fp = open(filepath, "rb") data = wrap_file(request.environ, fp) except IOError: raise NotFound("{} was not found".format(filename)) # Get the project name and normalize it lookup_filename = filename[:-4] if filename.endswith(".asc") else filename project = app.db.packaging.get_project_for_filename(lookup_filename) normalized = normalize(project) # Get the MD5 hash of the file content_md5 = app.db.packaging.get_filename_md5(filename) headers = {} # Add in additional headers if we're using Fastly headers.update({ "Surrogate-Key": " ".join([ "package", "package~{}".format(normalized), ]), }) # Look up the last serial for this file serial = app.db.packaging.get_last_serial(project) if serial is not None: headers["X-PyPI-Last-Serial"] = serial # Pass through the data directly to the response object resp = Response( data, headers=headers, mimetype=get_mimetype(filename), direct_passthrough=True, ) # Setup the Last-Modified header resp.last_modified = os.path.getmtime(filepath) # Setup the Content-Length header resp.content_length = os.path.getsize(filepath) if content_md5: # Setup the Content-MD5 headers resp.content_md5 = content_md5 # Setup Conditional Responses resp.set_etag(content_md5) resp.make_conditional(request) return resp
def package(app, request, path): # Get our filename and filepath from the request path filename = os.path.basename(path) filepath = safe_join(os.path.abspath(app.config.paths.packages), path) # If we cannot safely join the requested path with our directory # return a 404 if filepath is None: raise NotFound("{} was not found".format(filename)) # Open the file and attempt to wrap in the wsgi.file_wrapper if it's # available, otherwise read it directly. try: fp = open(filepath, "rb") data = wrap_file(request.environ, fp) except IOError: raise NotFound("{} was not found".format(filename)) # Get the project name and normalize it lookup_filename = filename[:-4] if filename.endswith(".asc") else filename project = app.models.packaging.get_project_for_filename(lookup_filename) normalized = normalize(project) # Get the MD5 hash of the file content_md5 = app.models.packaging.get_filename_md5(filename) headers = {} # Add in additional headers if we're using Fastly headers.update({ "Surrogate-Key": " ".join([ "package", "package~{}".format(normalized), ]), }) # Look up the last serial for this file serial = app.models.packaging.get_last_serial(project) if serial is not None: headers["X-PyPI-Last-Serial"] = serial # Pass through the data directly to the response object resp = Response( data, headers=headers, mimetype=get_mimetype(filename), direct_passthrough=True, ) # Setup the Last-Modified header resp.last_modified = os.path.getmtime(filepath) # Setup the Content-Length header resp.content_length = os.path.getsize(filepath) if content_md5: # Setup the Content-MD5 headers resp.content_md5 = content_md5 # Setup Conditional Responses resp.set_etag(content_md5) resp.make_conditional(request) return resp
def test_csrf_protect(): view = lambda app, request: Response() view = csrf_protect(view) assert view._csrf assert "cookie" in view(pretend.stub(), pretend.stub()).vary.as_set()
def test_csrf_exempt(): view = lambda app, request: Response() view = csrf_exempt(view) assert not view._csrf
def view(app, request): request._session.delete() return Response()
def view(app, request): request._session.cycle() return Response()
def daytime(app, request): response = time.strftime("%Y%m%dT%H:%M:%S\n", time.gmtime(time.time())) return Response(response, mimetype="text/plain")