Skip to content

Commit

Permalink
Accept responses with just a status code (Fixes #263)
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelgrinberg committed Nov 10, 2024
1 parent 4eac013 commit c46e429
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 22 deletions.
20 changes: 10 additions & 10 deletions src/microdot/microdot.py
Original file line number Diff line number Diff line change
Expand Up @@ -520,10 +520,8 @@ class Response:
:param body: The body of the response. If a dictionary or list is given,
a JSON formatter is used to generate the body. If a file-like
object or an async generator is given, a streaming response is
used. If a string is given, it is encoded from UTF-8. If an
integer is given and ``status_code`` isn't given, then the
status code is assigned and the body is kept empty. Else, the
body should be a byte sequence.
used. If a string is given, it is encoded from UTF-8. Else,
the body should be a byte sequence.
:param status_code: The numeric HTTP status code of the response. The
default is 200.
:param headers: A dictionary of headers to include in the response.
Expand Down Expand Up @@ -556,14 +554,11 @@ class Response:
#: written to the client. Used to exit WebSocket connections cleanly.
already_handled = None

def __init__(self, body='', status_code=None, headers=None, reason=None):
if body is None and status_code is None:
def __init__(self, body='', status_code=200, headers=None, reason=None):
if body is None and status_code == 200:
body = ''
status_code = 204
elif isinstance(body, int) and status_code is None:
status_code = int(body)
body = ''
self.status_code = status_code or 200
self.status_code = status_code
self.headers = NoCaseDict(headers or {})
self.reason = reason
if isinstance(body, (dict, list)):
Expand Down Expand Up @@ -1374,7 +1369,12 @@ async def dispatch_request(self, req):
if res is None:
res = await invoke_handler(
f, req, **req.url_args)
if isinstance(res, int):
res = '', res
if isinstance(res, tuple):
if isinstance(res[0], int):
res = ('', res[0],
res[1] if len(res) > 1 else {})
body = res[0]
if isinstance(res[1], int):
status_code = res[1]
Expand Down
20 changes: 20 additions & 0 deletions tests/test_microdot.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,14 @@ def four(req):
return '<p>four</p>', 202, \
{'Content-Type': 'text/html; charset=UTF-8'}

@app.route('/status')
def five(req):
return 202

@app.route('/status-headers')
def six(req):
return 202, {'Content-Type': 'text/html; charset=UTF-8'}

client = TestClient(app)

res = self._run(client.get('/body'))
Expand All @@ -299,6 +307,18 @@ def four(req):
'text/html; charset=UTF-8')
self.assertEqual(res.text, '<p>four</p>')

res = self._run(client.get('/status'))
self.assertEqual(res.text, '')
self.assertEqual(res.status_code, 202)
self.assertEqual(res.headers['Content-Type'],
'text/plain; charset=UTF-8')

res = self._run(client.get('/status-headers'))
self.assertEqual(res.text, '')
self.assertEqual(res.status_code, 202)
self.assertEqual(res.headers['Content-Type'],
'text/html; charset=UTF-8')

def test_before_after_request(self):
app = Microdot()

Expand Down
12 changes: 0 additions & 12 deletions tests/test_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,18 +109,6 @@ def test_create_json(self):
fd.response)
self.assertTrue(fd.response.endswith(b'\r\n\r\n[1, "2"]'))

def test_create_status_code(self):
res = Response(202)
self.assertEqual(res.status_code, 202)
self.assertEqual(res.body, b'')
fd = FakeStreamAsync()
self._run(res.write(fd))
self.assertIn(b'HTTP/1.0 202 N/A\r\n', fd.response)
self.assertIn(b'Content-Length: 0\r\n', fd.response)
self.assertIn(b'Content-Type: text/plain; charset=UTF-8\r\n',
fd.response)
self.assertTrue(fd.response.endswith(b'\r\n\r\n'))

def test_create_from_none(self):
res = Response(None)
self.assertEqual(res.status_code, 204)
Expand Down

0 comments on commit c46e429

Please sign in to comment.