omserv 0.0.0.dev395__tar.gz → 0.0.0.dev497__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.
- {omserv-0.0.0.dev395/omserv.egg-info → omserv-0.0.0.dev497}/PKG-INFO +6 -6
- omserv-0.0.0.dev395/omserv/.manifests.json → omserv-0.0.0.dev497/omserv/.omlish-manifests.json +3 -3
- omserv-0.0.0.dev497/omserv/README.md +9 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/__about__.py +2 -2
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/apps/markers.py +1 -1
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/apps/routes.py +3 -3
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/apps/sessions.py +2 -2
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/apps/templates.py +4 -2
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/nginx/build.py +1 -1
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/nginx/logs.py +3 -3
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/nodes/registry.py +2 -2
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/nodes/sql.py +2 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/debug.py +2 -2
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/events.py +5 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/lifespans.py +4 -2
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/listener.py +4 -3
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/protocols/h11.py +2 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/protocols/h2.py +16 -8
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/protocols/protocols.py +1 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/protocols/types.py +3 -1
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/server.py +2 -2
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/streams/httpstream.py +40 -4
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/streams/utils.py +3 -2
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/streams/wsstream.py +11 -4
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/taskspawner.py +3 -2
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/types.py +1 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/workercontext.py +2 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497/omserv.egg-info}/PKG-INFO +6 -6
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv.egg-info/SOURCES.txt +2 -1
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv.egg-info/requires.txt +5 -5
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/pyproject.toml +11 -7
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/LICENSE +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/MANIFEST.in +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/README.md +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/__init__.py +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/apps/__init__.py +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/apps/base.py +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/apps/inject.py +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/nginx/__init__.py +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/nginx/patches/__init__.py +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/nginx/patches/nginx-1.28.0_http_status.patch +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/nginx/stubstatus.py +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/nodes/__init__.py +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/nodes/models.py +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/LICENSE +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/__init__.py +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/config.py +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/default.py +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/headers.py +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/inject.py +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/multiprocess.py +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/protocols/__init__.py +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/resources/__init__.py +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/resources/favicon.ico +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/sockets.py +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/ssl.py +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/server/streams/__init__.py +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv.egg-info/dependency_links.txt +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv.egg-info/entry_points.txt +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv.egg-info/top_level.txt +0 -0
- {omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: omserv
|
|
3
|
-
Version: 0.0.0.
|
|
3
|
+
Version: 0.0.0.dev497
|
|
4
4
|
Summary: omserv
|
|
5
5
|
Author: wrmsr
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -14,18 +14,18 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
14
14
|
Requires-Python: >=3.13
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
16
16
|
License-File: LICENSE
|
|
17
|
-
Requires-Dist: omlish==0.0.0.
|
|
17
|
+
Requires-Dist: omlish==0.0.0.dev497
|
|
18
18
|
Provides-Extra: all
|
|
19
19
|
Requires-Dist: h11~=0.16; extra == "all"
|
|
20
|
-
Requires-Dist: h2~=4.
|
|
20
|
+
Requires-Dist: h2~=4.3; extra == "all"
|
|
21
21
|
Requires-Dist: priority~=2.0; extra == "all"
|
|
22
|
-
Requires-Dist: wsproto~=1.
|
|
22
|
+
Requires-Dist: wsproto~=1.3; extra == "all"
|
|
23
23
|
Requires-Dist: jinja2~=3.1; extra == "all"
|
|
24
24
|
Provides-Extra: server
|
|
25
25
|
Requires-Dist: h11~=0.16; extra == "server"
|
|
26
|
-
Requires-Dist: h2~=4.
|
|
26
|
+
Requires-Dist: h2~=4.3; extra == "server"
|
|
27
27
|
Requires-Dist: priority~=2.0; extra == "server"
|
|
28
|
-
Requires-Dist: wsproto~=1.
|
|
28
|
+
Requires-Dist: wsproto~=1.3; extra == "server"
|
|
29
29
|
Provides-Extra: templates
|
|
30
30
|
Requires-Dist: jinja2~=3.1; extra == "templates"
|
|
31
31
|
Dynamic: license-file
|
omserv-0.0.0.dev395/omserv/.manifests.json → omserv-0.0.0.dev497/omserv/.omlish-manifests.json
RENAMED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
"file": "omserv/nginx/logs.py",
|
|
6
6
|
"line": 68,
|
|
7
7
|
"value": {
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
8
|
+
"!omdev.cli.types.CliModule": {
|
|
9
|
+
"name": "nginxlogs",
|
|
10
|
+
"module": "omserv.nginx.logs"
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Overview
|
|
2
|
+
|
|
3
|
+
Request serving code.
|
|
4
|
+
|
|
5
|
+
# Notable packages
|
|
6
|
+
|
|
7
|
+
- **[server](https://github.com/wrmsr/omlish/blob/master/omserv/server)** - Production web server based on
|
|
8
|
+
[hypercorn](https://github.com/pgjones/hypercorn). Converted to anyio, but still being refined and integrated with the
|
|
9
|
+
codebase.
|
|
@@ -27,7 +27,7 @@ def append_app_marker(obj: T, *markers: AppMarker) -> T:
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
def get_app_markers(obj: ta.Any) -> ta.Sequence[AppMarker]:
|
|
30
|
-
return
|
|
30
|
+
return get_object_metadata(obj, type=AppMarker)
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
##
|
|
@@ -5,13 +5,13 @@ TODO:
|
|
|
5
5
|
"""
|
|
6
6
|
import contextlib
|
|
7
7
|
import dataclasses as dc
|
|
8
|
-
import logging
|
|
9
8
|
import re
|
|
10
9
|
import typing as ta
|
|
11
10
|
|
|
12
11
|
from omlish import check
|
|
13
12
|
from omlish import lang
|
|
14
13
|
from omlish.http import asgi
|
|
14
|
+
from omlish.logs import all as logs
|
|
15
15
|
|
|
16
16
|
from .base import BASE_SERVER_URL
|
|
17
17
|
from .base import SCOPE
|
|
@@ -49,7 +49,7 @@ KNOWN_METHODS: tuple[str, ...] = (
|
|
|
49
49
|
PatOrStr: ta.TypeAlias = re.Pattern | str
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
log =
|
|
52
|
+
log = logs.get_module_logger(globals())
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
##
|
|
@@ -143,7 +143,7 @@ HANDLES_APP_MARKER_PROCESSORS: AppMarkerProcessorMap = {
|
|
|
143
143
|
##
|
|
144
144
|
|
|
145
145
|
|
|
146
|
-
class RouteHandlerHolder(lang.Abstract):
|
|
146
|
+
class RouteHandlerHolder(lang.Abstract):
|
|
147
147
|
def get_route_handlers(self) -> ta.Iterable[RouteHandler]:
|
|
148
148
|
return get_marked_route_handlers(self)
|
|
149
149
|
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import contextvars
|
|
2
2
|
import dataclasses as dc
|
|
3
|
-
import logging
|
|
4
3
|
|
|
5
4
|
from omlish import lang
|
|
6
5
|
from omlish.http import asgi
|
|
7
6
|
from omlish.http import sessions
|
|
7
|
+
from omlish.logs import all as logs
|
|
8
8
|
|
|
9
9
|
from .markers import AppMarker
|
|
10
10
|
from .markers import AppMarkerProcessor
|
|
11
11
|
from .markers import append_app_marker
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
log =
|
|
14
|
+
log = logs.get_module_logger(globals())
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
##
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import dataclasses as dc
|
|
2
2
|
import importlib.resources
|
|
3
|
-
import logging
|
|
4
3
|
import typing as ta
|
|
5
4
|
|
|
6
5
|
import jinja2
|
|
7
6
|
|
|
7
|
+
from omlish.logs import all as logs
|
|
8
|
+
|
|
8
9
|
from .base import url_for
|
|
9
10
|
|
|
10
11
|
|
|
11
|
-
log =
|
|
12
|
+
log = logs.get_module_logger(globals())
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
##
|
|
@@ -53,6 +54,7 @@ class JinjaTemplates:
|
|
|
53
54
|
class _Loader(jinja2.BaseLoader):
|
|
54
55
|
def __init__(self, owner: 'JinjaTemplates') -> None:
|
|
55
56
|
super().__init__()
|
|
57
|
+
|
|
56
58
|
self._owner = owner
|
|
57
59
|
|
|
58
60
|
def get_source(self, environment, template):
|
|
@@ -20,7 +20,7 @@ from omlish import lang
|
|
|
20
20
|
NGINX_VERSION = '1.28.0'
|
|
21
21
|
NGINX_SRC_URL = f'https://nginx.org/download/nginx-{NGINX_VERSION}.tar.gz'
|
|
22
22
|
|
|
23
|
-
NGINX_VTS_VERSION = '0.2.
|
|
23
|
+
NGINX_VTS_VERSION = '0.2.4'
|
|
24
24
|
NGINX_VTS_SRC_URL = f'https://github.com/vozlt/nginx-module-vts/archive/refs/tags/v{NGINX_VTS_VERSION}.tar.gz'
|
|
25
25
|
|
|
26
26
|
|
|
@@ -66,9 +66,9 @@ def parse_nginx_log_line(
|
|
|
66
66
|
|
|
67
67
|
|
|
68
68
|
# @omlish-manifest
|
|
69
|
-
_CLI_MODULE = {'
|
|
70
|
-
'
|
|
71
|
-
'
|
|
69
|
+
_CLI_MODULE = {'!omdev.cli.types.CliModule': {
|
|
70
|
+
'name': 'nginxlogs',
|
|
71
|
+
'module': __name__,
|
|
72
72
|
}}
|
|
73
73
|
|
|
74
74
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import contextlib
|
|
2
2
|
import dataclasses as dc
|
|
3
|
-
import logging
|
|
4
3
|
import socket
|
|
5
4
|
import typing as ta
|
|
6
5
|
import uuid
|
|
@@ -12,6 +11,7 @@ from omlish import check
|
|
|
12
11
|
from omlish import lang
|
|
13
12
|
from omlish.asyncs import all as au
|
|
14
13
|
from omlish.asyncs import anyio as anu
|
|
14
|
+
from omlish.logs import all as logs
|
|
15
15
|
from omlish.sql import alchemy as sau
|
|
16
16
|
|
|
17
17
|
from .models import Nodes
|
|
@@ -19,7 +19,7 @@ from .models import setup_db
|
|
|
19
19
|
from .sql import utcnow
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
log =
|
|
22
|
+
log = logs.get_module_logger(globals())
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
##
|
|
@@ -85,6 +85,7 @@ class CreateUpdateAtTrigger(sa.schema.DDLElement):
|
|
|
85
85
|
|
|
86
86
|
def __init__(self, table_name: str) -> None:
|
|
87
87
|
super().__init__()
|
|
88
|
+
|
|
88
89
|
self.table_name = table_name
|
|
89
90
|
|
|
90
91
|
|
|
@@ -111,6 +112,7 @@ class DropUpdateAtTrigger(sa.schema.DDLElement):
|
|
|
111
112
|
|
|
112
113
|
def __init__(self, table_name: str) -> None:
|
|
113
114
|
super().__init__()
|
|
115
|
+
|
|
114
116
|
self.table_name = table_name
|
|
115
117
|
|
|
116
118
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import logging
|
|
2
1
|
import typing as ta
|
|
3
2
|
|
|
4
3
|
import anyio
|
|
@@ -6,6 +5,8 @@ import anyio.abc
|
|
|
6
5
|
import anyio.from_thread
|
|
7
6
|
import anyio.to_thread
|
|
8
7
|
|
|
8
|
+
from omlish.logs import all as logs
|
|
9
|
+
|
|
9
10
|
from .config import Config
|
|
10
11
|
from .debug import handle_error_debug
|
|
11
12
|
from .types import AppWrapper
|
|
@@ -15,7 +16,7 @@ from .types import LifespanScope
|
|
|
15
16
|
from .types import UnexpectedMessageError
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
log =
|
|
19
|
+
log = logs.get_module_logger(globals())
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
##
|
|
@@ -37,6 +38,7 @@ class LifespanFailureError(Exception):
|
|
|
37
38
|
class Lifespan:
|
|
38
39
|
def __init__(self, app: AppWrapper, config: Config) -> None:
|
|
39
40
|
super().__init__()
|
|
41
|
+
|
|
40
42
|
self.app = app
|
|
41
43
|
self.config = config
|
|
42
44
|
self.startup = anyio.Event()
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import errno
|
|
2
2
|
import functools
|
|
3
|
-
import logging
|
|
4
3
|
import os
|
|
5
4
|
import random
|
|
6
5
|
import signal # noqa
|
|
@@ -9,6 +8,8 @@ import typing as ta
|
|
|
9
8
|
import anyio
|
|
10
9
|
import anyio.abc
|
|
11
10
|
|
|
11
|
+
from omlish.logs import all as logs
|
|
12
|
+
|
|
12
13
|
from .config import Config
|
|
13
14
|
from .lifespans import Lifespan
|
|
14
15
|
from .server import ServerFactory
|
|
@@ -22,7 +23,7 @@ from .workercontext import ShutdownError
|
|
|
22
23
|
from .workercontext import WorkerContext
|
|
23
24
|
|
|
24
25
|
|
|
25
|
-
log =
|
|
26
|
+
log = logs.get_module_logger(globals())
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
##
|
|
@@ -173,7 +174,7 @@ class Listener:
|
|
|
173
174
|
binds = []
|
|
174
175
|
|
|
175
176
|
for sock in sockets.insecure_sockets:
|
|
176
|
-
listeners.append(anyio._core._eventloop.get_async_backend().create_tcp_listener(sock)) # noqa
|
|
177
|
+
listeners.append(anyio._core._eventloop.get_async_backend().create_tcp_listener(sock)) # type: ignore[attr-defined] # noqa
|
|
177
178
|
bind = repr_socket_addr(sock.family, sock.getsockname())
|
|
178
179
|
binds.append(f'http://{bind}')
|
|
179
180
|
log.info('Running on http://%s (CTRL + C to quit)', bind)
|
|
@@ -43,6 +43,7 @@ STREAM_ID = 1
|
|
|
43
43
|
class H2CProtocolRequiredError(Exception):
|
|
44
44
|
def __init__(self, data: bytes, request: h11.Request) -> None:
|
|
45
45
|
super().__init__()
|
|
46
|
+
|
|
46
47
|
settings = ''
|
|
47
48
|
headers = [(b':method', request.method), (b':path', request.target)]
|
|
48
49
|
for name, value in request.headers:
|
|
@@ -60,6 +61,7 @@ class H2CProtocolRequiredError(Exception):
|
|
|
60
61
|
class H2ProtocolAssumedError(Exception):
|
|
61
62
|
def __init__(self, data: bytes) -> None:
|
|
62
63
|
super().__init__()
|
|
64
|
+
|
|
63
65
|
self.data = data
|
|
64
66
|
|
|
65
67
|
|
|
@@ -24,6 +24,7 @@ from ..events import Request
|
|
|
24
24
|
from ..events import Response
|
|
25
25
|
from ..events import ServerEvent
|
|
26
26
|
from ..events import StreamClosed
|
|
27
|
+
from ..events import Trailers
|
|
27
28
|
from ..events import Updated
|
|
28
29
|
from ..headers import filter_pseudo_headers
|
|
29
30
|
from ..headers import response_headers
|
|
@@ -50,6 +51,7 @@ class BufferCompleteError(Exception):
|
|
|
50
51
|
class StreamBuffer:
|
|
51
52
|
def __init__(self, event_class: type[WaitableEvent]) -> None:
|
|
52
53
|
super().__init__()
|
|
54
|
+
|
|
53
55
|
self.buffer = bytearray()
|
|
54
56
|
self._complete = False
|
|
55
57
|
self._is_empty = event_class()
|
|
@@ -152,8 +154,7 @@ class H2Protocol(Protocol):
|
|
|
152
154
|
await self._flush()
|
|
153
155
|
|
|
154
156
|
if headers is not None:
|
|
155
|
-
event = h2.events.RequestReceived()
|
|
156
|
-
event.stream_id = 1
|
|
157
|
+
event = h2.events.RequestReceived(stream_id=1)
|
|
157
158
|
event.headers = [hpack.HeaderTuple(*t) for t in headers]
|
|
158
159
|
await self._create_stream(event)
|
|
159
160
|
await self.streams[event.stream_id].handle(EndBody(stream_id=event.stream_id))
|
|
@@ -239,6 +240,10 @@ class H2Protocol(Protocol):
|
|
|
239
240
|
await self.has_data.set()
|
|
240
241
|
await self.stream_buffers[event.stream_id].drain()
|
|
241
242
|
|
|
243
|
+
elif isinstance(event, Trailers):
|
|
244
|
+
self.connection.send_headers(event.stream_id, event.headers)
|
|
245
|
+
await self._flush()
|
|
246
|
+
|
|
242
247
|
elif isinstance(event, StreamClosed):
|
|
243
248
|
await self._close_stream(event.stream_id)
|
|
244
249
|
idle = len(self.streams) == 0 or all(
|
|
@@ -288,9 +293,13 @@ class H2Protocol(Protocol):
|
|
|
288
293
|
)
|
|
289
294
|
|
|
290
295
|
elif isinstance(event, h2.events.StreamEnded):
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
296
|
+
try:
|
|
297
|
+
stream = self.streams[check.not_none(event.stream_id)]
|
|
298
|
+
except KeyError:
|
|
299
|
+
# Response sent before full request received, nothing to do already closed.
|
|
300
|
+
pass
|
|
301
|
+
else:
|
|
302
|
+
await stream.handle(EndBody(stream_id=check.not_none(event.stream_id)))
|
|
294
303
|
|
|
295
304
|
elif isinstance(event, h2.events.StreamReset):
|
|
296
305
|
await self._close_stream(check.not_none(event.stream_id))
|
|
@@ -395,7 +404,7 @@ class H2Protocol(Protocol):
|
|
|
395
404
|
|
|
396
405
|
await self.streams[stream_id].handle(Request(
|
|
397
406
|
stream_id=stream_id,
|
|
398
|
-
headers=filter_pseudo_headers(check.not_none(request.headers)),
|
|
407
|
+
headers=filter_pseudo_headers(check.not_none(request.headers)),
|
|
399
408
|
http_version='2',
|
|
400
409
|
method=method,
|
|
401
410
|
raw_path=raw_path,
|
|
@@ -428,8 +437,7 @@ class H2Protocol(Protocol):
|
|
|
428
437
|
pass
|
|
429
438
|
|
|
430
439
|
else:
|
|
431
|
-
event = h2.events.RequestReceived()
|
|
432
|
-
event.stream_id = push_stream_id
|
|
440
|
+
event = h2.events.RequestReceived(stream_id=push_stream_id)
|
|
433
441
|
event.headers = [hpack.HeaderTuple(*t) for t in request_headers]
|
|
434
442
|
await self._create_stream(event)
|
|
435
443
|
await self.streams[event.stream_id].handle(EndBody(stream_id=event.stream_id))
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import abc
|
|
2
2
|
|
|
3
|
+
from omlish import lang
|
|
4
|
+
|
|
3
5
|
from ..events import ProtocolEvent
|
|
4
6
|
from ..events import ServerEvent
|
|
5
7
|
|
|
@@ -7,7 +9,7 @@ from ..events import ServerEvent
|
|
|
7
9
|
##
|
|
8
10
|
|
|
9
11
|
|
|
10
|
-
class Protocol(
|
|
12
|
+
class Protocol(lang.Abstract):
|
|
11
13
|
@abc.abstractmethod
|
|
12
14
|
async def initiate(self) -> None:
|
|
13
15
|
raise NotImplementedError
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import errno
|
|
2
|
-
import logging
|
|
3
2
|
import math
|
|
4
3
|
import typing as ta
|
|
5
4
|
|
|
@@ -7,6 +6,7 @@ import anyio.abc
|
|
|
7
6
|
|
|
8
7
|
from omlish import check
|
|
9
8
|
from omlish import lang
|
|
9
|
+
from omlish.logs import all as logs
|
|
10
10
|
|
|
11
11
|
from .config import Config
|
|
12
12
|
from .events import Closed
|
|
@@ -20,7 +20,7 @@ from .types import AppWrapper
|
|
|
20
20
|
from .workercontext import WorkerContext
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
log =
|
|
23
|
+
log = logs.get_module_logger(globals())
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
##
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import enum
|
|
2
|
-
import logging
|
|
3
2
|
import time
|
|
4
3
|
import typing as ta
|
|
5
4
|
import urllib.parse
|
|
6
5
|
|
|
6
|
+
from omlish.logs import all as logs
|
|
7
|
+
|
|
7
8
|
from ..config import Config
|
|
8
9
|
from ..events import Body
|
|
9
10
|
from ..events import EndBody
|
|
@@ -12,6 +13,7 @@ from ..events import ProtocolEvent
|
|
|
12
13
|
from ..events import Request
|
|
13
14
|
from ..events import Response
|
|
14
15
|
from ..events import StreamClosed
|
|
16
|
+
from ..events import Trailers
|
|
15
17
|
from ..taskspawner import TaskSpawner
|
|
16
18
|
from ..types import AppWrapper
|
|
17
19
|
from ..types import AsgiSendEvent
|
|
@@ -25,12 +27,13 @@ from .utils import suppress_body
|
|
|
25
27
|
from .utils import valid_server_name
|
|
26
28
|
|
|
27
29
|
|
|
28
|
-
log =
|
|
30
|
+
log = logs.get_module_logger(globals())
|
|
29
31
|
|
|
30
32
|
|
|
31
33
|
##
|
|
32
34
|
|
|
33
35
|
|
|
36
|
+
TRAILERS_VERSIONS = {'2', '3'}
|
|
34
37
|
PUSH_VERSIONS = {'2', '3'}
|
|
35
38
|
EARLY_HINTS_VERSIONS = {'2', '3'}
|
|
36
39
|
|
|
@@ -40,6 +43,7 @@ class AsgiHttpState(enum.Enum):
|
|
|
40
43
|
# hence why this state tracking is required.
|
|
41
44
|
REQUEST = enum.auto()
|
|
42
45
|
RESPONSE = enum.auto()
|
|
46
|
+
TRAILERS = enum.auto()
|
|
43
47
|
CLOSED = enum.auto()
|
|
44
48
|
|
|
45
49
|
|
|
@@ -56,6 +60,7 @@ class HttpStream:
|
|
|
56
60
|
stream_id: int,
|
|
57
61
|
) -> None:
|
|
58
62
|
super().__init__()
|
|
63
|
+
|
|
59
64
|
self.app = app
|
|
60
65
|
self.client = client
|
|
61
66
|
self.closed = False
|
|
@@ -99,6 +104,9 @@ class HttpStream:
|
|
|
99
104
|
'extensions': {},
|
|
100
105
|
}
|
|
101
106
|
|
|
107
|
+
if event.http_version in TRAILERS_VERSIONS:
|
|
108
|
+
self.scope['extensions']['http.response.trailers'] = {}
|
|
109
|
+
|
|
102
110
|
if event.http_version in PUSH_VERSIONS:
|
|
103
111
|
self.scope['extensions']['http.response.push'] = {}
|
|
104
112
|
|
|
@@ -198,7 +206,12 @@ class HttpStream:
|
|
|
198
206
|
await self.send(Body(stream_id=self.stream_id, data=bytes(message.get('body', b''))))
|
|
199
207
|
|
|
200
208
|
if not message.get('more_body', False):
|
|
201
|
-
|
|
209
|
+
await self.send(EndBody(stream_id=self.stream_id))
|
|
210
|
+
|
|
211
|
+
if self.response.get('trailers', False):
|
|
212
|
+
self.state = AsgiHttpState.TRAILERS
|
|
213
|
+
|
|
214
|
+
else:
|
|
202
215
|
self.state = AsgiHttpState.CLOSED
|
|
203
216
|
|
|
204
217
|
log_access(
|
|
@@ -208,7 +221,30 @@ class HttpStream:
|
|
|
208
221
|
time.time() - self.start_time,
|
|
209
222
|
)
|
|
210
223
|
|
|
211
|
-
await self.send(
|
|
224
|
+
await self.send(StreamClosed(stream_id=self.stream_id))
|
|
225
|
+
|
|
226
|
+
elif (
|
|
227
|
+
message['type'] == 'http.response.trailers' and
|
|
228
|
+
self.scope['http_version'] in TRAILERS_VERSIONS and
|
|
229
|
+
self.state == AsgiHttpState.TRAILERS
|
|
230
|
+
):
|
|
231
|
+
for name, value in self.scope['headers']:
|
|
232
|
+
if name == b'te' and value == b'trailers':
|
|
233
|
+
headers = build_and_validate_headers(message['headers'])
|
|
234
|
+
|
|
235
|
+
await self.send(Trailers(stream_id=self.stream_id, headers=headers))
|
|
236
|
+
|
|
237
|
+
break
|
|
238
|
+
|
|
239
|
+
if not message.get('more_trailers', False):
|
|
240
|
+
self.state = AsgiHttpState.CLOSED
|
|
241
|
+
|
|
242
|
+
log_access(
|
|
243
|
+
self.config,
|
|
244
|
+
self.scope,
|
|
245
|
+
self.response, # type: ignore # noqa
|
|
246
|
+
time.time() - self.start_time,
|
|
247
|
+
)
|
|
212
248
|
|
|
213
249
|
await self.send(StreamClosed(stream_id=self.stream_id))
|
|
214
250
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import logging
|
|
2
1
|
import typing as ta
|
|
3
2
|
|
|
3
|
+
from omlish.logs import all as logs
|
|
4
|
+
|
|
4
5
|
from ..config import Config
|
|
5
6
|
from ..events import Request
|
|
6
7
|
from ..types import Scope
|
|
7
8
|
|
|
8
9
|
|
|
9
|
-
log =
|
|
10
|
+
log = logs.get_module_logger(globals())
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
##
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import encodings.idna # prevents `LookupError: unknown encoding: idna` # noqa
|
|
2
2
|
import enum
|
|
3
3
|
import io
|
|
4
|
-
import logging
|
|
5
4
|
import time
|
|
6
5
|
import typing as ta
|
|
7
6
|
import urllib.parse
|
|
8
7
|
|
|
9
|
-
from omlish import check
|
|
10
8
|
import wsproto as wsp
|
|
11
9
|
import wsproto.events as wse
|
|
12
10
|
import wsproto.extensions
|
|
13
11
|
import wsproto.frame_protocol
|
|
14
12
|
import wsproto.utilities
|
|
15
13
|
|
|
14
|
+
from omlish import check
|
|
15
|
+
from omlish.logs import all as logs
|
|
16
|
+
|
|
16
17
|
from ..config import Config
|
|
17
18
|
from ..events import Body
|
|
18
19
|
from ..events import Data
|
|
@@ -37,7 +38,7 @@ from .utils import suppress_body
|
|
|
37
38
|
from .utils import valid_server_name
|
|
38
39
|
|
|
39
40
|
|
|
40
|
-
log =
|
|
41
|
+
log = logs.get_module_logger(globals())
|
|
41
42
|
|
|
42
43
|
|
|
43
44
|
##
|
|
@@ -64,6 +65,7 @@ class Handshake:
|
|
|
64
65
|
) -> None:
|
|
65
66
|
super().__init__()
|
|
66
67
|
|
|
68
|
+
self.accepted = False
|
|
67
69
|
self.http_version = http_version
|
|
68
70
|
self.connection_tokens: list[str] | None = None
|
|
69
71
|
self.extensions: list[str] | None = None
|
|
@@ -148,6 +150,7 @@ class Handshake:
|
|
|
148
150
|
|
|
149
151
|
headers.append((name, value))
|
|
150
152
|
|
|
153
|
+
self.accepted = True
|
|
151
154
|
return status_code, headers, wsp.Connection(wsp.ConnectionType.SERVER, extensions)
|
|
152
155
|
|
|
153
156
|
|
|
@@ -260,6 +263,10 @@ class WsStream:
|
|
|
260
263
|
self.connection.receive_data(event.data)
|
|
261
264
|
await self._handle_events()
|
|
262
265
|
|
|
266
|
+
elif isinstance(event, (Body, Data)) and not self.handshake.accepted:
|
|
267
|
+
await self._send_error_response(400)
|
|
268
|
+
self.closed = True
|
|
269
|
+
|
|
263
270
|
elif isinstance(event, StreamClosed):
|
|
264
271
|
self.closed = True
|
|
265
272
|
|
|
@@ -311,7 +318,7 @@ class WsStream:
|
|
|
311
318
|
elif message['type'] == 'websocket.send' and self.state == AsgiWebsocketState.CONNECTED:
|
|
312
319
|
event: wse.Event
|
|
313
320
|
if message.get('bytes') is not None:
|
|
314
|
-
event = wse.BytesMessage(data=
|
|
321
|
+
event = wse.BytesMessage(data=bytearray(message['bytes']))
|
|
315
322
|
|
|
316
323
|
elif not isinstance(message['text'], str):
|
|
317
324
|
raise TypeError(f'{message["text"]} should be a str')
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import logging
|
|
2
1
|
import types
|
|
3
2
|
import typing as ta
|
|
4
3
|
|
|
@@ -8,6 +7,7 @@ import anyio.from_thread
|
|
|
8
7
|
import anyio.to_thread
|
|
9
8
|
|
|
10
9
|
from omlish import check
|
|
10
|
+
from omlish.logs import all as logs
|
|
11
11
|
|
|
12
12
|
from .config import Config
|
|
13
13
|
from .debug import handle_error_debug
|
|
@@ -18,7 +18,7 @@ from .types import AsgiSendEvent
|
|
|
18
18
|
from .types import Scope
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
log =
|
|
21
|
+
log = logs.get_module_logger(globals())
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
##
|
|
@@ -67,6 +67,7 @@ async def _handle(
|
|
|
67
67
|
class TaskSpawner:
|
|
68
68
|
def __init__(self) -> None:
|
|
69
69
|
super().__init__()
|
|
70
|
+
|
|
70
71
|
self._task_group: anyio.abc.TaskGroup | None = None
|
|
71
72
|
|
|
72
73
|
async def start(
|
|
@@ -9,6 +9,7 @@ from .types import WaitableEvent
|
|
|
9
9
|
class WaitableEventWrapper:
|
|
10
10
|
def __init__(self) -> None:
|
|
11
11
|
super().__init__()
|
|
12
|
+
|
|
12
13
|
self._event = anyio.Event()
|
|
13
14
|
|
|
14
15
|
async def clear(self) -> None:
|
|
@@ -29,6 +30,7 @@ class WorkerContext:
|
|
|
29
30
|
|
|
30
31
|
def __init__(self, max_requests: int | None) -> None:
|
|
31
32
|
super().__init__()
|
|
33
|
+
|
|
32
34
|
self.max_requests = max_requests
|
|
33
35
|
self.requests = 0
|
|
34
36
|
self.terminate = self.event_class()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: omserv
|
|
3
|
-
Version: 0.0.0.
|
|
3
|
+
Version: 0.0.0.dev497
|
|
4
4
|
Summary: omserv
|
|
5
5
|
Author: wrmsr
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -14,18 +14,18 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
14
14
|
Requires-Python: >=3.13
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
16
16
|
License-File: LICENSE
|
|
17
|
-
Requires-Dist: omlish==0.0.0.
|
|
17
|
+
Requires-Dist: omlish==0.0.0.dev497
|
|
18
18
|
Provides-Extra: all
|
|
19
19
|
Requires-Dist: h11~=0.16; extra == "all"
|
|
20
|
-
Requires-Dist: h2~=4.
|
|
20
|
+
Requires-Dist: h2~=4.3; extra == "all"
|
|
21
21
|
Requires-Dist: priority~=2.0; extra == "all"
|
|
22
|
-
Requires-Dist: wsproto~=1.
|
|
22
|
+
Requires-Dist: wsproto~=1.3; extra == "all"
|
|
23
23
|
Requires-Dist: jinja2~=3.1; extra == "all"
|
|
24
24
|
Provides-Extra: server
|
|
25
25
|
Requires-Dist: h11~=0.16; extra == "server"
|
|
26
|
-
Requires-Dist: h2~=4.
|
|
26
|
+
Requires-Dist: h2~=4.3; extra == "server"
|
|
27
27
|
Requires-Dist: priority~=2.0; extra == "server"
|
|
28
|
-
Requires-Dist: wsproto~=1.
|
|
28
|
+
Requires-Dist: wsproto~=1.3; extra == "server"
|
|
29
29
|
Provides-Extra: templates
|
|
30
30
|
Requires-Dist: jinja2~=3.1; extra == "templates"
|
|
31
31
|
Dynamic: license-file
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
omlish==0.0.0.
|
|
1
|
+
omlish==0.0.0.dev497
|
|
2
2
|
|
|
3
3
|
[all]
|
|
4
4
|
h11~=0.16
|
|
5
|
-
h2~=4.
|
|
5
|
+
h2~=4.3
|
|
6
6
|
priority~=2.0
|
|
7
|
-
wsproto~=1.
|
|
7
|
+
wsproto~=1.3
|
|
8
8
|
jinja2~=3.1
|
|
9
9
|
|
|
10
10
|
[server]
|
|
11
11
|
h11~=0.16
|
|
12
|
-
h2~=4.
|
|
12
|
+
h2~=4.3
|
|
13
13
|
priority~=2.0
|
|
14
|
-
wsproto~=1.
|
|
14
|
+
wsproto~=1.3
|
|
15
15
|
|
|
16
16
|
[templates]
|
|
17
17
|
jinja2~=3.1
|
|
@@ -13,7 +13,7 @@ urls = {source = 'https://github.com/wrmsr/omlish'}
|
|
|
13
13
|
license = 'BSD-3-Clause'
|
|
14
14
|
readme = 'README.md'
|
|
15
15
|
requires-python = '>=3.13'
|
|
16
|
-
version = '0.0.0.
|
|
16
|
+
version = '0.0.0.dev497'
|
|
17
17
|
classifiers = [
|
|
18
18
|
'Development Status :: 2 - Pre-Alpha',
|
|
19
19
|
'Intended Audience :: Developers',
|
|
@@ -24,22 +24,22 @@ classifiers = [
|
|
|
24
24
|
]
|
|
25
25
|
description = 'omserv'
|
|
26
26
|
dependencies = [
|
|
27
|
-
'omlish == 0.0.0.
|
|
27
|
+
'omlish == 0.0.0.dev497',
|
|
28
28
|
]
|
|
29
29
|
|
|
30
30
|
[project.optional-dependencies]
|
|
31
31
|
all = [
|
|
32
32
|
'h11 ~= 0.16',
|
|
33
|
-
'h2 ~= 4.
|
|
33
|
+
'h2 ~= 4.3',
|
|
34
34
|
'priority ~= 2.0',
|
|
35
|
-
'wsproto ~= 1.
|
|
35
|
+
'wsproto ~= 1.3',
|
|
36
36
|
'jinja2 ~= 3.1',
|
|
37
37
|
]
|
|
38
38
|
server = [
|
|
39
39
|
'h11 ~= 0.16',
|
|
40
|
-
'h2 ~= 4.
|
|
40
|
+
'h2 ~= 4.3',
|
|
41
41
|
'priority ~= 2.0',
|
|
42
|
-
'wsproto ~= 1.
|
|
42
|
+
'wsproto ~= 1.3',
|
|
43
43
|
]
|
|
44
44
|
templates = [
|
|
45
45
|
'jinja2 ~= 3.1',
|
|
@@ -67,9 +67,13 @@ exclude = [
|
|
|
67
67
|
'*.cu',
|
|
68
68
|
'*.g4',
|
|
69
69
|
'*.h',
|
|
70
|
-
'
|
|
70
|
+
'*.hh',
|
|
71
|
+
'.omlish-manifests.json',
|
|
72
|
+
'README',
|
|
73
|
+
'README.md',
|
|
71
74
|
'LICENSE',
|
|
72
75
|
'LICENSE.txt',
|
|
76
|
+
'AUTHORS',
|
|
73
77
|
'nginx/patches/*.patch',
|
|
74
78
|
'server/resources/*.ico',
|
|
75
79
|
]
|
|
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
|
{omserv-0.0.0.dev395 → omserv-0.0.0.dev497}/omserv/nginx/patches/nginx-1.28.0_http_status.patch
RENAMED
|
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
|