GNServer 0.0.0.0.11__tar.gz → 0.0.0.0.12__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.
- {gnserver-0.0.0.0.11 → gnserver-0.0.0.0.12}/GNServer/GNServer/_app.py +108 -13
- {gnserver-0.0.0.0.11 → gnserver-0.0.0.0.12}/GNServer/GNServer.egg-info/PKG-INFO +1 -1
- {gnserver-0.0.0.0.11 → gnserver-0.0.0.0.12}/PKG-INFO +1 -1
- {gnserver-0.0.0.0.11 → gnserver-0.0.0.0.12}/setup.py +1 -1
- {gnserver-0.0.0.0.11 → gnserver-0.0.0.0.12}/GNServer/GNServer/__init__.py +0 -0
- {gnserver-0.0.0.0.11 → gnserver-0.0.0.0.12}/GNServer/GNServer.egg-info/SOURCES.txt +0 -0
- {gnserver-0.0.0.0.11 → gnserver-0.0.0.0.12}/GNServer/GNServer.egg-info/dependency_links.txt +0 -0
- {gnserver-0.0.0.0.11 → gnserver-0.0.0.0.12}/GNServer/GNServer.egg-info/requires.txt +0 -0
- {gnserver-0.0.0.0.11 → gnserver-0.0.0.0.12}/GNServer/GNServer.egg-info/top_level.txt +0 -0
- {gnserver-0.0.0.0.11 → gnserver-0.0.0.0.12}/GNServer/LICENSE +0 -0
- {gnserver-0.0.0.0.11 → gnserver-0.0.0.0.12}/GNServer/mmbConfig.json +0 -0
- {gnserver-0.0.0.0.11 → gnserver-0.0.0.0.12}/LICENSE +0 -0
- {gnserver-0.0.0.0.11 → gnserver-0.0.0.0.12}/MANIFEST.in +0 -0
- {gnserver-0.0.0.0.11 → gnserver-0.0.0.0.12}/setup.cfg +0 -0
@@ -162,29 +162,124 @@ import re
|
|
162
162
|
from urllib.parse import urlparse
|
163
163
|
|
164
164
|
def resolve_cors(origin_url: str, rules: list[str]) -> bool:
|
165
|
+
"""
|
166
|
+
Возвращает origin_url если он матчится хотя бы с одним правилом.
|
167
|
+
Правила:
|
168
|
+
- "*.example.com" -> wildcard (одна метка)
|
169
|
+
- "**.example.com" -> globstar (0+ меток)
|
170
|
+
- "pages.*.core.gn" -> смешанное
|
171
|
+
- "https://*.site.tld" -> с проверкой схемы
|
172
|
+
- "!<regex>" -> полное соответствие по regex к origin_url
|
173
|
+
"""
|
165
174
|
origin = origin_url.rstrip("/")
|
166
|
-
|
167
|
-
|
175
|
+
pu = urlparse(origin)
|
176
|
+
scheme = (pu.scheme or "").lower()
|
177
|
+
host = (pu.hostname or "").lower()
|
178
|
+
port = pu.port # может быть None
|
179
|
+
|
180
|
+
if not host:
|
181
|
+
return False
|
182
|
+
|
168
183
|
for rule in rules:
|
169
184
|
rule = rule.rstrip("/")
|
185
|
+
|
186
|
+
# 1) Регекс-правило
|
170
187
|
if rule.startswith("!"):
|
171
188
|
pattern = rule[1:]
|
172
|
-
if re.
|
173
|
-
return True
|
174
|
-
elif "*" in rule:
|
175
|
-
r = urlparse(rule.replace("*.", ""))
|
176
|
-
if r.scheme and r.scheme != parsed.scheme:
|
177
|
-
continue
|
178
|
-
regex = "^" + re.escape(rule).replace("\\*", "[^.]+") + "$"
|
179
|
-
if re.match(regex, origin):
|
189
|
+
if re.fullmatch(pattern, origin):
|
180
190
|
return True
|
191
|
+
continue
|
192
|
+
|
193
|
+
# 2) Разбор схемы/хоста в правиле
|
194
|
+
r_scheme = ""
|
195
|
+
r_host = ""
|
196
|
+
r_port = None
|
197
|
+
|
198
|
+
if "://" in rule:
|
199
|
+
pr = urlparse(rule)
|
200
|
+
r_scheme = (pr.scheme or "").lower()
|
201
|
+
# pr.netloc может содержать порт
|
202
|
+
netloc = pr.netloc.lower()
|
203
|
+
# разберём порт, если есть
|
204
|
+
if ":" in netloc and not netloc.endswith("]"): # простая обработка IPv6 не требуется здесь
|
205
|
+
name, _, p = netloc.rpartition(":")
|
206
|
+
r_host = name
|
207
|
+
try:
|
208
|
+
r_port = int(p)
|
209
|
+
except ValueError:
|
210
|
+
r_port = None
|
211
|
+
else:
|
212
|
+
r_host = netloc
|
181
213
|
else:
|
182
|
-
|
183
|
-
|
184
|
-
|
214
|
+
r_host = rule.lower()
|
215
|
+
|
216
|
+
# схема в правиле задана -> должна совпасть
|
217
|
+
if r_scheme and r_scheme != scheme:
|
218
|
+
continue
|
219
|
+
# порт в правиле задан -> должен совпасть
|
220
|
+
if r_port is not None and r_port != port:
|
221
|
+
continue
|
222
|
+
|
223
|
+
# 3) Сопоставление хоста по шаблону с * и ** (по меткам)
|
224
|
+
if _host_matches_pattern(host, r_host):
|
225
|
+
return True
|
226
|
+
|
185
227
|
return False
|
186
228
|
|
187
229
|
|
230
|
+
def _host_matches_pattern(host: str, pattern: str) -> bool:
|
231
|
+
"""
|
232
|
+
Матчит host против pattern по доменным меткам:
|
233
|
+
- '*' -> ровно одна метка
|
234
|
+
- '**' -> ноль или больше меток
|
235
|
+
Остальные метки — точное совпадение (без внутр. вайлдкардов).
|
236
|
+
Примеры:
|
237
|
+
host=pages.static.core.gn, pattern=**.core.gn -> True
|
238
|
+
host=pages.static.core.gn, pattern=pages.*.core.gn -> True
|
239
|
+
host=pages.static.core.gn, pattern=*.gn.gn -> False
|
240
|
+
host=abc.def.example.com, pattern=*.example.com -> False (нужно **.example.com)
|
241
|
+
host=abc.example.com, pattern=*.example.com -> True
|
242
|
+
"""
|
243
|
+
host_labels = host.split(".")
|
244
|
+
pat_labels = pattern.split(".")
|
245
|
+
|
246
|
+
# быстрый путь: точное совпадение без вайлдкардов
|
247
|
+
if "*" not in pattern:
|
248
|
+
return host == pattern
|
249
|
+
|
250
|
+
# рекурсивный матч с поддержкой ** (globstar)
|
251
|
+
def match(hi: int, pi: int) -> bool:
|
252
|
+
# оба дошли до конца
|
253
|
+
if pi == len(pat_labels) and hi == len(host_labels):
|
254
|
+
return True
|
255
|
+
# закончился паттерн — нет
|
256
|
+
if pi == len(pat_labels):
|
257
|
+
return False
|
258
|
+
|
259
|
+
token = pat_labels[pi]
|
260
|
+
if token == "**":
|
261
|
+
# два варианта:
|
262
|
+
# - пропустить '**' (ноль меток)
|
263
|
+
if match(hi, pi + 1):
|
264
|
+
return True
|
265
|
+
# - съесть одну метку (если есть) и остаться на '**'
|
266
|
+
if hi < len(host_labels) and match(hi + 1, pi):
|
267
|
+
return True
|
268
|
+
return False
|
269
|
+
elif token == "*":
|
270
|
+
# нужно съесть ровно одну метку
|
271
|
+
if hi < len(host_labels):
|
272
|
+
return match(hi + 1, pi + 1)
|
273
|
+
return False
|
274
|
+
else:
|
275
|
+
# точное совпадение метки
|
276
|
+
if hi < len(host_labels) and host_labels[hi] == token:
|
277
|
+
return match(hi + 1, pi + 1)
|
278
|
+
return False
|
279
|
+
|
280
|
+
return match(0, 0)
|
281
|
+
|
282
|
+
|
188
283
|
|
189
284
|
@dataclass
|
190
285
|
class Route:
|
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
|