Ejemplo n.º 1
0
    def test_add_route_endpoint_with_object(self):
        class MySuperApi:
            @route("/users")
            def user(self, _: Request, args):
                # should be inherited
                assert not args
                return Response("user")

        class MyApi(MySuperApi):
            @route("/users/<int:user_id>")
            def user_id(self, _: Request, args):
                assert args
                return Response(f"{args['user_id']}")

            def foo(self, _: Request, args):
                # should be ignored
                raise NotImplementedError

        api = MyApi()
        router = Router()
        rules = router.add_route_endpoints(api)
        assert len(rules) == 2

        assert router.dispatch(Request("GET", "/users")).data == b"user"
        assert router.dispatch(Request("GET", "/users/123")).data == b"123"
Ejemplo n.º 2
0
    def test_handler_dispatcher_with_none_return(self):
        router = Router(dispatcher=handler_dispatcher())

        def handler(_request: Request):
            return None

        router.add("/", handler)
        assert router.dispatch(Request("GET", "/")).status_code == 200
Ejemplo n.º 3
0
    def test_handler_dispatcher_with_text_return(self):
        router = Router(dispatcher=handler_dispatcher())

        def handler(_request: Request, arg1) -> str:
            return f"hello: {arg1}"

        router.add("/<arg1>", handler)
        assert router.dispatch(Request("GET",
                                       "/world")).data == b"hello: world"
Ejemplo n.º 4
0
    def test_handler_dispatcher_with_dict_return(self):
        router = Router(dispatcher=handler_dispatcher())

        def handler(_request: Request, arg1) -> Dict[str, Any]:
            return {"arg1": arg1, "hello": "there"}

        router.add("/foo/<arg1>", handler)
        assert router.dispatch(Request("GET", "/foo/a")).json == {
            "arg1": "a",
            "hello": "there"
        }
Ejemplo n.º 5
0
    def test_dispatch_with_host_matching(self):
        router = Router()

        def ep_all(_: Request, args) -> Response:
            response = Response()
            response.set_json(dict(method="all", **args))
            return response

        def ep_index1(_: Request, args) -> Response:
            response = Response()
            response.set_json(dict(method="1", **args))
            return response

        def ep_index2(_: Request, args) -> Response:
            response = Response()
            response.set_json(dict(method="2", **args))
            return response

        router.add("/", ep_index1, host="localhost:<port>")
        router.add("/", ep_index2, host="localhost:12345")
        router.add("/all", ep_all, host="<host>")

        def invoke(path, server, port):
            return router.dispatch(Request("GET", path, server=(server, port))).json

        assert invoke("/", "localhost", 4566) == {"method": "1", "port": "4566"}
        assert invoke("/", "localhost", 12345) == {"method": "2"}
        assert invoke("/all", "127.0.0.1", None) == {"method": "all", "host": "127.0.0.1"}
        assert invoke("/all", "127.0.0.1", 12345) == {"method": "all", "host": "127.0.0.1:12345"}

        with pytest.raises(NotFound):
            invoke("/", "localstack.cloud", None)
Ejemplo n.º 6
0
    def test_with_werkzeug(self):
        # setup up router
        router = Router()

        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 users(_: Request, args) -> Response:
            response = Response()
            response.set_json(args)
            return response

        router.add("/", index)
        router.add("/users/<int:user_id>", users, host="<host>:<port>")
        router.add("/echo/", echo_json, methods=["POST"])

        # serve router through werkzeug
        @werkzeug.Request.application
        def app(request: werkzeug.Request) -> werkzeug.Response:
            return router.dispatch(request)

        host = "localhost"
        port = get_free_tcp_port()
        url = f"http://{host}:{port}"

        server = werkzeug.serving.make_server(host,
                                              port,
                                              app=app,
                                              threaded=True)
        t = threading.Thread(target=server.serve_forever)
        t.start()

        try:
            resp = requests.get(f"{url}/")
            assert resp.ok
            assert resp.content == b"index"

            resp = requests.get(f"{url}/users/123")
            assert resp.ok
            assert resp.json() == {
                "user_id": 123,
                "host": host,
                "port": str(port)
            }

            resp = requests.get(f"{url}/users")
            assert not resp.ok

            resp = requests.post(f"{url}/echo", json={"foo": "bar", "a": 420})
            assert resp.ok
            assert resp.json() == {"foo": "bar", "a": 420}
        finally:
            server.shutdown()
            t.join(timeout=10)
