Skip to content

Commit af6f24a

Browse files
authored
Merge pull request #468 from infogrid-io/fix/django-path-parameter-pattern
Fix PATH_PARAMETER_PATTERN for DRF default value pattern.
2 parents 76faeb6 + 3cb7cd9 commit af6f24a

File tree

2 files changed

+49
-60
lines changed

2 files changed

+49
-60
lines changed

openapi_core/contrib/django/requests.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,19 @@
88

99
from openapi_core.validation.request.datatypes import RequestParameters
1010

11-
# https://docs.djangoproject.com/en/2.2/topics/http/urls/
11+
# https://docs.djangoproject.com/en/stable/topics/http/urls/
1212
#
1313
# Currently unsupported are :
1414
# - nested arguments, e.g.: ^comments/(?:page-(?P<page_number>\d+)/)?$
1515
# - unnamed regex groups, e.g.: ^articles/([0-9]{4})/$
1616
# - multiple named parameters between a single pair of slashes
1717
# e.g.: <page_slug>-<page_id>/edit/
1818
#
19-
# The regex matches everything, except a "/" until "<". Than only the name
19+
# The regex matches everything, except a "/" until "<". Then only the name
2020
# is exported, after which it matches ">" and everything until a "/".
21-
PATH_PARAMETER_PATTERN = r"(?:[^\/]*?)<(?:(?:.*?:))*?(\w+)>(?:[^\/]*)"
21+
# A check is made to ensure that "/" is not in an excluded character set such
22+
# as may be found with Django REST Framwork's default value pattern, "[^/.]+".
23+
PATH_PARAMETER_PATTERN = r"(?:[^/]*?)<(?:(?:.*?:))*?(\w+)>(?:(?:[^/]*?\[\^[^/]*/)?[^/]*)"
2224

2325

2426
class DjangoOpenAPIRequest:

tests/unit/contrib/django/test_django.py

Lines changed: 44 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ def django_settings(self):
4343
settings.ROOT_URLCONF = (
4444
path("admin/", admin.site.urls),
4545
re_path("^test/test-regexp/$", lambda d: None),
46+
re_path("^object/(?P<pk>[^/.]+)/action/$", lambda d: None),
4647
)
4748

4849
@pytest.fixture
@@ -68,81 +69,53 @@ def test_no_resolver(self, request_factory):
6869

6970
openapi_request = DjangoOpenAPIRequest(request)
7071

71-
path = {}
72-
query = ImmutableMultiDict(
73-
[
74-
("test1", "test2"),
75-
]
76-
)
77-
headers = Headers(
78-
{
79-
"Cookie": "",
80-
}
81-
)
82-
cookies = {}
8372
assert openapi_request.parameters == RequestParameters(
84-
path=path,
85-
query=query,
86-
header=headers,
87-
cookie=cookies,
73+
path={},
74+
query=ImmutableMultiDict([("test1", "test2")]),
75+
header=Headers({"Cookie": ""}),
76+
cookie={},
8877
)
8978
assert openapi_request.method == request.method.lower()
9079
assert openapi_request.host_url == request._current_scheme_host
9180
assert openapi_request.path == request.path
81+
assert openapi_request.path_pattern is None
9282
assert openapi_request.body == ""
9383
assert openapi_request.mimetype == request.content_type
9484

9585
def test_simple(self, request_factory):
9686
from django.urls import resolve
9787

9888
request = request_factory.get("/admin/")
99-
request.resolver_match = resolve("/admin/")
89+
request.resolver_match = resolve(request.path)
10090

10191
openapi_request = DjangoOpenAPIRequest(request)
10292

103-
path = {}
104-
query = {}
105-
headers = Headers(
106-
{
107-
"Cookie": "",
108-
}
109-
)
110-
cookies = {}
11193
assert openapi_request.parameters == RequestParameters(
112-
path=path,
113-
query=query,
114-
header=headers,
115-
cookie=cookies,
94+
path={},
95+
query={},
96+
header=Headers({"Cookie": ""}),
97+
cookie={},
11698
)
11799
assert openapi_request.method == request.method.lower()
118100
assert openapi_request.host_url == request._current_scheme_host
119101
assert openapi_request.path == request.path
102+
assert openapi_request.path_pattern == request.path
120103
assert openapi_request.body == ""
121104
assert openapi_request.mimetype == request.content_type
122105

123106
def test_url_rule(self, request_factory):
124107
from django.urls import resolve
125108

126109
request = request_factory.get("/admin/auth/group/1/")
127-
request.resolver_match = resolve("/admin/auth/group/1/")
110+
request.resolver_match = resolve(request.path)
128111

129112
openapi_request = DjangoOpenAPIRequest(request)
130113

131-
path = {
132-
"object_id": "1",
133-
}
134-
query = {}
135-
headers = Headers(
136-
{
137-
"Cookie": "",
138-
}
139-
)
140-
cookies = {}
141114
assert openapi_request.parameters == RequestParameters(
142-
path=path,
143-
query=query,
144-
header=headers,
145-
cookie=cookies,
115+
path={"object_id": "1"},
116+
query={},
117+
header=Headers({"Cookie": ""}),
118+
cookie={},
146119
)
147120
assert openapi_request.method == request.method.lower()
148121
assert openapi_request.host_url == request._current_scheme_host
@@ -155,27 +128,41 @@ def test_url_regexp_pattern(self, request_factory):
155128
from django.urls import resolve
156129

157130
request = request_factory.get("/test/test-regexp/")
158-
request.resolver_match = resolve("/test/test-regexp/")
131+
request.resolver_match = resolve(request.path)
159132

160133
openapi_request = DjangoOpenAPIRequest(request)
161134

162-
path = {}
163-
query = {}
164-
headers = Headers(
165-
{
166-
"Cookie": "",
167-
}
135+
assert openapi_request.parameters == RequestParameters(
136+
path={},
137+
query={},
138+
header=Headers({"Cookie": ""}),
139+
cookie={},
168140
)
169-
cookies = {}
141+
assert openapi_request.method == request.method.lower()
142+
assert openapi_request.host_url == request._current_scheme_host
143+
assert openapi_request.path == request.path
144+
assert openapi_request.path_pattern == request.path
145+
assert openapi_request.body == ""
146+
assert openapi_request.mimetype == request.content_type
147+
148+
def test_drf_default_value_pattern(self, request_factory):
149+
from django.urls import resolve
150+
151+
request = request_factory.get("/object/123/action/")
152+
request.resolver_match = resolve(request.path)
153+
154+
openapi_request = DjangoOpenAPIRequest(request)
155+
170156
assert openapi_request.parameters == RequestParameters(
171-
path=path,
172-
query=query,
173-
header=headers,
174-
cookie=cookies,
157+
path={"pk": "123"},
158+
query={},
159+
header=Headers({"Cookie": ""}),
160+
cookie={},
175161
)
176162
assert openapi_request.method == request.method.lower()
177163
assert openapi_request.host_url == request._current_scheme_host
178-
assert openapi_request.path == "/test/test-regexp/"
164+
assert openapi_request.path == request.path
165+
assert openapi_request.path_pattern == "/object/{pk}/action/"
179166
assert openapi_request.body == ""
180167
assert openapi_request.mimetype == request.content_type
181168

0 commit comments

Comments
 (0)