Skip to content

Commit c3be52e

Browse files
rdallmandenismakogon
authored andcommitted
properly grab content type (#90)
* properly grab content type we're not using a case insensitive dict so these end up overlapping. this now grabs the right content type out of the user headers before creating the real http headers, at least, but we should probably use a case insensitive dict for these things as this has been a real pain. this also changes the default to be "text/plain" instead of sending in Content-Type: None is the user does not set this particular header. Now I see application/json being set properly without None or another value in content type, so this ought to work. * add case insensitive dict to async_http lib removes any higher level setting of the content type, since the async_http lib itself will handle this and only at that level do we have case insensitive header checks. it wasn't worth trying to change all of async_http header getting to use lower case.
1 parent ef13220 commit c3be52e

4 files changed

Lines changed: 56 additions & 11 deletions

File tree

fdk/async_http/app.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,7 @@ async def handle_request(self, request, write_callback, stream_callback):
8080
headers = res.headers
8181
status = res.status
8282
response = HTTPResponse(
83-
body=body, status=status,
84-
headers=headers,
85-
content_type=headers.get("Content-Type")
83+
body=body, status=status, headers=headers,
8684
)
8785
except CancelledError:
8886
response = None

fdk/async_http/response.py

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,57 @@ def get_headers(
131131
)
132132

133133

134+
# CaseInsensitiveDict for headers. TODO should we let users use it in fdk too?
135+
class CaseInsensitiveDict(dict):
136+
@classmethod
137+
def _k(cls, key):
138+
return key.lower() if isinstance(key, str) else key
139+
140+
def __init__(self, *args, **kwargs):
141+
super(CaseInsensitiveDict, self).__init__(*args, **kwargs)
142+
self._convert_keys()
143+
144+
def __getitem__(self, key):
145+
return super(CaseInsensitiveDict, self).__getitem__(
146+
self.__class__._k(key))
147+
148+
def __setitem__(self, key, value):
149+
super(CaseInsensitiveDict, self).__setitem__(
150+
self.__class__._k(key), value)
151+
152+
def __delitem__(self, key):
153+
return super(CaseInsensitiveDict, self).__delitem__(
154+
self.__class__._k(key))
155+
156+
def __contains__(self, key):
157+
return super(CaseInsensitiveDict, self).__contains__(
158+
self.__class__._k(key))
159+
160+
# DEPRECATED
161+
# def has_key(self, key):
162+
163+
def pop(self, key, *args, **kwargs):
164+
return super(CaseInsensitiveDict, self).pop(
165+
self.__class__._k(key), *args, **kwargs)
166+
167+
def get(self, key, *args, **kwargs):
168+
return super(CaseInsensitiveDict, self).get(
169+
self.__class__._k(key), *args, **kwargs)
170+
171+
def setdefault(self, key, *args, **kwargs):
172+
return super(CaseInsensitiveDict, self).setdefault(
173+
self.__class__._k(key), *args, **kwargs)
174+
175+
def update(self, E={}, **F):
176+
super(CaseInsensitiveDict, self).update(self.__class__(E))
177+
super(CaseInsensitiveDict, self).update(self.__class__(**F))
178+
179+
def _convert_keys(self):
180+
for k in list(self.keys()):
181+
v = super(CaseInsensitiveDict, self).pop(k)
182+
self.__setitem__(k, v)
183+
184+
134185
class HTTPResponse(BaseHTTPResponse):
135186
__slots__ = ("body", "status", "content_type", "headers", "_cookies")
136187

@@ -150,7 +201,7 @@ def __init__(
150201
self.body = body_bytes
151202

152203
self.status = status
153-
self.headers = dict(headers or {})
204+
self.headers = CaseInsensitiveDict(headers or {})
154205
self._cookies = None
155206

156207
def output(self, version="1.1", keep_alive=False, keep_alive_timeout=None):

fdk/runner.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import types
2222

2323
from fdk import context
24-
from fdk import constants
2524
from fdk import customer_code
2625
from fdk import errors
2726
from fdk import log
@@ -91,11 +90,6 @@ async def handle_request(handler_code, format_def, **kwargs):
9190

9291
headers = ctx.GetResponseHeaders()
9392
log.log("response headers obtained")
94-
response_content_type = headers.get(
95-
constants.CONTENT_TYPE, "text/plain"
96-
)
97-
headers[constants.CONTENT_TYPE] = response_content_type
98-
9993
return response.Response(
10094
ctx, response_data=response_data,
10195
headers=headers, status_code=200)

fdk/tests/test_http_stream.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ async def test_override_content_type():
3232

3333
assert 200 == status
3434
assert "OK" == content
35-
assert "application/json" in headers.get("content-type")
35+
assert headers.get("content-type") == "application/json"
36+
# we've had issues with 'Content-Type: None' slipping in
37+
assert headers.get("Content-Type") is None
3638
assert version.VERSION == headers.get(constants.FN_FDK_VERSION)
3739

3840

0 commit comments

Comments
 (0)