Ejemplo n.º 7
0
    def test_router_route_decorator(self):
        router = Router()

        @router.route("/users")
        def user(_: Request, args):
            assert not args
            return Response("user")

        @router.route("/users/<int:user_id>")
        def user_id(_: Request, args):
            assert args
            return Response(f"{args['user_id']}")

        assert router.dispatch(Request("GET", "/users")).data == b"user"
        assert router.dispatch(Request("GET", "/users/123")).data == b"123"
Ejemplo n.º 8
0
    def test_custom_dispatcher(self):
        collector = RequestCollector()
        router = Router(dispatcher=collector)

        router.add("/", "index")
        router.add("/users/<int:id>", "users")

        router.dispatch(Request("GET", "/"))
        router.dispatch(Request("GET", "/users/12"))

        _, endpoint, args = collector.requests[0]
        assert endpoint == "index"
        assert args == {}

        _, endpoint, args = collector.requests[1]
        assert endpoint == "users"
        assert args == {"id": 12}
Ejemplo n.º 9
0
 def test_regex_path_dispatcher(self):
     router = Router()
     router.url_map.converters["regex"] = RegexConverter
     rgx = r"([^.]+)endpoint(.*)"
     regex = f"/<regex('{rgx}'):dist>/"
     router.add(path=regex, endpoint=noop)
     assert router.dispatch(Request(method="GET", path="/test-endpoint"))
     with pytest.raises(NotFound):
         router.dispatch(Request(method="GET", path="/test-not-point"))
Ejemplo n.º 10
0
    def test_dispatch_to_correct_function(self):
        router = Router(dispatcher=resource_dispatcher(pass_response=False))

        requests = []

        class TestResource:
            def on_get(self, req):
                requests.append(req)
                return "GET/OK"

            def on_post(self, req):
                requests.append(req)
                return {"ok": "POST"}

        router.add("/health", TestResource())

        request1 = Request("GET", "/health")
        request2 = Request("POST", "/health")
        assert router.dispatch(request1).get_data(True) == "GET/OK"
        assert router.dispatch(request1).get_data(True) == "GET/OK"
        assert router.dispatch(request2).json == {"ok": "POST"}
        assert len(requests) == 3
        assert requests[0] is request1
        assert requests[1] is request1
        assert requests[2] is request2
Ejemplo n.º 11
0
    def test_remove_non_existing_rule(self):
        router = Router()

        def index(_: Request, args) -> Response:
            return Response(b"index")

        rule = router.add("/", index)
        router.remove_rule(rule)

        with pytest.raises(KeyError) as e:
            router.remove_rule(rule)
        e.match("no such rule")
Ejemplo n.º 12
0
    def test_handler_dispatcher_invalid_signature(self):
        router = Router(dispatcher=handler_dispatcher())

        def handler(_request: Request, arg1) -> Response:  # invalid signature
            return Response("ok")

        router.add("/foo/<arg1>/<arg2>", handler)

        with pytest.raises(TypeError):
            router.dispatch(Request("GET", "/foo/a/b"))
Ejemplo n.º 13
0
    def test_default_dispatcher_invokes_correct_endpoint(self):
        router = Router()

        def index(_: Request, args) -> Response:
            response = Response()
            response.set_json(args)
            return response

        def users(_: Request, args) -> Response:
            response = Response()
            response.set_json(args)
            return response

        router.add("/", index)
        router.add("/users/<int:user_id>", users)

        assert router.dispatch(Request("GET", "/")).json == {}
        assert router.dispatch(Request("GET", "/users/12")).json == {"user_id": 12}
Ejemplo n.º 14
0
    def test_handler_dispatcher(self):
        router = Router(dispatcher=handler_dispatcher())

        def handler_foo(_request: Request) -> Response:
            return Response("ok")

        def handler_bar(_request: Request, bar, baz) -> Dict[str, any]:
            response = Response()
            response.set_json({"bar": bar, "baz": baz})
            return response

        router.add("/foo", handler_foo)
        router.add("/bar/<int:bar>/<baz>", handler_bar)

        assert router.dispatch(Request("GET", "/foo")).data == b"ok"
        assert router.dispatch(Request("GET", "/bar/420/ed")).json == {
            "bar": 420,
            "baz": "ed"
        }

        with pytest.raises(NotFound):
            assert router.dispatch(Request("GET", "/bar/asfg/ed"))
