| 27 | |
| 28 | class URL: |
| 29 | def __init__( |
| 30 | self, |
| 31 | url: str = class="st">"", |
| 32 | scope: Scope | None = None, |
| 33 | **components: Any, |
| 34 | ) -> None: |
| 35 | if scope is not None: |
| 36 | assert not url, &class="cm">#x27;Cannot set both class="st">"url" and class="st">"scope".' |
| 37 | assert not components, &class="cm">#x27;Cannot set both class="st">"scope" and class="st">"**components".' |
| 38 | scheme = scope.get(class="st">"scheme", class="st">"http") |
| 39 | server = scope.get(class="st">"server", None) |
| 40 | path = scope[class="st">"path"] |
| 41 | query_string = scope.get(class="st">"query_string", bclass="st">"") |
| 42 | |
| 43 | host_header = None |
| 44 | for key, value in scope[class="st">"headers"]: |
| 45 | if key == bclass="st">"host": |
| 46 | host_header = value.decode(class="st">"latin-1") |
| 47 | break |
| 48 | |
| 49 | if host_header is not None and _HOST_RE.fullmatch(host_header): |
| 50 | netloc = host_header |
| 51 | elif server is not None: |
| 52 | host, port = server |
| 53 | default_port = {class="st">"http": 80, class="st">"https": 443, class="st">"ws": 80, class="st">"wss": 443}[scheme] |
| 54 | netloc = host if port == default_port else fclass="st">"{host}:{port}" |
| 55 | else: |
| 56 | netloc = None |
| 57 | |
| 58 | query = query_string.decode() |
| 59 | if netloc is not None: |
| 60 | url = SplitResult(scheme=scheme, netloc=netloc, path=path, query=query, fragment=class="st">"").geturl() |
| 61 | else: |
| 62 | url = fclass="st">"{path}?{query}" if query else path |
| 63 | elif components: |
| 64 | assert not url, &class="cm">#x27;Cannot set both class="st">"url" and class="st">"**components".' |
| 65 | url = URL(class="st">"").replace(**components).components.geturl() |
| 66 | |
| 67 | self._url = url |
| 68 | |
| 69 | @property |
| 70 | def components(self) -> SplitResult: |