uhttp-server 2.3.0__tar.gz → 2.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/PKG-INFO +1 -1
  2. uhttp_server-2.3.1/tests/test_respond_falsy.py +106 -0
  3. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/uhttp/server.py +15 -2
  4. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/uhttp_server.egg-info/PKG-INFO +1 -1
  5. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/uhttp_server.egg-info/SOURCES.txt +1 -0
  6. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/.github/workflows/micropython.yml +0 -0
  7. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/.github/workflows/publish.yml +0 -0
  8. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/.github/workflows/tests.yml +0 -0
  9. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/.gitignore +0 -0
  10. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/LICENSE +0 -0
  11. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/README.md +0 -0
  12. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/examples/client_with_server.py +0 -0
  13. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/examples/http_to_https_redirect.py +0 -0
  14. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/examples/https_server.py +0 -0
  15. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/pyproject.toml +0 -0
  16. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/setup.cfg +0 -0
  17. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/__init__.py +0 -0
  18. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_100_continue.py +0 -0
  19. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_concurrent_connections.py +0 -0
  20. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_content_length_security.py +0 -0
  21. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_data_parsing.py +0 -0
  22. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_double_response.py +0 -0
  23. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_eagain.py +0 -0
  24. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_error_handling.py +0 -0
  25. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_event_mode.py +0 -0
  26. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_ipv6.py +0 -0
  27. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_keepalive.py +0 -0
  28. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_keepalive_basic.py +0 -0
  29. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_keepalive_http10.py +0 -0
  30. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_keepalive_limits.py +0 -0
  31. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_keepalive_simple.py +0 -0
  32. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_mpy_integration.py +0 -0
  33. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_mpy_websocket.py +0 -0
  34. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_multipart.py +0 -0
  35. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_pipelining.py +0 -0
  36. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_respond_file.py +0 -0
  37. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_respond_file_race.py +0 -0
  38. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_ssl.py +0 -0
  39. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_utils.py +0 -0
  40. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_websocket.py +0 -0
  41. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/tests/test_websocket_utils.py +0 -0
  42. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/uhttp_server.egg-info/dependency_links.txt +0 -0
  43. {uhttp_server-2.3.0 → uhttp_server-2.3.1}/uhttp_server.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: uhttp-server
3
- Version: 2.3.0
3
+ Version: 2.3.1
4
4
  Summary: Micro HTTP server for Python and MicroPython
5
5
  Author-email: Pavel Revak <pavelrevak@gmail.com>
