uhttp-server 2.3.2__tar.gz → 2.3.4__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.
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/PKG-INFO +15 -8
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/README.md +14 -7
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_keepalive_simple.py +4 -4
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/uhttp/server.py +5 -1
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/uhttp_server.egg-info/PKG-INFO +15 -8
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/.github/workflows/micropython.yml +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/.github/workflows/publish.yml +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/.github/workflows/tests.yml +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/.gitignore +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/LICENSE +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/examples/client_with_server.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/examples/http_to_https_redirect.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/examples/https_server.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/pyproject.toml +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/setup.cfg +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/__init__.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_100_continue.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_concurrent_connections.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_content_length_security.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_data_parsing.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_double_response.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_eagain.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_error_handling.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_event_mode.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_ipv6.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_keepalive.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_keepalive_basic.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_keepalive_http10.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_keepalive_limits.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_mpy_integration.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_mpy_websocket.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_multipart.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_pipelining.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_respond_falsy.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_respond_file.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_respond_file_race.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_ssl.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_timeout_during_response.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_utils.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_websocket.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/tests/test_websocket_utils.py +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/uhttp_server.egg-info/SOURCES.txt +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/uhttp_server.egg-info/dependency_links.txt +0 -0
- {uhttp_server-2.3.2 → uhttp_server-2.3.4}/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.
|
|
3
|
+
Version: 2.3.4
|
|
4
4
|
Summary: Micro HTTP server for Python and MicroPython
|
|
5
5
|
Author-email: Pavel Revak <pavelrevak@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -480,6 +480,8 @@ Parameters:
|
|
|
480
480
|
|
|
481
481
|
uHTTP supports WebSocket connections (RFC 6455) in both event mode and non-event mode.
|
|
482
482
|
|
|
483
|
+
**Important:** When using `process_events()` with external select loop, `event_mode=True` is required for WebSocket support.
|
|
484
|
+
|
|
483
485
|
### Event Mode (non-blocking, multiple connections)
|
|
484
486
|
|
|
485
487
|
```python
|
|
@@ -504,17 +506,20 @@ while True:
|
|
|
504
506
|
client.respond({'status': 'ok'})
|
|
505
507
|
|
|
506
508
|
elif client.event == EVENT_WS_MESSAGE:
|
|
507
|
-
|
|
508
|
-
client.
|
|
509
|
+
data = client.read_buffer() # bytes
|
|
510
|
+
if client.ws_is_text:
|
|
511
|
+
client.ws_send(data.decode('utf-8')) # echo as text
|
|
512
|
+
else:
|
|
513
|
+
client.ws_send(data) # echo as binary
|
|
509
514
|
|
|
510
515
|
elif client.event == EVENT_WS_CHUNK_FIRST:
|
|
511
|
-
client.context = {'chunks': [client.
|
|
516
|
+
client.context = {'chunks': [client.read_buffer()]}
|
|
512
517
|
|
|
513
518
|
elif client.event == EVENT_WS_CHUNK_NEXT:
|
|
514
|
-
client.context['chunks'].append(client.
|
|
519
|
+
client.context['chunks'].append(client.read_buffer())
|
|
515
520
|
|
|
516
521
|
elif client.event == EVENT_WS_CHUNK_LAST:
|
|
517
|
-
client.context['chunks'].append(client.
|
|
522
|
+
client.context['chunks'].append(client.read_buffer())
|
|
518
523
|
# process all chunks...
|
|
519
524
|
client.ws_send('received')
|
|
520
525
|
|
|
@@ -549,10 +554,12 @@ while True:
|
|
|
549
554
|
**HttpConnection properties:**
|
|
550
555
|
- `is_websocket_request` - True if request is a WebSocket upgrade
|
|
551
556
|
- `is_websocket` - True if connection is in WebSocket mode
|
|
552
|
-
- `
|
|
557
|
+
- `ws_is_text` - True if current message is text frame (vs binary)
|
|
558
|
+
- `ws_message` - Ping/close payload (only for `EVENT_WS_PING` and `EVENT_WS_CLOSE`)
|
|
553
559
|
|
|
554
560
|
**HttpConnection methods (event mode):**
|
|
555
561
|
- `accept_websocket()` - Accept upgrade, switch to WebSocket mode
|
|
562
|
+
- `read_buffer()` - Read message data (returns bytes, use `ws_is_text` to check type)
|
|
556
563
|
- `ws_send(data)` - Send message (str → text frame, bytes → binary frame)
|
|
557
564
|
- `ws_ping(data=b'')` - Send ping frame
|
|
558
565
|
- `ws_close(code=1000, reason='')` - Close WebSocket connection
|
|
@@ -566,7 +573,7 @@ while True:
|
|
|
566
573
|
|
|
567
574
|
### Large Message Chunking
|
|
568
575
|
|
|
569
|
-
Messages larger than `MAX_WS_MESSAGE_LENGTH` (default 64KB, configurable via `max_ws_message_length` kwarg) are delivered in chunks via `EVENT_WS_CHUNK_FIRST`, `EVENT_WS_CHUNK_NEXT`, `EVENT_WS_CHUNK_LAST` events.
|
|
576
|
+
Messages larger than `MAX_WS_MESSAGE_LENGTH` (default 64KB, configurable via `max_ws_message_length` kwarg) are delivered in chunks via `EVENT_WS_CHUNK_FIRST`, `EVENT_WS_CHUNK_NEXT`, `EVENT_WS_CHUNK_LAST` events. Read chunk data with `read_buffer()`, check frame type with `ws_is_text`.
|
|
570
577
|
|
|
571
578
|
In non-event mode, messages exceeding the limit close the connection with status 1009.
|
|
572
579
|
|
|
@@ -463,6 +463,8 @@ Parameters:
|
|
|
463
463
|
|
|
464
464
|
uHTTP supports WebSocket connections (RFC 6455) in both event mode and non-event mode.
|
|
465
465
|
|
|
466
|
+
**Important:** When using `process_events()` with external select loop, `event_mode=True` is required for WebSocket support.
|
|
467
|
+
|
|
466
468
|
### Event Mode (non-blocking, multiple connections)
|
|
467
469
|
|
|
468
470
|
```python
|
|
@@ -487,17 +489,20 @@ while True:
|
|
|
487
489
|
client.respond({'status': 'ok'})
|
|
488
490
|
|
|
489
491
|
elif client.event == EVENT_WS_MESSAGE:
|
|
490
|
-
|
|
491
|
-
client.
|
|
492
|
+
data = client.read_buffer() # bytes
|
|
493
|
+
if client.ws_is_text:
|
|
494
|
+
client.ws_send(data.decode('utf-8')) # echo as text
|
|
495
|
+
else:
|
|
496
|
+
client.ws_send(data) # echo as binary
|
|
492
497
|
|
|
493
498
|
elif client.event == EVENT_WS_CHUNK_FIRST:
|
|
494
|
-
client.context = {'chunks': [client.
|
|
499
|
+
client.context = {'chunks': [client.read_buffer()]}
|
|
495
500
|
|
|
496
501
|
elif client.event == EVENT_WS_CHUNK_NEXT:
|
|
497
|
-
client.context['chunks'].append(client.
|
|
502
|
+
client.context['chunks'].append(client.read_buffer())
|
|
498
503
|
|
|
499
504
|
elif client.event == EVENT_WS_CHUNK_LAST:
|
|
500
|
-
client.context['chunks'].append(client.
|
|
505
|
+
client.context['chunks'].append(client.read_buffer())
|
|
501
506
|
# process all chunks...
|
|
502
507
|
client.ws_send('received')
|
|
503
508
|
|
|
@@ -532,10 +537,12 @@ while True:
|
|
|
532
537
|
**HttpConnection properties:**
|
|
533
538
|
- `is_websocket_request` - True if request is a WebSocket upgrade
|
|
534
539
|
- `is_websocket` - True if connection is in WebSocket mode
|
|
535
|
-
- `
|
|
540
|
+
- `ws_is_text` - True if current message is text frame (vs binary)
|
|
541
|
+
- `ws_message` - Ping/close payload (only for `EVENT_WS_PING` and `EVENT_WS_CLOSE`)
|
|
536
542
|
|
|
537
543
|
**HttpConnection methods (event mode):**
|
|
538
544
|
- `accept_websocket()` - Accept upgrade, switch to WebSocket mode
|
|
545
|
+
- `read_buffer()` - Read message data (returns bytes, use `ws_is_text` to check type)
|
|
539
546
|
- `ws_send(data)` - Send message (str → text frame, bytes → binary frame)
|
|
540
547
|
- `ws_ping(data=b'')` - Send ping frame
|
|
541
548
|
- `ws_close(code=1000, reason='')` - Close WebSocket connection
|
|
@@ -549,7 +556,7 @@ while True:
|
|
|
549
556
|
|
|
550
557
|
### Large Message Chunking
|
|
551
558
|
|
|
552
|
-
Messages larger than `MAX_WS_MESSAGE_LENGTH` (default 64KB, configurable via `max_ws_message_length` kwarg) are delivered in chunks via `EVENT_WS_CHUNK_FIRST`, `EVENT_WS_CHUNK_NEXT`, `EVENT_WS_CHUNK_LAST` events.
|
|
559
|
+
Messages larger than `MAX_WS_MESSAGE_LENGTH` (default 64KB, configurable via `max_ws_message_length` kwarg) are delivered in chunks via `EVENT_WS_CHUNK_FIRST`, `EVENT_WS_CHUNK_NEXT`, `EVENT_WS_CHUNK_LAST` events. Read chunk data with `read_buffer()`, check frame type with `ws_is_text`.
|
|
553
560
|
|
|
554
561
|
In non-event mode, messages exceeding the limit close the connection with status 1009.
|
|
555
562
|
|
|
@@ -58,7 +58,7 @@ class TestKeepAliveSimple(unittest.TestCase):
|
|
|
58
58
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
59
59
|
try:
|
|
60
60
|
sock.connect(('localhost', self.PORT))
|
|
61
|
-
sock.settimeout(0
|
|
61
|
+
sock.settimeout(2.0)
|
|
62
62
|
|
|
63
63
|
responses = []
|
|
64
64
|
|
|
@@ -119,7 +119,7 @@ class TestKeepAliveSimple(unittest.TestCase):
|
|
|
119
119
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
120
120
|
try:
|
|
121
121
|
sock.connect(('localhost', self.PORT))
|
|
122
|
-
sock.settimeout(0
|
|
122
|
+
sock.settimeout(2.0)
|
|
123
123
|
|
|
124
124
|
request = b"GET /test HTTP/1.1\r\nHost: localhost\r\n\r\n"
|
|
125
125
|
sock.send(request)
|
|
@@ -167,7 +167,7 @@ class TestKeepAliveSimple(unittest.TestCase):
|
|
|
167
167
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
168
168
|
try:
|
|
169
169
|
sock.connect(('localhost', self.PORT))
|
|
170
|
-
sock.settimeout(0
|
|
170
|
+
sock.settimeout(2.0)
|
|
171
171
|
|
|
172
172
|
request = b"GET /test HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n"
|
|
173
173
|
sock.send(request)
|
|
@@ -197,7 +197,7 @@ class TestKeepAliveSimple(unittest.TestCase):
|
|
|
197
197
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
198
198
|
try:
|
|
199
199
|
sock.connect(('localhost', self.PORT))
|
|
200
|
-
sock.settimeout(0
|
|
200
|
+
sock.settimeout(2.0)
|
|
201
201
|
|
|
202
202
|
request_numbers = []
|
|
203
203
|
|
|
@@ -128,6 +128,7 @@ STATUS_CODES = {
|
|
|
128
128
|
405: "Method Not Allowed",
|
|
129
129
|
406: "Not Acceptable",
|
|
130
130
|
408: "Request Timeout",
|
|
131
|
+
409: "Conflict",
|
|
131
132
|
410: "Gone",
|
|
132
133
|
411: "Length Required",
|
|
133
134
|
413: "Payload Too Large",
|
|
@@ -781,7 +782,10 @@ class HttpConnection(_WsFrameMixin):
|
|
|
781
782
|
|
|
782
783
|
@property
|
|
783
784
|
def data(self):
|
|
784
|
-
"""Content data"""
|
|
785
|
+
"""Content data (parsed JSON/form or raw bytes)"""
|
|
786
|
+
# Lazy parse buffer on EVENT_COMPLETE (after accept_body)
|
|
787
|
+
if self._data is None and self._event == EVENT_COMPLETE and self._buffer:
|
|
788
|
+
self._process_data()
|
|
785
789
|
return self._data
|
|
786
790
|
|
|
787
791
|
@property
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: uhttp-server
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.4
|
|
4
4
|
Summary: Micro HTTP server for Python and MicroPython
|
|
5
5
|
Author-email: Pavel Revak <pavelrevak@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -480,6 +480,8 @@ Parameters:
|
|
|
480
480
|
|
|
481
481
|
uHTTP supports WebSocket connections (RFC 6455) in both event mode and non-event mode.
|
|
482
482
|
|
|
483
|
+
**Important:** When using `process_events()` with external select loop, `event_mode=True` is required for WebSocket support.
|
|
484
|
+
|
|
483
485
|
### Event Mode (non-blocking, multiple connections)
|
|
484
486
|
|
|
485
487
|
```python
|
|
@@ -504,17 +506,20 @@ while True:
|
|
|
504
506
|
client.respond({'status': 'ok'})
|
|
505
507
|
|
|
506
508
|
elif client.event == EVENT_WS_MESSAGE:
|
|
507
|
-
|
|
508
|
-
client.
|
|
509
|
+
data = client.read_buffer() # bytes
|
|
510
|
+
if client.ws_is_text:
|
|
511
|
+
client.ws_send(data.decode('utf-8')) # echo as text
|
|
512
|
+
else:
|
|
513
|
+
client.ws_send(data) # echo as binary
|
|
509
514
|
|
|
510
515
|
elif client.event == EVENT_WS_CHUNK_FIRST:
|
|
511
|
-
client.context = {'chunks': [client.
|
|
516
|
+
client.context = {'chunks': [client.read_buffer()]}
|
|
512
517
|
|
|
513
518
|
elif client.event == EVENT_WS_CHUNK_NEXT:
|
|
514
|
-
client.context['chunks'].append(client.
|
|
519
|
+
client.context['chunks'].append(client.read_buffer())
|
|
515
520
|
|
|
516
521
|
elif client.event == EVENT_WS_CHUNK_LAST:
|
|
517
|
-
client.context['chunks'].append(client.
|
|
522
|
+
client.context['chunks'].append(client.read_buffer())
|
|
518
523
|
# process all chunks...
|
|
519
524
|
client.ws_send('received')
|
|
520
525
|
|
|
@@ -549,10 +554,12 @@ while True:
|
|
|
549
554
|
**HttpConnection properties:**
|
|
550
555
|
- `is_websocket_request` - True if request is a WebSocket upgrade
|
|
551
556
|
- `is_websocket` - True if connection is in WebSocket mode
|
|
552
|
-
- `
|
|
557
|
+
- `ws_is_text` - True if current message is text frame (vs binary)
|
|
558
|
+
- `ws_message` - Ping/close payload (only for `EVENT_WS_PING` and `EVENT_WS_CLOSE`)
|
|
553
559
|
|
|
554
560
|
**HttpConnection methods (event mode):**
|
|
555
561
|
- `accept_websocket()` - Accept upgrade, switch to WebSocket mode
|
|
562
|
+
- `read_buffer()` - Read message data (returns bytes, use `ws_is_text` to check type)
|
|
556
563
|
- `ws_send(data)` - Send message (str → text frame, bytes → binary frame)
|
|
557
564
|
- `ws_ping(data=b'')` - Send ping frame
|
|
558
565
|
- `ws_close(code=1000, reason='')` - Close WebSocket connection
|
|
@@ -566,7 +573,7 @@ while True:
|
|
|
566
573
|
|
|
567
574
|
### Large Message Chunking
|
|
568
575
|
|
|
569
|
-
Messages larger than `MAX_WS_MESSAGE_LENGTH` (default 64KB, configurable via `max_ws_message_length` kwarg) are delivered in chunks via `EVENT_WS_CHUNK_FIRST`, `EVENT_WS_CHUNK_NEXT`, `EVENT_WS_CHUNK_LAST` events.
|
|
576
|
+
Messages larger than `MAX_WS_MESSAGE_LENGTH` (default 64KB, configurable via `max_ws_message_length` kwarg) are delivered in chunks via `EVENT_WS_CHUNK_FIRST`, `EVENT_WS_CHUNK_NEXT`, `EVENT_WS_CHUNK_LAST` events. Read chunk data with `read_buffer()`, check frame type with `ws_is_text`.
|
|
570
577
|
|
|
571
578
|
In non-event mode, messages exceeding the limit close the connection with status 1009.
|
|
572
579
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|