GNServer 0.0.0.0.7__py3-none-any.whl → 0.0.0.0.8__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/_app.py CHANGED
@@ -110,6 +110,59 @@ def guess_type(filename: str) -> str:
110
110
  return mime_map.get(ext, "application/octet-stream")
111
111
 
112
112
 
113
+ import re
114
+ from typing import List
115
+
116
+ # regex для !{var}, поддерживает вложенность через точку
117
+ TPL_VAR_RE = re.compile(r'(?<!\\)!\{([A-Za-z_][A-Za-z0-9_\.]*)\}')
118
+
119
+ # список mime, которые считаем текстовыми
120
+ TEXTUAL_MIME_PREFIXES = [
121
+ "text/", # text/html, text/css, text/plain
122
+ ]
123
+ TEXTUAL_MIME_EXACT = {
124
+ "application/javascript",
125
+ "application/json",
126
+ "application/xml",
127
+ "application/xhtml+xml"
128
+ }
129
+ TEXTUAL_MIME_SUFFIXES = (
130
+ "+xml", # например application/rss+xml
131
+ "+json", # application/ld+json
132
+ )
133
+
134
+ def extract_template_vars(filedata: bytes, mime: str) -> List[str]:
135
+ """
136
+ Ищет все !{var} в тексте, если MIME относится к текстовым.
137
+ """
138
+ mime = (mime or "").lower().strip()
139
+
140
+ # определяем, текстовый ли mime
141
+ is_textual = (
142
+ mime.startswith(tuple(TEXTUAL_MIME_PREFIXES))
143
+ or mime in TEXTUAL_MIME_EXACT
144
+ or mime.endswith(TEXTUAL_MIME_SUFFIXES)
145
+ or "javascript" in mime
146
+ or "json" in mime
147
+ or "xml" in mime
148
+ )
149
+
150
+ if not is_textual:
151
+ return []
152
+
153
+ try:
154
+ text = filedata.decode("utf-8", errors="ignore")
155
+ except Exception:
156
+ return []
157
+
158
+ return list(set(m.group(1) for m in TPL_VAR_RE.finditer(text)))
159
+
160
+
161
+
162
+
163
+
164
+
165
+
113
166
  @dataclass
114
167
  class Route:
115
168
  method: str
@@ -290,7 +343,7 @@ class App:
290
343
 
291
344
  def fastFile(self, path: str, file_path: str, cors: Optional[gn.CORSObject] = None):
292
345
  @self.get(path)
293
- async def r_static(path: str):
346
+ async def r_static():
294
347
  nonlocal file_path
295
348
  if file_path.endswith('/'):
296
349
  file_path = file_path[:-1]
@@ -429,10 +482,6 @@ class App:
429
482
 
430
483
  response = await self._api.dispatch(request)
431
484
 
432
-
433
- response = await self.resolve_extra_response(response)
434
-
435
-
436
485
  if inspect.isasyncgen(response):
437
486
  async for chunk in response: # type: ignore[misc]
438
487
  chunk._stream = True
@@ -455,7 +504,7 @@ class App:
455
504
  except Exception as e:
456
505
  logger.error('GNServer: error\n' + traceback.format_exc())
457
506
 
458
- response = gn.GNResponse('gn:backend:500:Internal Server Error')
507
+ response = gn.GNResponse('gn:backend:500')
459
508
  self._quic.send_stream_data(request.stream_id, response.serialize(3), end_stream=True)
460
509
  self.transmit()
461
510
 
@@ -463,36 +512,12 @@ class App:
463
512
  if response._cors is None:
464
513
  response._cors = self._api._cors
465
514
 
515
+ await response.assembly()
516
+
466
517
  return response
467
518
 
468
519
 
469
- async def resolve_extra_response(self, response: Union[gn.GNResponse, AsyncGenerator[gn.GNResponse, None]]) -> Union[gn.GNResponse, AsyncGenerator[gn.GNResponse, None]]:
470
-
471
- file_types = (
472
- 'html',
473
- 'css',
474
- 'js',
475
- 'svg'
476
- )
477
-
478
- if isinstance(response, gn.GNResponse):
479
- payload = response.payload
480
- if payload is not None:
481
- for ext_file in file_types:
482
- ext_file_ = payload.get(ext_file)
483
- if ext_file_ is not None:
484
- if isinstance(ext_file_, str):
485
- if ext_file_.startswith('/') or ext_file_.startswith('./'):
486
- try:
487
- async with await anyio.open_file(ext_file_, mode="rb") as file:
488
- data = await file.read()
489
-
490
- payload.pop(ext_file)
491
- payload['files'] = [{'mime-type': guess_type(ext_file_.split('/')[-1]), 'data': data}]
492
- except Exception as e:
493
- payload[ext_file] = f'GNServer error: {e}'
494
- logger.debug(f'error resolving extra response -> {traceback.format_exc()}')
495
- return response
520
+
496
521
 
497
522
 
498
523
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GNServer
3
- Version: 0.0.0.0.7
3
+ Version: 0.0.0.0.8
4
4
  Summary: GNServer
5
5
  Home-page: https://github.com/KeyisB/libs/tree/main/GNServer
6
6
  Author: KeyisB
@@ -0,0 +1,7 @@
1
+ GNServer/__init__.py,sha256=l9B6gZZ2gTkWvNdla--J15_Bj0BtP8RyPsrMI6amgDo,1376
2
+ GNServer/_app.py,sha256=WM7gJqSzgUl7fHNPLhzGeyfJOSC4yj4dUZxowSSbWms,18340
3
+ gnserver-0.0.0.0.8.dist-info/licenses/LICENSE,sha256=WH_t7dKZyWJ5Ld07eYIkUG4Tv6zZWXtAdsUqYAUesn0,1084
4
+ gnserver-0.0.0.0.8.dist-info/METADATA,sha256=WCL7mc5UxeFicgVe2tLAw0oyCqKlgpGJ0uPg-bygirU,804
5
+ gnserver-0.0.0.0.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
6
+ gnserver-0.0.0.0.8.dist-info/top_level.txt,sha256=-UOUBuD4u7Qkb1o5PdcwyA3kx8xCH2lwy0tJHi26Wb4,9
7
+ gnserver-0.0.0.0.8.dist-info/RECORD,,
@@ -1,8 +0,0 @@
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,,