wsgirouter3


Namewsgirouter3 JSON
Version 0.8.4 PyPI version JSON
download
home_pagehttps://github.com/andruskutt/wsgirouter3
SummaryWSGI routing library
upload_time2023-01-07 14:39:11
maintainer
docs_urlNone
authorAndrus Kütt
requires_python>=3.7
licenseMIT
keywords web services
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # wsgirouter3

Small opinionated WSGI request dispatcher. Influenced by Flask.

Works using path segments instead of more common regex matching (RFC 3986 path segment parameters are not supported) https://datatracker.ietf.org/doc/html/rfc3986#section-3.3

Path variables are by default defined using RFC 6570 level 1 https://datatracker.ietf.org/doc/html/rfc6570#section-1.2 Start and optional end markers are customizable.
Path variable types are defined using python typing information. Customizable, types supported out-of-box: bool, int, str, uuid.UUID.

WSGI environ wrapper can passed to handler if there is parameter with type Request. No global variables/threadlocals.
Request body and query string binding is also supported, using generic types Body and Query.

Supports overlapping path segments: zero or more literal segments can overlap with one parameter definition. Parameters of different type and/or name in same position are not supported. Literal segment takes precedence.

Route decorators for HTTP methods DELETE, GET, PATCH, POST, PUT.

Response compression. By default enabled for application/json. Configurable compression level.


```python
@router.get('/abc/literal')
def literal():
    pass

@router.get('/abc/{variable}')
def parameterized(variable: str):
    pass
```

Multiple routes can point to same handler:

```python
@router.get('/abc', defaults={'variable': None})
@router.get('/abc/{variable}')
def with_optional_parameter(variable: Optional[str]):
    pass
```

Content negotiation:

```python
@router.get('/get', produces='application/json')
def get() -> dict:
    return {'field': 'value'}

@router.post('/post', consumes='application/json')
def post_with_json(req: Request) -> Tuple[int]:
    data = req.json
    return 204,
```

Query string and request body binding:

```python
@router.get('/get', produces='application/json')
def get(query: Query[dict]) -> dict:
    return query

@router.post('/post', consumes='application/json')
def post_with_json(data: Body[dict]) -> Tuple[int]:
    # do something with data
    return 204,
```

Handler return type handling:

| Type | Description |
| ---- | ----------- |
| tuple | shortcut for returning status code and optional result + headers |
| None | allowed for status codes which have no content |
| dict | application/json |
| str | defined by optional Content-Type header. When header is missing, taken from config.default_str_content_type, by default text/plain;charset=utf-8 |
| bytes | defined by required Content-Type header |
| dataclass | application/json, but overridable by custom result handler |
| typing.GeneratorType | passed as is |

Cache control for responses:

```python
@router.get('/no-store', cache_control=CacheControl.no_store)
def no_store() -> dict:
    return {'a': 1}

@router.get('/store', cache_control=CacheControl.of(max_age=600, private=False))
def store() -> dict:
    return {'a': 1}
```

## Configuration checklist

WsgiAppConfig class