6
6
  License: MIT
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Test responding with falsy values (empty list, empty dict, 0, empty string, empty bytes)
4
+ """
5
+ import unittest
6
+ import socket
7
+ import time
8
+ import threading
9
+ import json
10
+ from uhttp import server as uhttp_server
11
+
12
+
13
+ class TestRespondFalsy(unittest.TestCase):
14
+ """Test that respond() correctly handles falsy but valid data values"""
15
+
16
+ server = None
17
+ server_thread = None
18
+ response_data = None
19
+ PORT = 9997
20
+
21
+ @classmethod
22
+ def setUpClass(cls):
23
+ cls.server = uhttp_server.HttpServer(port=cls.PORT)
24
+
25
+ def run_server():
26
+ try:
27
+ while cls.server:
28
+ client = cls.server.wait(timeout=0.1)
29
+ if client:
30
+ client.respond(cls.response_data)
31
+ except Exception:
32
+ pass
33
+
34
+ cls.server_thread = threading.Thread(target=run_server, daemon=True)
35
+ cls.server_thread.start()
36
+ time.sleep(0.5)
37
+
38
+ @classmethod
39
+ def tearDownClass(cls):
40
+ if cls.server:
41
+ cls.server.close()
42
+ cls.server = None
43
+
44
+ def get_response(self):
45
+ """Send GET and return (headers_str, body_bytes)"""
46
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
47
+ sock.settimeout(2.0)
48
+ sock.connect(('localhost', self.PORT))
49
+ sock.sendall(b"GET / HTTP/1.0\r\nHost: localhost\r\n\r\n")
50
+ response = b""
51
+ while True:
52
+ chunk = sock.recv(4096)
53
+ if not chunk:
54
+ break
55
+ response += chunk
56
+ sock.close()
57
+ parts = response.split(b"\r\n\r\n", 1)
58
+ headers = parts[0].decode()
59
+ body = parts[1] if len(parts) > 1 else b""
60
+ return headers, body
61
+
62
+ def test_respond_empty_list(self):
63
+ """respond([]) should return JSON '[]'"""
64
+ TestRespondFalsy.response_data = []
65
+ headers, body = self.get_response()
66
+ self.assertIn('200', headers)
67
+ self.assertEqual(json.loads(body), [])
68
+
69
+ def test_respond_empty_dict(self):
70
+ """respond({}) should return JSON '{}'"""
71
+ TestRespondFalsy.response_data = {}
72
+ headers, body = self.get_response()
73
+ self.assertIn('200', headers)
74
+ self.assertEqual(json.loads(body), {})
75
+
76
+ def test_respond_zero(self):
77
+ """respond(0) should return JSON '0'"""
78
+ TestRespondFalsy.response_data = 0
79
+ headers, body = self.get_response()
80
+ self.assertIn('200', headers)
81
+ self.assertEqual(json.loads(body), 0)
82
+
83
+ def test_respond_empty_string(self):
84
+ """respond('') should return empty body"""
85
+ TestRespondFalsy.response_data = ''
86
+ headers, body = self.get_response()
87
+ self.assertIn('200', headers)
88
+ self.assertEqual(body, b'')
89
+
90
+ def test_respond_empty_bytes(self):
91
+ """respond(b'') should return empty body"""
92
+ TestRespondFalsy.response_data = b''
93
+ headers, body = self.get_response()
94
+ self.assertIn('200', headers)
95
+ self.assertEqual(body, b'')
96
+
97
+ def test_respond_none(self):
98
+ """respond(None) should return no body"""
99
+ TestRespondFalsy.response_data = None
100
+ headers, body = self.get_response()
101
+ self.assertIn('200', headers)
102
+ self.assertEqual(body, b'')
103
+
104
+
105
+ if __name__ == '__main__':
106
+ unittest.main()
@@ -60,6 +60,19 @@ CONTENT_TYPE_MAP = {
60
60
  'webp': 'image/webp',
61
61
  'ico': 'image/x-icon',
62
62
  'bmp': 'image/bmp',
63
+ 'js': 'application/javascript',
64
+ 'css': 'text/css',
65
+ 'json': 'application/json',
66
+ 'xml': 'text/xml',
67
+ 'txt': 'text/plain',
68
+ 'woff': 'font/woff',
69
+ 'woff2': 'font/woff2',
70
+ 'ttf': 'font/ttf',
71
+ 'mp3': 'audio/mpeg',
72
+ 'mp4': 'video/mp4',
73
+ 'wav': 'audio/wav',
74
+ 'pdf': 'application/pdf',
75
+ 'zip': 'application/zip',
63
76
  }
64
77
  METHODS = (
65
78
  'CONNECT', 'DELETE', 'GET', 'HEAD', 'OPTIONS', 'PATCH', 'POST',
@@ -1447,12 +1460,12 @@ class HttpConnection(_WsFrameMixin):
1447
1460
  if self._socket is None:
1448
1461
  return
1449
1462
  headers = self._prepare_response(headers)
1450
- if data:
1463
+ if data is not None:
1451
1464
  data = encode_response_data(headers, data)
1452
1465
 
1453
1466
  header = self._build_response_header(status, headers=headers, cookies=cookies)
1454
1467
  try:
1455
- if data:
1468
+ if data is not None:
1456
1469
  header_bytes = header.encode('ascii') if isinstance(header, str) else header
1457
1470
  self._send(header_bytes + data)
1458
1471
  else:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: uhttp-server
3
- Version: 2.3.0
3
+ Version: 2.3.1
4
4
  Summary: Micro HTTP server for Python and MicroPython
5
5
  Author-email: Pavel Revak <pavelrevak@gmail.com>
6
6
  License: MIT
@@ -27,6 +27,7 @@ tests/test_mpy_integration.py
27
27
  tests/test_mpy_websocket.py
28
28
  tests/test_multipart.py
29
29
  tests/test_pipelining.py
30
+ tests/test_respond_falsy.py
30
31
  tests/test_respond_file.py
31
32
  tests/test_respond_file_race.py
32
33
  tests/test_ssl.py
File without changes
File without changes
File without changes
File without changes