GNServer 0.0.0.0.5__py3-none-any.whl → 0.0.0.0.7__py3-none-any.whl
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.
- GNServer/__init__.py +1 -1
- GNServer/_app.py +59 -17
- GNServer/models.py +25 -0
- {gnserver-0.0.0.0.5.dist-info → gnserver-0.0.0.0.7.dist-info}/METADATA +1 -1
- gnserver-0.0.0.0.7.dist-info/RECORD +8 -0
- gnserver-0.0.0.0.5.dist-info/RECORD +0 -7
- {gnserver-0.0.0.0.5.dist-info → gnserver-0.0.0.0.7.dist-info}/WHEEL +0 -0
- {gnserver-0.0.0.0.5.dist-info → gnserver-0.0.0.0.7.dist-info}/licenses/LICENSE +0 -0
- {gnserver-0.0.0.0.5.dist-info → gnserver-0.0.0.0.7.dist-info}/top_level.txt +0 -0
GNServer/__init__.py
CHANGED
GNServer/_app.py
CHANGED
@@ -44,6 +44,12 @@ console = logging.StreamHandler()
|
|
44
44
|
console.setLevel(logging.INFO)
|
45
45
|
console.setFormatter(logging.Formatter("[GNServer] %(name)s: %(levelname)s: %(message)s"))
|
46
46
|
|
47
|
+
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
|
47
53
|
def guess_type(filename: str) -> str:
|
48
54
|
"""
|
49
55
|
Возвращает актуальный MIME-тип по расширению файла.
|
@@ -112,6 +118,7 @@ class Route:
|
|
112
118
|
param_types: dict[str, Callable[[str], Any]]
|
113
119
|
handler: Callable[..., Any]
|
114
120
|
name: str
|
121
|
+
cors: Optional[gn.CORSObject]
|
115
122
|
|
116
123
|
_PARAM_REGEX: dict[str, str] = {
|
117
124
|
"str": r"[^/]+",
|
@@ -193,8 +200,9 @@ def _ensure_async(fn: Callable[..., Any]) -> Callable[..., Any]:
|
|
193
200
|
class App:
|
194
201
|
def __init__(self):
|
195
202
|
self._routes: List[Route] = []
|
203
|
+
self._cors: Optional[gn.CORSObject] = None
|
196
204
|
|
197
|
-
def route(self, method: str, path: str,
|
205
|
+
def route(self, method: str, path: str, cors: Optional[gn.CORSObject] = None):
|
198
206
|
def decorator(fn: Callable[..., Any]):
|
199
207
|
regex, param_types = _compile_path(path)
|
200
208
|
self._routes.append(
|
@@ -204,26 +212,29 @@ class App:
|
|
204
212
|
regex,
|
205
213
|
param_types,
|
206
214
|
_ensure_async(fn),
|
207
|
-
|
215
|
+
fn.__name__,
|
216
|
+
cors
|
208
217
|
)
|
209
218
|
)
|
210
219
|
return fn
|
211
220
|
return decorator
|
212
221
|
|
213
|
-
def get(self, path: str, *,
|
214
|
-
return self.route("GET", path,
|
222
|
+
def get(self, path: str, *, cors: Optional[gn.CORSObject] = None):
|
223
|
+
return self.route("GET", path, cors)
|
224
|
+
|
225
|
+
def post(self, path: str, *, cors: Optional[gn.CORSObject] = None):
|
226
|
+
return self.route("POST", path, cors)
|
215
227
|
|
216
|
-
def
|
217
|
-
return self.route("
|
228
|
+
def put(self, path: str, *, cors: Optional[gn.CORSObject] = None):
|
229
|
+
return self.route("PUT", path, cors)
|
218
230
|
|
219
|
-
def
|
220
|
-
return self.route("
|
231
|
+
def delete(self, path: str, *, cors: Optional[gn.CORSObject] = None):
|
232
|
+
return self.route("DELETE", path, cors)
|
221
233
|
|
222
|
-
|
223
|
-
|
234
|
+
|
235
|
+
def setRouteCors(self, cors: Optional[gn.CORSObject] = None):
|
236
|
+
self._cors = cors
|
224
237
|
|
225
|
-
def custom(self, method: str, path: str, *, name: str | None = None):
|
226
|
-
return self.route(method, path, name=name)
|
227
238
|
|
228
239
|
|
229
240
|
async def dispatch(
|
@@ -277,18 +288,38 @@ class App:
|
|
277
288
|
return gn.GNResponse("gn:backend:404", {'error': 'Not Found'})
|
278
289
|
|
279
290
|
|
280
|
-
def
|
291
|
+
def fastFile(self, path: str, file_path: str, cors: Optional[gn.CORSObject] = None):
|
292
|
+
@self.get(path)
|
293
|
+
async def r_static(path: str):
|
294
|
+
nonlocal file_path
|
295
|
+
if file_path.endswith('/'):
|
296
|
+
file_path = file_path[:-1]
|
297
|
+
|
298
|
+
if not os.path.isfile(file_path):
|
299
|
+
return gn.GNResponse('gn:backend:404', cors=cors)
|
300
|
+
|
301
|
+
mime_type = guess_type(file_path.split('/')[-1])
|
302
|
+
async with aiofiles.open(file_path, "rb") as f:
|
303
|
+
data = await f.read()
|
304
|
+
|
305
|
+
return gn.GNResponse('ok', {'files': [{'mime-type': mime_type, 'data': data}]}, cors=cors)
|
306
|
+
|
307
|
+
def static(self, path: str, dir_path: str, cors: Optional[gn.CORSObject] = None):
|
281
308
|
@self.get(f"{path}/{{_path:path}}")
|
282
309
|
async def r_static(_path: str):
|
283
310
|
file_path = os.path.join(dir_path, _path)
|
311
|
+
|
312
|
+
if file_path.endswith('/'):
|
313
|
+
file_path = file_path[:-1]
|
314
|
+
|
284
315
|
if not os.path.isfile(file_path):
|
285
|
-
return gn.GNResponse('gn:backend:404')
|
316
|
+
return gn.GNResponse('gn:backend:404', cors=cors)
|
286
317
|
|
287
318
|
mime_type = guess_type(file_path.split('/')[-1])
|
288
319
|
async with aiofiles.open(file_path, "rb") as f:
|
289
|
-
data = f.read()
|
320
|
+
data = await f.read()
|
290
321
|
|
291
|
-
return gn.GNResponse('ok', {'files': [{'mime-type': mime_type, 'data': data}]})
|
322
|
+
return gn.GNResponse('ok', {'files': [{'mime-type': mime_type, 'data': data}]}, cors=cors)
|
292
323
|
|
293
324
|
|
294
325
|
|
@@ -397,6 +428,7 @@ class App:
|
|
397
428
|
try:
|
398
429
|
|
399
430
|
response = await self._api.dispatch(request)
|
431
|
+
|
400
432
|
|
401
433
|
response = await self.resolve_extra_response(response)
|
402
434
|
|
@@ -404,18 +436,21 @@ class App:
|
|
404
436
|
if inspect.isasyncgen(response):
|
405
437
|
async for chunk in response: # type: ignore[misc]
|
406
438
|
chunk._stream = True
|
439
|
+
chunk = await self.resolve_response(chunk)
|
407
440
|
self._quic.send_stream_data(request.stream_id, chunk.serialize(3), end_stream=False)
|
408
441
|
self.transmit()
|
409
442
|
|
410
443
|
l = gn.GNResponse('gn:end-stream')
|
411
444
|
l._stream = True
|
445
|
+
l = self.resolve_response(l)
|
412
446
|
self._quic.send_stream_data(request.stream_id, l.serialize(3), end_stream=True)
|
413
447
|
self.transmit()
|
414
448
|
return
|
415
449
|
|
416
450
|
|
451
|
+
response = await self.resolve_response(response)
|
417
452
|
self._quic.send_stream_data(request.stream_id, response.serialize(3), end_stream=True)
|
418
|
-
logger.debug(f'Отправлен на сервер ответ -> {response.command
|
453
|
+
logger.debug(f'Отправлен на сервер ответ -> {response.command} {response.payload if response.payload and len((response.payload)) < 200 else ''}')
|
419
454
|
self.transmit()
|
420
455
|
except Exception as e:
|
421
456
|
logger.error('GNServer: error\n' + traceback.format_exc())
|
@@ -424,6 +459,13 @@ class App:
|
|
424
459
|
self._quic.send_stream_data(request.stream_id, response.serialize(3), end_stream=True)
|
425
460
|
self.transmit()
|
426
461
|
|
462
|
+
async def resolve_response(self, response: gn.GNResponse) -> gn.GNResponse:
|
463
|
+
if response._cors is None:
|
464
|
+
response._cors = self._api._cors
|
465
|
+
|
466
|
+
return response
|
467
|
+
|
468
|
+
|
427
469
|
async def resolve_extra_response(self, response: Union[gn.GNResponse, AsyncGenerator[gn.GNResponse, None]]) -> Union[gn.GNResponse, AsyncGenerator[gn.GNResponse, None]]:
|
428
470
|
|
429
471
|
file_types = (
|
GNServer/models.py
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
GNServer/__init__.py,sha256=l9B6gZZ2gTkWvNdla--J15_Bj0BtP8RyPsrMI6amgDo,1376
|
2
|
+
GNServer/_app.py,sha256=w2rK4nrDWVZ_f0c3tC2cVckvkb8gY4Xudajiajw6yqQ,18534
|
3
|
+
GNServer/models.py,sha256=3HTbPgXMcltK3hh3RWii0z6X2qYitXmPWzud8pOc4Rk,50
|
4
|
+
gnserver-0.0.0.0.7.dist-info/licenses/LICENSE,sha256=WH_t7dKZyWJ5Ld07eYIkUG4Tv6zZWXtAdsUqYAUesn0,1084
|
5
|
+
gnserver-0.0.0.0.7.dist-info/METADATA,sha256=bqObiR6rIxTCq4Lg_GU9oRyYbw6B1wg2NggJV2qrg5c,804
|
6
|
+
gnserver-0.0.0.0.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
7
|
+
gnserver-0.0.0.0.7.dist-info/top_level.txt,sha256=-UOUBuD4u7Qkb1o5PdcwyA3kx8xCH2lwy0tJHi26Wb4,9
|
8
|
+
gnserver-0.0.0.0.7.dist-info/RECORD,,
|
@@ -1,7 +0,0 @@
|
|
1
|
-
GNServer/__init__.py,sha256=T6kT6WoJpmIXashMSHfuafb9DSePUIzw192h27j9a4M,1364
|
2
|
-
GNServer/_app.py,sha256=sLQwfXmEbMCpRulSVVqUGC5-4jdSQmtDD5JWWhsgXQs,17169
|
3
|
-
gnserver-0.0.0.0.5.dist-info/licenses/LICENSE,sha256=WH_t7dKZyWJ5Ld07eYIkUG4Tv6zZWXtAdsUqYAUesn0,1084
|
4
|
-
gnserver-0.0.0.0.5.dist-info/METADATA,sha256=uEYN3KzhtTxDmRKKNFMo2LYVIZu4O5BnL8BEPubn9KQ,804
|
5
|
-
gnserver-0.0.0.0.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
6
|
-
gnserver-0.0.0.0.5.dist-info/top_level.txt,sha256=-UOUBuD4u7Qkb1o5PdcwyA3kx8xCH2lwy0tJHi26Wb4,9
|
7
|
-
gnserver-0.0.0.0.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|