Skip to content

Commit 0afd172

Browse files
author
Rob Hudson
committed
Replace HttpResponse type with HttpResponseBase
1 parent c2a4317 commit 0afd172

File tree

4 files changed

+42
-38
lines changed

4 files changed

+42
-38
lines changed

csp/contrib/rate_limiting.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
from csp.utils import build_policy
99

1010
if TYPE_CHECKING:
11-
from django.http import HttpRequest, HttpResponse
11+
from django.http import HttpRequest, HttpResponseBase
1212

1313

1414
class RateLimitedCSPMiddleware(CSPMiddleware):
1515
"""A CSP middleware that rate-limits the number of violation reports sent
1616
to report-uri by excluding it from some requests."""
1717

18-
def build_policy(self, request: HttpRequest, response: HttpResponse) -> str:
18+
def build_policy(self, request: HttpRequest, response: HttpResponseBase) -> str:
1919
config = getattr(response, "_csp_config", None)
2020
update = getattr(response, "_csp_update", None)
2121
replace = getattr(response, "_csp_replace", {})
@@ -33,7 +33,7 @@ def build_policy(self, request: HttpRequest, response: HttpResponse) -> str:
3333

3434
return build_policy(config=config, update=update, replace=replace, nonce=nonce)
3535

36-
def build_policy_ro(self, request: HttpRequest, response: HttpResponse) -> str:
36+
def build_policy_ro(self, request: HttpRequest, response: HttpResponseBase) -> str:
3737
config = getattr(response, "_csp_config_ro", None)
3838
update = getattr(response, "_csp_update_ro", None)
3939
replace = getattr(response, "_csp_replace_ro", {})

csp/decorators.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1+
from __future__ import annotations
2+
13
from functools import wraps
2-
from typing import Callable, Optional, Any, Dict, List
3-
from django.http import HttpRequest, HttpResponse
4+
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional
5+
6+
if TYPE_CHECKING:
7+
from django.http import HttpRequest, HttpResponseBase
48

5-
# A generic Django view function
6-
_VIEW_T = Callable[[HttpRequest], HttpResponse]
7-
_VIEW_DECORATOR_T = Callable[[_VIEW_T], _VIEW_T]
9+
# A generic Django view function
10+
_VIEW_T = Callable[[HttpRequest], HttpResponseBase]
11+
_VIEW_DECORATOR_T = Callable[[_VIEW_T], _VIEW_T]
812

913

1014
def csp_exempt(REPORT_ONLY: Optional[bool] = None) -> _VIEW_DECORATOR_T:
@@ -18,7 +22,7 @@ def csp_exempt(REPORT_ONLY: Optional[bool] = None) -> _VIEW_DECORATOR_T:
1822

