Skip to content

Commit

Permalink
Add regex support in path params (#92)
Browse files Browse the repository at this point in the history
* add regex support in path params

Co-authored-by: Valeriia Shestakova <valeriia_shestakova@epam.com>
  • Loading branch information
lerushe and Valeriia Shestakova committed Oct 25, 2021
1 parent 2927b08 commit 05e02f7
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 3 deletions.
7 changes: 7 additions & 0 deletions aiohttp_swagger3/swagger_docs.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import functools
import re
from collections import defaultdict
from typing import Callable, Dict, Optional, Type, Union

Expand All @@ -12,6 +13,8 @@
from .swagger_route import SwaggerRoute, _SwaggerHandler
from .ui_settings import RapiDocUiSettings, ReDocUiSettings, SwaggerUiSettings

_PATH_VAR_REGEX = re.compile(r"{([_a-zA-Z][_a-zA-Z0-9].+?):.+?}(/|$)")


def swagger_doc(path: str) -> Callable:
"""
Expand Down Expand Up @@ -109,6 +112,10 @@ def _wrap_handler(
return handler
*_, spec = handler.__doc__.split("---")
method_spec = yaml.safe_load(spec)
path = _PATH_VAR_REGEX.sub(r"{\1}", path)
if self.spec["paths"].get(path, {}).get(method) is not None:
raise Exception(f"{method} {path} already exists")

self.spec["paths"][path][method] = method_spec
try:
self.spec_validate(self.spec)
Expand Down
6 changes: 3 additions & 3 deletions tests/test_custom_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,17 @@ async def handler(request, body: Dict):

swagger = swagger_docs()
with pytest.raises(Exception) as exc_info:
swagger.add_route("POST", "/r", handler)
swagger.add_route("POST", "/r1", handler)
assert "register handler for custom/handler first" == str(exc_info.value)

swagger.register_media_type_handler("*/handler1", custom_handler)
with pytest.raises(Exception) as exc_info:
swagger.add_route("POST", "/r", handler)
swagger.add_route("POST", "/r2", handler)
assert "missing handler for media type */*" == str(exc_info.value)

swagger.register_media_type_handler("custom/handler1", custom_handler)
with pytest.raises(Exception) as exc_info:
swagger.add_route("POST", "/r", handler)
swagger.add_route("POST", "/r3", handler)
assert "register handler for custom/handler first" == str(exc_info.value)


Expand Down
71 changes: 71 additions & 0 deletions tests/test_docs_paths.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from functools import wraps

import pytest
from aiohttp import web


Expand Down Expand Up @@ -67,3 +68,73 @@ async def handler(request, param_id: int):
resp = await client.get("/r/10")
assert resp.status == 200
assert await resp.json() == {"param_id": 10}


async def test_already_exists_path(swagger_docs, aiohttp_client):
async def handler(request, param_id: int):
"""
---
parameters:
- name: param_id
in: path
required: true
schema:
type: integer
responses:
'200':
description: OK.
"""
return web.json_response({"param_id": param_id})

swagger = swagger_docs()
swagger.add_route("GET", r"/r/{param_id:\d+}", handler)

with pytest.raises(Exception) as exc_info:
swagger.add_route("GET", r"/r/{param_id:\w+}", handler)
assert "get /r/{param_id} already exists" == str(exc_info.value)


async def test_path_with_regex(swagger_docs, aiohttp_client):
async def handler(request, first_param_id: int, second_param_id: int, third_param_id: str):
"""
---
parameters:
- name: first_param_id
in: path
required: true
schema:
type: integer
- name: second_param_id
in: path
required: true
schema:
type: integer
- name: third_param_id
in: path
required: true
schema:
type: string
responses:
'200':
description: OK.
"""
return web.json_response(
{"first_param_id": first_param_id, "second_param_id": second_param_id, "third_param_id": third_param_id}
)

swagger = swagger_docs()
swagger.add_route("GET", r"/r/{first_param_id:\d+}/r/{second_param_id:\d+}/{third_param_id:\w{2,10}}", handler)

client = await aiohttp_client(swagger._app)

resp = await client.get("/r/10/r/11/abc")
assert resp.status == 200
assert await resp.json() == {"first_param_id": 10, "second_param_id": 11, "third_param_id": "abc"}

0 comments on commit 05e02f7

Please sign in to comment.