diff --git a/sanic/constants.py b/sanic/constants.py index cb2e8ffa..80f1d2a9 100644 --- a/sanic/constants.py +++ b/sanic/constants.py @@ -1,2 +1,28 @@ -HTTP_METHODS = ("GET", "POST", "PUT", "HEAD", "OPTIONS", "PATCH", "DELETE") +from enum import Enum, auto + + +class HTTPMethod(str, Enum): + def _generate_next_value_(name, start, count, last_values): + return name.upper() + + def __eq__(self, value: object) -> bool: + value = str(value).upper() + return super().__eq__(value) + + def __hash__(self) -> int: + return hash(self.value) + + def __str__(self) -> str: + return self.value + + GET = auto() + POST = auto() + PUT = auto() + HEAD = auto() + OPTIONS = auto() + PATCH = auto() + DELETE = auto() + + +HTTP_METHODS = tuple(HTTPMethod.__members__.values()) DEFAULT_HTTP_CONTENT_TYPE = "application/octet-stream" diff --git a/sanic/router.py b/sanic/router.py index e3343037..0973a3fa 100644 --- a/sanic/router.py +++ b/sanic/router.py @@ -109,7 +109,7 @@ class Router(BaseRouter): params = dict( path=uri, handler=handler, - methods=methods, + methods=frozenset(map(str, methods)) if methods else None, name=name, strict=strict_slashes, unquote=unquote, diff --git a/tests/test_constants.py b/tests/test_constants.py new file mode 100644 index 00000000..7ce6e4d7 --- /dev/null +++ b/tests/test_constants.py @@ -0,0 +1,28 @@ +from crypt import methods + +from sanic import text +from sanic.constants import HTTP_METHODS, HTTPMethod + + +def test_string_compat(): + assert "GET" == HTTPMethod.GET + assert "GET" in HTTP_METHODS + assert "get" == HTTPMethod.GET + assert "get" in HTTP_METHODS + + assert HTTPMethod.GET.lower() == "get" + assert HTTPMethod.GET.upper() == "GET" + + +def test_use_in_routes(app): + @app.route("/", methods=[HTTPMethod.GET, HTTPMethod.POST]) + def handler(_): + return text("It works") + + _, response = app.test_client.get("/") + assert response.status == 200 + assert response.text == "It works" + + _, response = app.test_client.post("/") + assert response.status == 200 + assert response.text == "It works"