def __call__(self, env, start_response): """WSGI protocol handler""" # PERF: Use literal constructor for dicts ctx = {} # TODO # ctx.update(global_ctx_for_route) req = Request(env) resp = Response() # PERF: Use try...except blocks when the key usually exists try: # TODO: Figure out a way to use codegen to make a state machine, # may have to in order to support URI templates. handler = self.routes[req.path] except KeyError: handler = path_not_found_handler handler(ctx, req, resp) # # Set status and headers # self._set_auto_resp_headers(env, req, resp) start_response(resp.status, resp._wsgi_headers()) # Return an iterable for the body, per the WSGI spec return [resp.body] if resp.body is not None else []
def test_process_request_for_nonstring(mocker): resp_data = b"{\"status\": \"success\"}" env = testing.create_environ() req = Request(env) req.method = 'POST' mocker.patch('app.app_middleware.response_process.json_of') resp = Response() resp.body = resp_data cut = ResponseJSONProcessMiddleware() cut.process_response(req, resp, None, None) app.app_middleware.response_process.json_of.assert_called_once_with(resp_data)
def test_fallback_filename(uri, default, expected, content_type, downloadable, monkeypatch): def mockOpen(path, mode): if default in path: return path raise IOError() monkeypatch.setattr(io, 'open', mockOpen) monkeypatch.setattr('os.path.isfile', lambda file: default in file) sr = StaticRoute('/static', '/var/www/statics', downloadable=downloadable, fallback_filename=default) req_path = '/static/' + uri req = Request(testing.create_environ( host='test.com', path=req_path, app='statics' )) resp = Response() sr(req, resp) assert sr.match(req.path) assert resp.stream == os.path.join('/var/www/statics', expected) assert resp.content_type == content_type if downloadable: assert os.path.basename(expected) in resp.downloadable_as else: assert resp.downloadable_as is None
def test_views(self): load_settings('test_templates/settings.py') from ukumuku.views import View req = mock.Mock() resp = Response() view = View() view.get = mock.Mock() view.on_get(req, resp) view.get.assert_called_with(req) view.post = mock.Mock() view.on_post(req, resp) view.post.assert_called_with(req) view.put = mock.Mock() view.on_put(req, resp) view.put.assert_called_with(req) view.patch = mock.Mock() view.on_patch(req, resp) view.patch.assert_called_with(req) view.head = mock.Mock() view.on_head(req, resp) view.head.assert_called_with(req) view.delete = mock.Mock() view.on_delete(req, resp) view.delete.assert_called_with(req)
def on_post(self, req: Request, res: Response): twilio_message = TwilioMessage.apply(req.params) if twilio_message.is_song_request: song_request = twilio_message.extract_song() spotify_uri = SpotifySongFinder.lucky_find( artist=song_request.artist, track=song_request.title) song_request.uri = spotify_uri AwsServices.add(**song_request.to_kwargs()) self.twilio_reply(to=twilio_message.msg_from) res.status = falcon.HTTP_CREATED else: res.status = falcon.HTTP_BAD_REQUEST res.content_type = MEDIA_XML res.body = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>' \ '<Response></Response>'
def test_bad_path(uri, monkeypatch): monkeypatch.setattr(io, 'open', lambda path, mode: path) sr = StaticRoute('/static', '/var/www/statics') req = Request( testing.create_environ(host='test.com', path=uri, app='statics')) resp = Response() with pytest.raises(falcon.HTTPNotFound): sr(req, resp)
def test_views_not_implemented(self): load_settings('test_templates/settings.py') from ukumuku.views import View import ukumuku req = mock.Mock() resp = Response() view = View() view.on_get(req, resp) self.assertEqual(resp.status, ukumuku.HTTP_501) resp = Response() view.on_post(req, resp) self.assertEqual(resp.status, ukumuku.HTTP_501) resp = Response() view.on_put(req, resp) self.assertEqual(resp.status, ukumuku.HTTP_501) resp = Response() view.on_patch(req, resp) self.assertEqual(resp.status, ukumuku.HTTP_501) resp = Response() view.on_head(req, resp) self.assertEqual(resp.status, ukumuku.HTTP_501) resp = Response() view.on_delete(req, resp) self.assertEqual(resp.status, ukumuku.HTTP_501)
def on_patch(self, req: Request, resp: Response): try: data = json.load(req.stream) except json.JSONDecodeError: raise falcon.HTTPBadRequest("Invalid JSON.") if "profile" not in data: raise falcon.HTTPBadRequest("Expected 'profile' in request.") user = req.context["user"] user["profile"].update(data["profile"]) resp.media = user_to_dict(user)
def __call__(self, env, start_response): """WSGI "app" method Makes instances of API callable by any WSGI server. See also PEP 333. Args: env: A WSGI environment dictionary start_response: A WSGI helper method for setting status and headers on a response. """ req = Request(env) resp = Response() responder, params, na_responder = self._get_responder( req.path, req.method) try: responder(req, resp, **params) except HTTPError as ex: resp.status = ex.status if ex.headers is not None: resp.set_headers(ex.headers) if req.client_accepts('application/json'): resp.body = ex.json() # # Set status and headers # use_body = not helpers.should_ignore_body(resp.status, req.method) if use_body: helpers.set_content_length(resp) body = helpers.get_body(resp) else: # Default: return an empty body body = [] # Set content type if needed use_content_type = (body or req.method == 'HEAD' or resp.status == HTTP_416) if use_content_type: media_type = self._media_type else: media_type = None headers = resp._wsgi_headers(media_type) # Return the response per the WSGI spec start_response(resp.status, headers) return body
def test_good_path(uri_prefix, uri_path, expected_path, mtype, monkeypatch): monkeypatch.setattr(io, 'open', lambda path, mode: path) sr = StaticRoute(uri_prefix, '/var/www/statics') req_path = uri_prefix[:-1] if uri_prefix.endswith('/') else uri_prefix req_path += uri_path req = Request( testing.create_environ(host='test.com', path=req_path, app='statics')) resp = Response() sr(req, resp) assert resp.content_type == mtype assert resp.stream == '/var/www/statics' + expected_path
def on_post(self, req: Request, resp: Response): try: data = json.load(req.stream) except json.JSONDecodeError: raise falcon.HTTPBadRequest("Invalid JSON.") username = data.get("username", "").lower() password = data.get("password") if not username or not password: raise falcon.HTTPBadRequest("Missing username or password.") if username not in users or password != users[username]["password"]: raise falcon.HTTPUnauthorized("Login failed.") token = str(uuid.uuid4()) tokens[token] = username logger.info("Token %s has been issued for %s.", token, username) resp.media = {"token": token}
def test_invalid_process_request(mocker): req_data = "\"service_id\": \"invoice_extraction1\",\"model_name\": \"invoice_extraction\"," \ "\"image\": \"test_data\"".encode("utf-8") env = testing.create_environ(headers={ "Content-Type": "application/json", "Content-Length": str(len(req_data)) }) req = Request(env) req.method = 'POST' mocker.patch.object(req.stream, 'read', return_value=req_data) doc = { "service_id": "invoice_extraction1", "model_name": "invoice_extraction", "image": "test_data" } resp = Response() cut = RequestBodyJSONProcessMiddleware() with raises(falcon.HTTPBadRequest): cut.process_request(req, resp)
def __call__(self, env, start_response): """WSGI "app" method Makes instances of API callable by any WSGI server. See also PEP 333. Args: env: A WSGI environment dictionary start_response: A WSGI helper method for setting status and headers on a response. """ req = Request(env) resp = Response() responder, params, na_responder = self._get_responder( req.path, req.method) try: responder(req, resp, **params) except HTTPError as ex: resp.status = ex.status if ex.headers is not None: resp.set_headers(ex.headers) if req.client_accepts('application/json'): resp.body = ex.json() except TypeError as ex: # NOTE(kgriffs): Get the stack trace up here since we can just # use this convenience function which graps the last raised # exception context. stack_trace = traceback.format_exc() # See if the method doesn't support the given route's params, to # support assigning multiple routes to the same resource. try: argspec = responder.wrapped_argspec except AttributeError: argspec = inspect.getargspec(responder) # First three args should be (self, req, resp) if argspec.args[0] == 'self': offset = 3 else: offset = 2 args_needed = set(argspec.args[offset:]) args_given = set(params.keys()) # Reset the response resp = Response() # Does the responder require more or fewer args than given? if args_needed != args_given: req.log_error('A responder method could not be found with the ' 'correct arguments.') na_responder(req, resp) else: # Error caused by something else req.log_error('A responder method (on_*) raised TypeError. %s' % stack_trace) falcon.responders.internal_server_error(req, resp) # # Set status and headers # use_body = not helpers.should_ignore_body(resp.status, req.method) if use_body: helpers.set_content_length(resp) body = helpers.get_body(resp) else: # Default: return an empty body body = [] # Set content type if needed use_content_type = (body or req.method == 'HEAD' or resp.status == HTTP_416) if use_content_type: media_type = self._media_type else: media_type = None headers = resp._wsgi_headers(media_type) # Return the response per the WSGI spec start_response(resp.status, headers) return body
def __call__(self, env, start_response): """WSGI "app" method Makes instances of API callable by any WSGI server. See also PEP 333. Args: env: A WSGI environment dictionary start_response: A WSGI helper method for setting status and headers on a response. """ req = Request(env) resp = Response() responder, params = self._get_responder( req.path, req.method) try: # NOTE(kgriffs): Using an inner try..except in order to # address the case when err_handler raises HTTPError. # # NOTE(kgriffs): Coverage is giving false negatives, # so disabled on relevant lines. All paths are tested # afaict. try: responder(req, resp, **params) # pragma: no cover except Exception as ex: for err_type, err_handler in self._error_handlers: if isinstance(ex, err_type): err_handler(ex, req, resp, params) break # pragma: no cover else: # PERF(kgriffs): This will propagate HTTPError to # the handler below. It makes handling HTTPError # less efficient, but that is OK since error cases # don't need to be as fast as the happy path, and # indeed, should perhaps be slower to create # backpressure on clients that are issuing bad # requests. raise except HTTPError as ex: resp.status = ex.status if ex.headers is not None: resp.set_headers(ex.headers) if req.client_accepts('application/json'): resp.body = ex.json() # # Set status and headers # use_body = not helpers.should_ignore_body(resp.status, req.method) if use_body: helpers.set_content_length(resp) body = helpers.get_body(resp) else: # Default: return an empty body body = [] # Set content type if needed use_content_type = (body or req.method == 'HEAD' or resp.status == HTTP_416) if use_content_type: media_type = self._media_type else: media_type = None headers = resp._wsgi_headers(media_type) # Return the response per the WSGI spec start_response(resp.status, headers) return body
def on_get(self, req: Request, resp: Response): resp.status = falcon.HTTP_200 resp.body = json.dumps(self.spec.to_dict(), ensure_ascii=False)
def __call__(self, env, start_response): """WSGI "app" method Makes instances of API callable by any WSGI server. See also PEP 333. Args: env: A WSGI environment dictionary start_response: A WSGI helper method for setting status and headers on a response. """ req = Request(env) resp = Response() responder, params, na_responder = self._get_responder( req.path, req.method) try: responder(req, resp, **params) except HTTPError as ex: resp.status = ex.status if ex.headers is not None: resp.set_headers(ex.headers) if req.client_accepts('application/json'): resp.body = ex.json() except TypeError as ex: # NOTE(kgriffs): Get the stack trace up here since we can just # use this convenience function which graps the last raised # exception context. stack_trace = traceback.format_exc() # See if the method doesn't support the given route's params, to # support assigning multiple routes to the same resource. try: argspec = responder.wrapped_argspec except AttributeError: argspec = inspect.getargspec(responder) # First three args should be (self, req, resp) if argspec.args[0] == 'self': offset = 3 else: offset = 2 args_needed = set(argspec.args[offset:]) args_given = set(params.keys()) # Reset the response resp = Response() # Does the responder require more or fewer args than given? if args_needed != args_given: req.log_error('A responder method could not be found with the ' 'correct arguments.') na_responder(req, resp) else: # Error caused by something else req.log_error( 'A responder method (on_*) raised TypeError. %s' % stack_trace) falcon.responders.internal_server_error(req, resp) # # Set status and headers # use_body = not helpers.should_ignore_body(resp.status, req.method) if use_body: helpers.set_content_length(resp) body = helpers.get_body(resp) else: # Default: return an empty body body = [] # Set content type if needed use_content_type = (body or req.method == 'HEAD' or resp.status == HTTP_416) if use_content_type: media_type = self._media_type else: media_type = None headers = resp._wsgi_headers(media_type) # Return the response per the WSGI spec start_response(resp.status, headers) return body
def on_get(self, req: Request, res: Response): res.body = "All good!" res.content_type = MEDIA_TEXT
def on_get(self, req: Request, resp: Response): user = req.context["user"] resp.media = user_to_dict(user)
def on_get(self, req: Request, resp: Response): resp.media = [user_to_dict(user) for user in users.values()]