Skip to content

Commit

Permalink
looser Content-Type header checking for application/json (#101)
Browse files Browse the repository at this point in the history
  • Loading branch information
keotl committed Dec 22, 2019
1 parent af58570 commit 1066072
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
11 changes: 10 additions & 1 deletion jivago/wsgi/request/json_serialization_filter.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import json
from typing import Optional

from jivago.lang.annotations import Override
from jivago.lang.nullable import Nullable
from jivago.lang.stream import Stream
from jivago.wsgi.filter.filter import Filter
from jivago.wsgi.filter.filter_chain import FilterChain
from jivago.wsgi.request.request import Request
Expand All @@ -11,11 +14,17 @@ class JsonSerializationFilter(Filter):

@Override
def doFilter(self, request: Request, response: Response, chain: FilterChain):
if request.headers['Content-Type'] == 'application/json' and len(request.body) > 0:
if is_application_json(request.headers['Content-Type']) and len(request.body) > 0:
request.body = json.loads(request.body)

chain.doFilter(request, response)

if isinstance(response.body, dict) or isinstance(response.body, list):
response.body = json.dumps(response.body)
response.headers['Content-Type'] = 'application/json'


def is_application_json(content_type: Optional[str]) -> bool:
return Nullable(content_type) \
.map(lambda x: "application/json" in x) \
.orElse(False)
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,27 @@ def test_givenSerializable_whenApplyingFilter_thenSetContentTypeToApplicationJso
def test_givenApplicationJsonHeaderWithEmptyBody_whenApplyingFilter_thenDoNotDeserializeTheEmptyString(self):
request = RequestBuilder().headers({"Content-Type": "application/json"}).body("").method("POST").build()

self.filter.doFilter(A_REQUEST, ResponseBuilder().build(), self.filterChainMock)
self.filter.doFilter(request, ResponseBuilder().build(), self.filterChainMock)

self.assertEqual("", request.body)

def test_givenMultipleContentTypeDirectives_whenApplyingFilter_thenMatchOnMediaType(self):
"""https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type"""
request = RequestBuilder() \
.headers({"Content-Type": "application/json; charset=utf-8"}) \
.body('{"name": "bar"}') \
.build()

self.filter.doFilter(request, ResponseBuilder().build(), self.filterChainMock)

self.assertEqual({"name": "bar"}, request.body)

def test_givenTrailingSemiColonInContentType_whenApplyingFilter_thenMatchAnyway(self):
request = RequestBuilder() \
.headers({"Content-Type": "application/json; "}) \
.body('{"name": "bar"}') \
.build()

self.filter.doFilter(request, ResponseBuilder().build(), self.filterChainMock)

self.assertEqual({"name": "bar"}, request.body)

0 comments on commit 1066072

Please sign in to comment.