1923
def decorator(f: _VIEW_T) -> _VIEW_T:
2024
@wraps(f)
21-
def _wrapped(*a: Any, **kw: Any) -> HttpResponse:
25+
def _wrapped(*a: Any, **kw: Any) -> HttpResponseBase:
2226
resp = f(*a, **kw)
2327
if REPORT_ONLY:
2428
setattr(resp, "_csp_exempt_ro", True)
@@ -44,7 +48,7 @@ def csp_update(config: Optional[Dict[str, Any]] = None, REPORT_ONLY: bool = Fals
4448

4549
def decorator(f: _VIEW_T) -> _VIEW_T:
4650
@wraps(f)
47-
def _wrapped(*a: Any, **kw: Any) -> HttpResponse:
51+
def _wrapped(*a: Any, **kw: Any) -> HttpResponseBase:
4852
resp = f(*a, **kw)
4953
if REPORT_ONLY:
5054
setattr(resp, "_csp_update_ro", config)
@@ -63,7 +67,7 @@ def csp_replace(config: Optional[Dict[str, Any]] = None, REPORT_ONLY: bool = Fal
6367

6468
def decorator(f: _VIEW_T) -> _VIEW_T:
6569
@wraps(f)
66-
def _wrapped(*a: Any, **kw: Any) -> HttpResponse:
70+
def _wrapped(*a: Any, **kw: Any) -> HttpResponseBase:
6771
resp = f(*a, **kw)
6872
if REPORT_ONLY:
6973
setattr(resp, "_csp_replace_ro", config)
@@ -87,7 +91,7 @@ def csp(config: Optional[Dict[str, Any]] = None, REPORT_ONLY: bool = False, **kw
8791

8892
def decorator(f: _VIEW_T) -> _VIEW_T:
8993
@wraps(f)
90-
def _wrapped(*a: Any, **kw: Any) -> HttpResponse:
94+
def _wrapped(*a: Any, **kw: Any) -> HttpResponseBase:
9195
resp = f(*a, **kw)
9296
if REPORT_ONLY:
9397
setattr(resp, "_csp_config_ro", processed_config)

csp/middleware.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from csp.utils import build_policy
1414

1515
if TYPE_CHECKING:
16-
from django.http import HttpRequest, HttpResponse
16+
from django.http import HttpRequest, HttpResponseBase
1717

1818

1919
class CSPMiddleware(MiddlewareMixin):
@@ -39,7 +39,7 @@ def process_request(self, request: HttpRequest) -> None:
3939
nonce = partial(self._make_nonce, request)
4040
setattr(request, "csp_nonce", SimpleLazyObject(nonce))
4141

42-
def process_response(self, request: HttpRequest, response: HttpResponse) -> HttpResponse:
42+
def process_response(self, request: HttpRequest, response: HttpResponseBase) -> HttpResponseBase:
4343
# Check for debug view
4444
exempted_debug_codes = (
4545
http_client.INTERNAL_SERVER_ERROR,
@@ -72,14 +72,14 @@ def process_response(self, request: HttpRequest, response: HttpResponse) -> Http
7272

7373
return response
7474

75-
def build_policy(self, request: HttpRequest, response: HttpResponse) -> str:
75+
def build_policy(self, request: HttpRequest, response: HttpResponseBase) -> str:
7676
config = getattr(response, "_csp_config", None)
7777
update = getattr(response, "_csp_update", None)
7878
replace = getattr(response, "_csp_replace", None)
7979
nonce = getattr(request, "_csp_nonce", None)
8080
return build_policy(config=config, update=update, replace=replace, nonce=nonce)
8181

82-
def build_policy_ro(self, request: HttpRequest, response: HttpResponse) -> str:
82+
def build_policy_ro(self, request: HttpRequest, response: HttpResponseBase) -> str:
8383
config = getattr(response, "_csp_config_ro", None)
8484
update = getattr(response, "_csp_update_ro", None)
8585
replace = getattr(response, "_csp_replace_ro", None)

csp/tests/test_decorators.py

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@
1212
from csp.tests.utils import response
1313

1414
if TYPE_CHECKING:
15-
from django.http import HttpRequest
15+
from django.http import HttpRequest, HttpResponseBase
1616

1717
mw = CSPMiddleware(response())
1818

1919

2020
def test_csp_exempt() -> None:
2121
@csp_exempt()
22-
def view(request: HttpRequest) -> HttpResponse:
22+
def view(request: HttpRequest) -> HttpResponseBase:
2323
return HttpResponse()
2424

2525
response = view(RequestFactory().get("/"))
@@ -29,7 +29,7 @@ def view(request: HttpRequest) -> HttpResponse:
2929

3030
def test_csp_exempt_ro() -> None:
3131
@csp_exempt(REPORT_ONLY=True)
32-
def view(request: HttpRequest) -> HttpResponse:
32+
def view(request: HttpRequest) -> HttpResponseBase:
3333
return HttpResponse()
3434

3535
response = view(RequestFactory().get("/"))
@@ -41,7 +41,7 @@ def view(request: HttpRequest) -> HttpResponse:
4141
def test_csp_update() -> None:
4242
request = RequestFactory().get("/")
4343

44-
def view_without_decorator(request: HttpRequest) -> HttpResponse:
44+
def view_without_decorator(request: HttpRequest) -> HttpResponseBase:
4545
return HttpResponse()
4646

4747
response = view_without_decorator(request)
@@ -51,7 +51,7 @@ def view_without_decorator(request: HttpRequest) -> HttpResponse:
5151
assert policy_list == ["default-src 'self'", "img-src foo.com"]
5252

5353
@csp_update({"img-src": ["bar.com", NONCE]})
54-
def view_with_decorator(request: HttpRequest) -> HttpResponse:
54+
def view_with_decorator(request: HttpRequest) -> HttpResponseBase:
5555
return HttpResponse()
5656

5757
response = view_with_decorator(request)
@@ -74,7 +74,7 @@ def view_with_decorator(request: HttpRequest) -> HttpResponse:
7474
def test_csp_update_ro() -> None:
7575
request = RequestFactory().get("/")
7676

77-
def view_without_decorator(request: HttpRequest) -> HttpResponse:
77+
def view_without_decorator(request: HttpRequest) -> HttpResponseBase:
7878
return HttpResponse()
7979

8080
response = view_without_decorator(request)
@@ -84,7 +84,7 @@ def view_without_decorator(request: HttpRequest) -> HttpResponse:
8484
assert policy_list == ["default-src 'self'", "img-src foo.com"]
8585

8686
@csp_update({"img-src": ["bar.com", NONCE]}, REPORT_ONLY=True)
87-
def view_with_decorator(request: HttpRequest) -> HttpResponse:
87+
def view_with_decorator(request: HttpRequest) -> HttpResponseBase:
8888
return HttpResponse()
8989

9090
response = view_with_decorator(request)
@@ -107,7 +107,7 @@ def view_with_decorator(request: HttpRequest) -> HttpResponse:
107107
def test_csp_replace() -> None:
108108
request = RequestFactory().get("/")
109109

110-
def view_without_decorator(request: HttpRequest) -> HttpResponse:
110+
def view_without_decorator(request: HttpRequest) -> HttpResponseBase:
111111
return HttpResponse()
112112

113113
response = view_without_decorator(request)
@@ -117,7 +117,7 @@ def view_without_decorator(request: HttpRequest) -> HttpResponse:
117117
assert policy_list == ["default-src 'self'", "img-src foo.com"]
118118

119119
@csp_replace({"img-src": ["bar.com"]})
120-
def view_with_decorator(request: HttpRequest) -> HttpResponse:
120+
def view_with_decorator(request: HttpRequest) -> HttpResponseBase:
121121
return HttpResponse()
122122

123123
response = view_with_decorator(request)
@@ -134,7 +134,7 @@ def view_with_decorator(request: HttpRequest) -> HttpResponse:
134134
assert policy_list == ["default-src 'self'", "img-src foo.com"]
135135

136136
@csp_replace({"img-src": None})
137-
def view_removing_directive(request: HttpRequest) -> HttpResponse:
137+
def view_removing_directive(request: HttpRequest) -> HttpResponseBase:
138138
return HttpResponse()
139139

140140
response = view_removing_directive(request)
@@ -148,7 +148,7 @@ def view_removing_directive(request: HttpRequest) -> HttpResponse:
148148
def test_csp_replace_ro() -> None:
149149
request = RequestFactory().get("/")
150150

151-
def view_without_decorator(request: HttpRequest) -> HttpResponse:
151+
def view_without_decorator(request: HttpRequest) -> HttpResponseBase:
152152
return HttpResponse()
153153

154154
response = view_without_decorator(request)
@@ -158,7 +158,7 @@ def view_without_decorator(request: HttpRequest) -> HttpResponse:
158158
assert policy_list == ["default-src 'self'", "img-src foo.com"]
159159

160160
@csp_replace({"img-src": ["bar.com"]}, REPORT_ONLY=True)
161-
def view_with_decorator(request: HttpRequest) -> HttpResponse:
161+
def view_with_decorator(request: HttpRequest) -> HttpResponseBase:
162162
return HttpResponse()
163163

164164
response = view_with_decorator(request)
@@ -175,7 +175,7 @@ def view_with_decorator(request: HttpRequest) -> HttpResponse:
175175
assert policy_list == ["default-src 'self'", "img-src foo.com"]
176176

177177
@csp_replace({"img-src": None}, REPORT_ONLY=True)
178-
def view_removing_directive(request: HttpRequest) -> HttpResponse:
178+
def view_removing_directive(request: HttpRequest) -> HttpResponseBase:
179179
return HttpResponse()
180180

181181
response = view_removing_directive(request)
@@ -188,7 +188,7 @@ def view_removing_directive(request: HttpRequest) -> HttpResponse:
188188
def test_csp() -> None:
189189
request = RequestFactory().get("/")
190190

191-
def view_without_decorator(request: HttpRequest) -> HttpResponse:
191+
def view_without_decorator(request: HttpRequest) -> HttpResponseBase:
192192
return HttpResponse()
193193

194194
response = view_without_decorator(request)
@@ -198,7 +198,7 @@ def view_without_decorator(request: HttpRequest) -> HttpResponse:
198198
assert policy_list == ["default-src 'self'"]
199199

200200
@csp({"img-src": ["foo.com"], "font-src": ["bar.com"]})
201-
def view_with_decorator(request: HttpRequest) -> HttpResponse:
201+
def view_with_decorator(request: HttpRequest) -> HttpResponseBase:
202202
return HttpResponse()
203203

204204
response = view_with_decorator(request)
@@ -218,7 +218,7 @@ def view_with_decorator(request: HttpRequest) -> HttpResponse:
218218
def test_csp_ro() -> None:
219219
request = RequestFactory().get("/")
220220

221-
def view_without_decorator(request: HttpRequest) -> HttpResponse:
221+
def view_without_decorator(request: HttpRequest) -> HttpResponseBase:
222222
return HttpResponse()
223223

224224
response = view_without_decorator(request)
@@ -229,7 +229,7 @@ def view_without_decorator(request: HttpRequest) -> HttpResponse:
229229

230230
@csp({"img-src": ["foo.com"], "font-src": ["bar.com"]}, REPORT_ONLY=True)
231231
@csp({}) # CSP with no directives effectively removes the header.
232-
def view_with_decorator(request: HttpRequest) -> HttpResponse:
232+
def view_with_decorator(request: HttpRequest) -> HttpResponseBase:
233233
return HttpResponse()
234234

235235
response = view_with_decorator(request)
@@ -251,7 +251,7 @@ def test_csp_string_values() -> None:
251251
request = RequestFactory().get("/")
252252

253253
@csp({"img-src": "foo.com", "font-src": "bar.com"})
254-
def view_with_decorator(request: HttpRequest) -> HttpResponse:
254+
def view_with_decorator(request: HttpRequest) -> HttpResponseBase:
255255
return HttpResponse()
256256

257257
response = view_with_decorator(request)
@@ -268,7 +268,7 @@ def test_csp_exempt_error() -> None:
268268
with pytest.raises(RuntimeError) as excinfo:
269269
# Ignore type error since we're checking for the exception raised for 3.x syntax
270270
@csp_exempt # type: ignore
271-
def view(request: HttpRequest) -> HttpResponse:
271+
def view(request: HttpRequest) -> HttpResponseBase:
272272
return HttpResponse()
273273

274274
assert "Incompatible `csp_exempt` decorator usage" in str(excinfo.value)
@@ -278,7 +278,7 @@ def test_csp_update_error() -> None:
278278
with pytest.raises(RuntimeError) as excinfo:
279279

280280
@csp_update(IMG_SRC="bar.com")
281-
def view(request: HttpRequest) -> HttpResponse:
281+
def view(request: HttpRequest) -> HttpResponseBase:
282282
return HttpResponse()
283283

284284
assert "Incompatible `csp_update` decorator arguments" in str(excinfo.value)
@@ -288,7 +288,7 @@ def test_csp_replace_error() -> None:
288288
with pytest.raises(RuntimeError) as excinfo:
289289

290290
@csp_replace(IMG_SRC="bar.com")
291-
def view(request: HttpRequest) -> HttpResponse:
291+
def view(request: HttpRequest) -> HttpResponseBase:
292292
return HttpResponse()
293293

294294
assert "Incompatible `csp_replace` decorator arguments" in str(excinfo.value)
@@ -298,7 +298,7 @@ def test_csp_error() -> None:
298298
with pytest.raises(RuntimeError) as excinfo:
299299

300300
@csp(IMG_SRC=["bar.com"])
301-
def view(request: HttpRequest) -> HttpResponse:
301+
def view(request: HttpRequest) -> HttpResponseBase:
302302
return HttpResponse()
303303

304304
assert "Incompatible `csp` decorator arguments" in str(excinfo.value)

0 commit comments

Comments
 (0)