| Task | Action |
| ----------- | ----------- |
| Want to use another json library or configure value types serialized / deserialized | Override json_serializer / json_deserializer |
| Change maximum length of accepted request body | Set value of max_request_content_length |
| Change default content type for str returned | Change value of default_str_content_type |
| Add authorization | Set before_request hook handler, use route options to define roles. See [sample](https://github.com/andruskutt/wsgirouter3/tree/main/examples/authorization/application.py) |
| Handle more return types | Add entry of tuple[matcher, handler] to result_converters or override custom_result_handler |
| Validate/convert query string and request body | Use Query and Body generics with value class in handler and override binder |
| Customize error handling | Override error_handler |
| Disable response compression | set compress_level to 0 |
| Enable response compression for more cases | Update compress_content_types and/or override can_compress_result |
| Configure compression level | Set value of compress_level (0-9 or -1, see zlib documentation) |

PathRouter class

| Task | Action |
| ----------- | ----------- |
| Change parameter markers | Change value of path_parameter_start and path_parameter_end |
| Add new path parameter type | Add new class inherited from PathParameter into parameter_types |

## Installation

```shell
$ pip install wsgirouter3
```

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/andruskutt/wsgirouter3",
    "name": "wsgirouter3",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": "",
    "keywords": "web services",
    "author": "Andrus K\u00fctt",
    "author_email": "andrus.kuett@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/f7/c6/93c27287cfb554b1c2e45f8b36ba0312d3f1dde234598dfd800bfdfed7e9/wsgirouter3-0.8.4.tar.gz",
    "platform": null,
    "description": "# wsgirouter3\n\nSmall opinionated WSGI request dispatcher. Influenced by Flask.\n\nWorks using path segments instead of more common regex matching (RFC 3986 path segment parameters are not supported) https://datatracker.ietf.org/doc/html/rfc3986#section-3.3\n\nPath variables are by default defined using RFC 6570 level 1 https://datatracker.ietf.org/doc/html/rfc6570#section-1.2 Start and optional end markers are customizable.\nPath variable types are defined using python typing information. Customizable, types supported out-of-box: bool, int, str, uuid.UUID.\n\nWSGI environ wrapper can passed to handler if there is parameter with type Request. No global variables/threadlocals.\nRequest body and query string binding is also supported, using generic types Body and Query.\n\nSupports overlapping path segments: zero or more literal segments can overlap with one parameter definition. Parameters of different type and/or name in same position are not supported. Literal segment takes precedence.\n\nRoute decorators for HTTP methods DELETE, GET, PATCH, POST, PUT.\n\nResponse compression. By default enabled for application/json. Configurable compression level.\n\n\n```python\n@router.get('/abc/literal')\ndef literal():\n    pass\n\n@router.get('/abc/{variable}')\ndef parameterized(variable: str):\n    pass\n```\n\nMultiple routes can point to same handler:\n\n```python\n@router.get('/abc', defaults={'variable': None})\n@router.get('/abc/{variable}')\ndef with_optional_parameter(variable: Optional[str]):\n    pass\n```\n\nContent negotiation:\n\n```python\n@router.get('/get', produces='application/json')\ndef get() -> dict:\n    return {'field': 'value'}\n\n@router.post('/post', consumes='application/json')\ndef post_with_json(req: Request) -> Tuple[int]:\n    data = req.json\n    return 204,\n```\n\nQuery string and request body binding:\n\n```python\n@router.get('/get', produces='application/json')\ndef get(query: Query[dict]) -> dict:\n    return query\n\n@router.post('/post', consumes='application/json')\ndef post_with_json(data: Body[dict]) -> Tuple[int]:\n    # do something with data\n    return 204,\n```\n\nHandler return type handling:\n\n| Type | Description |\n| ---- | ----------- |\n| tuple | shortcut for returning status code and optional result + headers |\n| None | allowed for status codes which have no content |\n| dict | application/json |\n| str | defined by optional Content-Type header. When header is missing, taken from config.default_str_content_type, by default text/plain;charset=utf-8 |\n| bytes | defined by required Content-Type header |\n| dataclass | application/json, but overridable by custom result handler |\n| typing.GeneratorType | passed as is |\n\nCache control for responses:\n\n```python\n@router.get('/no-store', cache_control=CacheControl.no_store)\ndef no_store() -> dict:\n    return {'a': 1}\n\n@router.get('/store', cache_control=CacheControl.of(max_age=600, private=False))\ndef store() -> dict:\n    return {'a': 1}\n```\n\n## Configuration checklist\n\nWsgiAppConfig class\n\n| Task | Action |\n| ----------- | ----------- |\n| Want to use another json library or configure value types serialized / deserialized | Override json_serializer / json_deserializer |\n| Change maximum length of accepted request body | Set value of max_request_content_length |\n| Change default content type for str returned | Change value of default_str_content_type |\n| Add authorization | Set before_request hook handler, use route options to define roles. See [sample](https://github.com/andruskutt/wsgirouter3/tree/main/examples/authorization/application.py) |\n| Handle more return types | Add entry of tuple[matcher, handler] to result_converters or override custom_result_handler |\n| Validate/convert query string and request body | Use Query and Body generics with value class in handler and override binder |\n| Customize error handling | Override error_handler |\n| Disable response compression | set compress_level to 0 |\n| Enable response compression for more cases | Update compress_content_types and/or override can_compress_result |\n| Configure compression level | Set value of compress_level (0-9 or -1, see zlib documentation) |\n\nPathRouter class\n\n| Task | Action |\n| ----------- | ----------- |\n| Change parameter markers | Change value of path_parameter_start and path_parameter_end |\n| Add new path parameter type | Add new class inherited from PathParameter into parameter_types |\n\n## Installation\n\n```shell\n$ pip install wsgirouter3\n```\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "WSGI routing library",
    "version": "0.8.4",
    "split_keywords": [
        "web",
        "services"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "59971d2811fd5367e4828c9cfe968318c9d4613d58e08e0a7417d5fc9e00aa2a",
                "md5": "ec235c08317fdf354ffab3972094ef0e",
                "sha256": "1e296c8b03b9a85360be193cb325cc5f74ed179f80198552304c59f89c6a0de2"
            },
            "downloads": -1,
            "filename": "wsgirouter3-0.8.4-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "ec235c08317fdf354ffab3972094ef0e",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 13122,
            "upload_time": "2023-01-07T14:39:09",
            "upload_time_iso_8601": "2023-01-07T14:39:09.413095Z",
            "url": "https://files.pythonhosted.org/packages/59/97/1d2811fd5367e4828c9cfe968318c9d4613d58e08e0a7417d5fc9e00aa2a/wsgirouter3-0.8.4-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "f7c693c27287cfb554b1c2e45f8b36ba0312d3f1dde234598dfd800bfdfed7e9",
                "md5": "803fbcd9359cf0cd813430d8f5db1b81",
                "sha256": "fe14cf5a83ab6153d98c5cc7008b7c0a8c4982119d2fa12c0a7952b21db15f13"
            },
            "downloads": -1,
            "filename": "wsgirouter3-0.8.4.tar.gz",
            "has_sig": false,
            "md5_digest": "803fbcd9359cf0cd813430d8f5db1b81",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 12709,
            "upload_time": "2023-01-07T14:39:11",
            "upload_time_iso_8601": "2023-01-07T14:39:11.011401Z",
            "url": "https://files.pythonhosted.org/packages/f7/c6/93c27287cfb554b1c2e45f8b36ba0312d3f1dde234598dfd800bfdfed7e9/wsgirouter3-0.8.4.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-01-07 14:39:11",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "github_user": "andruskutt",
    "github_project": "wsgirouter3",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [],
    "tox": true,
    "lcname": "wsgirouter3"
}
        
Elapsed time: 0.02536s