(base_url: Optional[str], match: str)
| 185 | |
| 186 | |
| 187 | def resolve_glob_base(base_url: Optional[str], match: str) -> str: |
| 188 | if match[0] == "*": |
| 189 | return match |
| 190 | |
| 191 | token_map: Dict[str, str] = {} |
| 192 | |
| 193 | def map_token(original: str, replacement: str) -> str: |
| 194 | if len(original) == 0: |
| 195 | return "" |
| 196 | token_map[replacement] = original |
| 197 | return replacement |
| 198 | |
| 199 | # Escaped `\\?` behaves the same as `?` in our glob patterns. |
| 200 | match = match.replace(r"\\?", "?") |
| 201 | # Special case about: URLs as they are not relative to base_url |
| 202 | if ( |
| 203 | match.startswith("about:") |
| 204 | or match.startswith("data:") |
| 205 | or match.startswith("chrome:") |
| 206 | or match.startswith("edge:") |
| 207 | or match.startswith("file:") |
| 208 | ): |
| 209 | # about: and data: URLs are not relative to base_url, so we return them as is. |
| 210 | return match |
| 211 | # Glob symbols may be escaped in the URL and some of them such as ? affect resolution, |
| 212 | # so we replace them with safe components first. |
| 213 | processed_parts = [] |
| 214 | for index, token in enumerate(match.split("/")): |
| 215 | if token in (".", "..", ""): |
| 216 | processed_parts.append(token) |
| 217 | continue |
| 218 | # Handle special case of http*://, note that the new schema has to be |
| 219 | # a web schema so that slashes are properly inserted after domain. |
| 220 | if index == 0 and token.endswith(":"): |
| 221 | # Replace any pattern with http: |
| 222 | if "*" in token or "{" in token: |
| 223 | processed_parts.append(map_token(token, "http:")) |
| 224 | else: |
| 225 | # Preserve explicit schema as is as it may affect trailing slashes after domain. |
| 226 | processed_parts.append(token) |
| 227 | continue |
| 228 | question_index = token.find("?") |
| 229 | if question_index == -1: |
| 230 | processed_parts.append(map_token(token, f"$_{index}_$")) |
| 231 | else: |
| 232 | new_prefix = map_token(token[:question_index], f"$_{index}_$") |
| 233 | new_suffix = map_token(token[question_index:], f"?$_{index}_$") |
| 234 | processed_parts.append(new_prefix + new_suffix) |
| 235 | |
| 236 | relative_path = "/".join(processed_parts) |
| 237 | resolved, case_insensitive_part = resolve_base_url(base_url, relative_path) |
| 238 | |
| 239 | for token, original in token_map.items(): |
| 240 | normalize = case_insensitive_part and token in case_insensitive_part |
| 241 | resolved = resolved.replace( |
| 242 | token, original.lower() if normalize else original, 1 |
| 243 | ) |
| 244 |
no test coverage detected