Ejemplo n.º 15
0
    def test_dispatch_to_non_existing_method_raises_exception(self):
        router = Router(dispatcher=resource_dispatcher(pass_response=False))

        class TestResource:
            def on_post(self, request):
                return "POST/OK"

        router.add("/health", TestResource())

        with pytest.raises(MethodNotAllowed):
            assert router.dispatch(Request("GET", "/health"))
        assert router.dispatch(Request("POST",
                                       "/health")).get_data(True) == "POST/OK"
Ejemplo n.º 16
0
 def test_regex_host_dispatcher(self):
     router = Router()
     router.url_map.converters["regex"] = RegexConverter
     rgx = r"\.cloudfront.(net|localhost\.localstack\.cloud)"
     router.add(path="/", endpoint=noop, host=f"<dist_id><regex('{rgx}'):host>:<port>")
     assert router.dispatch(
         Request(
             method="GET",
             headers={"Host": "ad91f538.cloudfront.localhost.localstack.cloud:5446"},
         )
     )
     with pytest.raises(NotFound):
         router.dispatch(
             Request(
                 method="GET",
                 headers={"Host": "ad91f538.cloudfront.amazon.aws.com:5446"},
             )
         )
Ejemplo n.º 17
0
    def test_dispatcher_with_pass_response(self):
        router = Router(dispatcher=resource_dispatcher(pass_response=True))

        class TestResource:
            def on_get(self, req, resp: Response):
                resp.set_json({"message": "GET/OK"})

            def on_post(self, req, resp):
                resp.set_data("POST/OK")

        router.add("/health", TestResource())
        assert router.dispatch(Request("GET", "/health")).json == {
            "message": "GET/OK"
        }
        assert router.dispatch(Request("POST",
                                       "/health")).get_data(True) == "POST/OK"
Ejemplo n.º 18
0
    # certain EC2 requests from Java SDK contain no Auth headers (issue #3805)
    if b"Version=2016-11-15" in data_bytes:
        return "ec2", config.service_port("ec2")


def get_service_port_for_account(service, headers):
    # assume we're only using a single account, hence return the static port mapping from config.py
    return config.service_port(service)


PROXY_LISTENER_EDGE = ProxyListenerEdge()
# the ROUTER is part of the edge proxy. use the router to inject custom handlers that are handled before actual
# service calls
ROUTER: Router[Handler] = Router(
    dispatcher=handler_dispatcher(), converters={"regex": RegexConverter}
)


def is_trace_logging_enabled(headers):
    if not config.LS_LOG:
        return False
    if config.LS_LOG == LS_LOG_TRACE_INTERNAL:
        return True
    auth_header = headers.get("Authorization") or ""
    return INTERNAL_AWS_ACCESS_KEY_ID not in auth_header


def do_start_edge(bind_address, port, use_ssl, asynchronous=False):
    from localstack.http.adapters import RouterListener
    from localstack.services.internal import LocalstackResourceHandler
Ejemplo n.º 19
0
    def test_remove_rule(self):
        router = Router()

        def index(_: Request, args) -> Response:
            return Response(b"index")

        def users(_: Request, args) -> Response:
            return Response(b"users")

        rule0 = router.add("/", index)
        rule1 = router.add("/users/<int:user_id>", users)

        assert router.dispatch(Request("GET", "/")).data == b"index"
        assert router.dispatch(Request("GET", "/users/12")).data == b"users"

        router.remove_rule(rule1)

        assert router.dispatch(Request("GET", "/")).data == b"index"
        with pytest.raises(NotFound):
            assert router.dispatch(Request("GET", "/users/12"))

        router.remove_rule(rule0)
        with pytest.raises(NotFound):
            assert router.dispatch(Request("GET", "/"))
        with pytest.raises(NotFound):
            assert router.dispatch(Request("GET", "/users/12"))
Ejemplo n.º 20
0
 def test_dispatch_raises_not_found(self):
     router = Router()
     router.add("/foobar", noop)
     with pytest.raises(NotFound):
         assert router.dispatch(Request("GET", "/foo"))