def __call__(self, chain: HandlerChain, context: RequestContext, response: Response): try: router_response = self.router.dispatch(context.request) response.update_from(router_response) chain.stop() except NotFound: if self.respond_not_found: chain.respond(404)
def on_post(self, request: Request): data = request.get_json(True, True) if not data: return Response("invalid request", 400) # backdoor API to support restarting the instance if data.get("action") in ["kill", "restart"]: terminate_all_processes_in_docker() SHUTDOWN_INFRA.set() return Response("ok", 200)
def __call__(self, chain: HandlerChain, context: RequestContext, response: Response): try: # serve response.update_from(self.resources.dispatch(context.request)) chain.stop() except NotFound: path = context.request.path if path.startswith(constants.INTERNAL_RESOURCE_PATH + "/"): # only return 404 if we're accessing an internal resource, otherwise fall back to the other handlers LOG.warning("Unable to find resource handler for path: %s", path) chain.respond(404)
def __call__( self, chain: HandlerChain, exception: Exception, context: RequestContext, response: Response, ): if not context.service: return error = self.create_exception_response(exception, context) if error: response.update_from(error)
def __call__(self, environ: "WSGIEnvironment", start_response: "StartResponse") -> Iterable[bytes]: # create request from environment LOG.debug( "[%s] %s %s%s", threading.current_thread().name, environ["REQUEST_METHOD"], environ.get("HTTP_HOST"), environ["RAW_URI"], ) request = Request(environ) if "asgi.headers" in environ: # restores raw headers from ASGI scope, which allows dashes in header keys # see https://github.com/pallets/werkzeug/issues/940 request.headers = Headers(environ["asgi.headers"].raw_items()) else: # by default, werkzeug requests from environ are immutable request.headers = Headers(request.headers) # prepare response response = Response() self.gateway.process(request, response) return response(environ, start_response)
def on_get(self, request): from localstack.utils.aws.aws_stack import get_valid_regions deploy_html_file = os.path.join(constants.MODULE_MAIN_PATH, "services", "cloudformation", "deploy.html") deploy_html = load_file(deploy_html_file) req_params = request.values params = { "stackName": "stack1", "templateBody": "{}", "errorMessage": "''", "regions": json.dumps(sorted(list(get_valid_regions()))), } download_url = req_params.get("templateURL") if download_url: try: LOG.debug( "Attempting to download CloudFormation template URL: %s", download_url) template_body = requests.get(download_url).text template_body = parse_json_or_yaml(template_body) params["templateBody"] = json.dumps(template_body) except Exception as e: msg = f"Unable to download CloudFormation template URL: {e}" LOG.info(msg) params["errorMessage"] = json.dumps(msg.replace("\n", " - ")) # using simple string replacement here, for simplicity (could be replaced with, e.g., jinja) for key, value in params.items(): deploy_html = deploy_html.replace(f"<{key}>", value) return Response(deploy_html, mimetype="text/html")
def test_composite_handler_stops_handler_chain(self): def inner1(_chain: HandlerChain, request: RequestContext, response: Response): _chain.stop() inner2 = mock.MagicMock() outer1 = mock.MagicMock() outer2 = mock.MagicMock() response1 = mock.MagicMock() chain = HandlerChain() composite = CompositeHandler() composite.handlers.append(inner1) composite.handlers.append(inner2) chain.request_handlers.append(outer1) chain.request_handlers.append(composite) chain.request_handlers.append(outer2) chain.response_handlers.append(response1) chain.handle(RequestContext(), Response()) outer1.assert_called_once() outer2.assert_not_called() inner2.assert_not_called() response1.assert_called_once()
def test_composite_handler_exception_calls_outer_exception_handlers(self): def inner1(_chain: HandlerChain, request: RequestContext, response: Response): raise ValueError() inner2 = mock.MagicMock() outer1 = mock.MagicMock() outer2 = mock.MagicMock() exception_handler = mock.MagicMock() response1 = mock.MagicMock() chain = HandlerChain() composite = CompositeHandler() composite.handlers.append(inner1) composite.handlers.append(inner2) chain.request_handlers.append(outer1) chain.request_handlers.append(composite) chain.request_handlers.append(outer2) chain.exception_handlers.append(exception_handler) chain.response_handlers.append(response1) chain.handle(RequestContext(), Response()) outer1.assert_called_once() outer2.assert_not_called() inner2.assert_not_called() exception_handler.assert_called_once() response1.assert_called_once()
def invoke_rest_api(self, request: Request, **url_params: Dict[str, Any]) -> Response: if not url_params["api_id"] in API_REGIONS: return Response(status=404) invocation_context = to_invocation_context(request, url_params) result = invoke_rest_api_from_request(invocation_context) if result is not None: return convert_response(result) raise NotFound()
def __call__(self, chain: HandlerChain, context: RequestContext, response: Response): if not context.service: return service_name = context.service.service_name operation_name = context.operation.name key = ServiceOperation(service_name, operation_name) handler = self.handlers.get(key) if not handler: error = self.create_not_implemented_response(context) response.update_from(error) chain.stop() return handler(chain, context, response)
def __call__( self, chain: HandlerChain, exception: Exception, context: RequestContext, response: Response, ): if response.data: # response already set return LOG.debug("setting internal failure response for %s", exception) response.status_code = 500 response.set_json( { "message": "Unexpected exception", "error": str(exception), "type": str(exception.__class__.__name__), } )
def __call__(self, chain: HandlerChain, context: RequestContext, response: Response) -> None: if (not config.DISABLE_CORS_CHECKS and self.should_enforce_self_managed_service(context) and not self.is_cors_origin_allowed(context.request.headers)): LOG.info( "Blocked CORS request from forbidden origin %s", context.request.headers.get("origin") or context.request.headers.get("referer"), ) response.status_code = 403 chain.terminate()
def return_response(self, method: str, path: str, data: MessagePayload, headers: Headers, response: Response) -> Optional[Response]: if headers.get("Accept") == APPLICATION_JSON: try: if response._content or b"".startswith(b"<"): content = xmltodict.parse(to_str(response._content)) stripped_content = strip_xmlns(content) response._content = stripped_content except Exception as e: LOG.debug("Unable to convert XML response to JSON", exc_info=e) return super().return_response(method, path, data, headers, response)
def convert_response(result: RequestsResponse) -> Response: """ Utility function to convert a response for the requests library to our internal (Werkzeug based) Response object. """ if result is None: return Response() if isinstance(result, LambdaResponse): headers = Headers(dict(result.headers)) for k, values in result.multi_value_headers.items(): for value in values: headers.add(k, value) else: headers = dict(result.headers) response = Response(status=result.status_code, headers=headers) if isinstance(result.content, dict): response.set_json(result.content) elif isinstance(result.content, (str, bytes)): response.data = result.content else: raise ValueError(f"Unhandled content type {type(result.content)}") return response
def __call__(self, chain: HandlerChain, context: RequestContext, response: Response): request = context.request # a werkzeug Request consumes form/multipart data from the socket stream, so we need to restore the payload here data = restore_payload(request) # TODO: rethink whether this proxy handling is necessary context.request.headers[ HEADER_LOCALSTACK_REQUEST_URL] = context.request.base_url result = self.forward_request( context, method=request.method, path=request.full_path if request.query_string else request.path, data=data, headers=request.headers, ) if type(result) == int: chain.respond(status_code=result) return if isinstance(result, tuple): # special case for Kinesis SubscribeToShard if len(result) == 2: response.status_code = 200 response.set_response(result[0]) response.headers.update(dict(result[1])) chain.stop() return if isinstance(result, RequestsResponse): response.status_code = result.status_code response.set_response(result.content) # make sure headers are set after the content, so potential content-length headers are overwritten response.headers.update(dict(result.headers)) # make sure content-length is re-calculated correctly, unless it's a HEAD request if request.method != "HEAD": length = response.calculate_content_length() if length is not None: response.headers["Content-Length"] = str(length) chain.stop() return raise ValueError("cannot create response for result %s" % result)
def handle_request(request: Request, region: str) -> Response: if request.is_json: # TODO: the response should be sent as JSON response raise NotImplementedError try: response, operation = try_call_sqs(request, region) del response["ResponseMetadata"] return serializer.serialize_to_response(response, operation) except UnknownOperationException: return Response("<UnknownOperationException/>", 404) except CommonServiceException as e: # use a dummy operation for the serialization to work op = service.operation_model(service.operation_names[0]) return serializer.serialize_error_to_response(e, op) except Exception as e: LOG.exception("exception") op = service.operation_model(service.operation_names[0]) return serializer.serialize_error_to_response( CommonServiceException( "InternalError", f"An internal error ocurred: {e}", status_code=500 ), op, )
def test_composite_handler_continues_handler_chain(self): inner1 = mock.MagicMock() inner2 = mock.MagicMock() outer1 = mock.MagicMock() outer2 = mock.MagicMock() response1 = mock.MagicMock() chain = HandlerChain() composite = CompositeHandler() composite.handlers.append(inner1) composite.handlers.append(inner2) chain.request_handlers.append(outer1) chain.request_handlers.append(composite) chain.request_handlers.append(outer2) chain.response_handlers.append(response1) chain.handle(RequestContext(), Response()) outer1.assert_called_once() outer2.assert_called_once() inner1.assert_called_once() inner2.assert_called_once() response1.assert_called_once()
def __call__(self, request: Request, endpoint: E, args: RequestArguments) -> Response: self.requests.append((request, endpoint, args)) return Response()
def handler(_request: Request, arg1) -> Response: # invalid signature return Response("ok")
def handler_bar(_request: Request, bar, baz) -> Dict[str, any]: response = Response() response.set_json({"bar": bar, "baz": baz}) return response
def handler_foo(_request: Request) -> Response: return Response("ok")
def on_get(self, req, resp: Response): resp.set_json({"message": "GET/OK"})
def ep_index2(_: Request, args) -> Response: response = Response() response.set_json(dict(method="2", **args)) return response
def ep_all(_: Request, args) -> Response: response = Response() response.set_json(dict(method="all", **args)) return response
def users(_: Request, args) -> Response: response = Response() response.set_json(args) return response
def users(_: Request, args) -> Response: return Response(b"users")
def index(_: Request, args) -> Response: return Response(b"index")
def echo_json(request: Request, args) -> Response: response = Response() response.set_json(request.json) return response
def __call__(self, chain: HandlerChain, context: RequestContext, response: Response): skeleton_response = self.skeleton.invoke(context) response.update_from(skeleton_response)
def index(_: Request, args) -> Response: response = Response() response.set_json(args) return response