unique-search-proxy 2026.44.0.dev8__tar.gz → 2026.44.0.dev9__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.
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/PKG-INFO +2 -2
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/pyproject.toml +2 -2
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/crawlers/basic/service.py +63 -6
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/README.md +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/api/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/api/health.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/api/v1/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/api/v1/agent_search.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/api/v1/configuration.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/api/v1/context_headers.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/api/v1/crawl.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/api/v1/openapi_examples.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/api/v1/search.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/app.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/context.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/agent_engines/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/agent_engines/bing/cleanup.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/agent_engines/bing/client.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/agent_engines/bing/runner.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/agent_engines/bing/service.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/agent_engines/factory.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/agent_engines/service_base.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/agent_engines/structured_output.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/agent_engines/vertexai/client.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/agent_engines/vertexai/gemini.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/agent_engines/vertexai/redirects.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/agent_engines/vertexai/service.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/client/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/client/azure_transport.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/client/credentials.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/client/service.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/crawlers/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/crawlers/basic/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/crawlers/basic/processing/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/crawlers/basic/processing/errors.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/crawlers/basic/processing/html_markdown.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/crawlers/basic/processing/processors/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/crawlers/basic/processing/processors/html.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/crawlers/basic/processing/processors/pdf.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/crawlers/basic/processing/processors/plain_text.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/crawlers/basic/processing/registry.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/crawlers/basic/settings.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/crawlers/basic/user_agent.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/crawlers/factory.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/crawlers/firecrawl/polling.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/crawlers/firecrawl/request_body.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/crawlers/firecrawl/service.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/crawlers/jina/request_body.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/crawlers/jina/service.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/crawlers/pinned_egress.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/crawlers/tavily/request_body.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/crawlers/tavily/service.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/provider_response.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/providers.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/registry.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/search_engines/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/search_engines/brave/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/search_engines/brave/pagination.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/search_engines/brave/query_params.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/search_engines/brave/service.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/search_engines/custom_api/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/search_engines/custom_api/service.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/search_engines/descriptor.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/search_engines/factory.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/search_engines/google/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/search_engines/google/pagination.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/search_engines/google/query_params.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/search_engines/google/service.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/search_engines/pagination.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/search_engines/perplexity/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/search_engines/perplexity/request_body.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/search_engines/perplexity/service.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/search_engines/service_base.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/url_safety/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/core/url_safety/gate.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/error_handlers.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/helm/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/helm/generator/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/helm/generator/introspect.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/helm/generator/schema.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/helm/generator/template.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/helm/generator/templates/provider_values_yaml.j2 +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/helm/generator/values_yaml.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/helm/metadata.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/helm/registry.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/helm/url_safety_registration.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/logging_config.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/middleware/context.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/monitoring/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/monitoring/metrics.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/monitoring/setup.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/presets/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/presets/common.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/presets/crawl.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/presets/search.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/presets/types.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/settings/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/settings/app.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/settings/base.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/settings/client.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/settings/monitoring.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/settings/providers/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/settings/providers/base.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/settings/providers/bing_agent.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/settings/providers/brave.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/settings/providers/firecrawl.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/settings/providers/google.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/settings/providers/jina.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/settings/providers/perplexity.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/settings/providers/tavily.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/settings/providers/vertexai_agent.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/settings/secret_str.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/startup_report.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/utils/__init__.py +0 -0
- {unique_search_proxy-2026.44.0.dev8 → unique_search_proxy-2026.44.0.dev9}/unique_search_proxy_client/web/utils/url.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: unique-search-proxy
|
|
3
|
-
Version: 2026.44.0.
|
|
3
|
+
Version: 2026.44.0.dev9
|
|
4
4
|
Summary: Web Search Proxy implementation
|
|
5
5
|
Author: ThePhilAz
|
|
6
6
|
Author-email: ThePhilAz <rami.azouz@philico.com>
|
|
@@ -21,7 +21,7 @@ Requires-Dist: google-genai>=1.73.0,<2
|
|
|
21
21
|
Requires-Dist: google-auth>=2.43.0,<3
|
|
22
22
|
Requires-Dist: jinja2>=3.1.6,<4
|
|
23
23
|
Requires-Dist: unique-toolkit[monitoring]>=2026.44.0.dev9,<2026.44.0rc0
|
|
24
|
-
Requires-Dist: unique-search-proxy-core>=2026.44.0.
|
|
24
|
+
Requires-Dist: unique-search-proxy-core>=2026.44.0.dev8,<2026.44.0rc0
|
|
25
25
|
Requires-Dist: openai>=1.105.0,<3
|
|
26
26
|
Requires-Python: >=3.12
|
|
27
27
|
Description-Content-Type: text/markdown
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "unique-search-proxy"
|
|
3
|
-
version = "2026.44.0.
|
|
3
|
+
version = "2026.44.0.dev9"
|
|
4
4
|
description = "Web Search Proxy implementation"
|
|
5
5
|
authors = [{ name = "ThePhilAz", email = "rami.azouz@philico.com" }]
|
|
6
6
|
readme = "README.md"
|
|
@@ -23,7 +23,7 @@ dependencies = [
|
|
|
23
23
|
"google-auth>=2.43.0,<3",
|
|
24
24
|
"jinja2>=3.1.6,<4",
|
|
25
25
|
"unique-toolkit[monitoring]>=2026.44.0.dev9,<2026.44.0rc0",
|
|
26
|
-
"unique-search-proxy-core>=2026.44.0.
|
|
26
|
+
"unique-search-proxy-core>=2026.44.0.dev8,<2026.44.0rc0",
|
|
27
27
|
"openai>=1.105.0,<3",
|
|
28
28
|
]
|
|
29
29
|
|
|
@@ -10,6 +10,8 @@ from unique_search_proxy_core.crawlers.basic.processing.policy import (
|
|
|
10
10
|
ContentTypeHandlerPolicy,
|
|
11
11
|
)
|
|
12
12
|
from unique_search_proxy_core.crawlers.basic.schema import BasicCrawlRequest
|
|
13
|
+
from unique_search_proxy_core.errors import ResponseTooLargeError
|
|
14
|
+
from unique_search_proxy_core.http_client import read_capped_body
|
|
13
15
|
from unique_search_proxy_core.schema import (
|
|
14
16
|
CrawlUrlResult,
|
|
15
17
|
ProxyErrorCode,
|
|
@@ -18,7 +20,7 @@ from unique_search_proxy_core.url_safety import (
|
|
|
18
20
|
CrawlTargetValidationError,
|
|
19
21
|
ResolvedCrawlTarget,
|
|
20
22
|
bypass_crawl_target,
|
|
21
|
-
|
|
23
|
+
safe_pinned_httpx_stream,
|
|
22
24
|
url_safety_settings,
|
|
23
25
|
)
|
|
24
26
|
|
|
@@ -37,9 +39,15 @@ from unique_search_proxy_client.web.core.provider_response import (
|
|
|
37
39
|
)
|
|
38
40
|
from unique_search_proxy_client.web.core.url_safety.gate import AllowedCrawlTarget
|
|
39
41
|
from unique_search_proxy_client.web.monitoring.metrics import record_crawl_blocked
|
|
42
|
+
from unique_search_proxy_client.web.settings.client import http_client_settings
|
|
40
43
|
|
|
41
44
|
_LOGGER = logging.getLogger(__name__)
|
|
42
45
|
|
|
46
|
+
# Only encodings whose decoded size read_capped_body can bound in small steps;
|
|
47
|
+
# brotli and zstd reach far higher compression ratios.
|
|
48
|
+
_ACCEPT_ENCODING = "gzip, deflate"
|
|
49
|
+
_COMPRESSING_CONTENT_ENCODINGS = frozenset({"gzip", "deflate"})
|
|
50
|
+
|
|
43
51
|
|
|
44
52
|
def _content_type_from_response(response: httpx.Response) -> str | None:
|
|
45
53
|
header = response.headers.get("content-type")
|
|
@@ -48,6 +56,25 @@ def _content_type_from_response(response: httpx.Response) -> str | None:
|
|
|
48
56
|
return str(header).split(";")[0].strip().lower() or None
|
|
49
57
|
|
|
50
58
|
|
|
59
|
+
def _unsupported_content_encoding(response: httpx.Response) -> str | None:
|
|
60
|
+
encodings = [
|
|
61
|
+
encoding.strip().lower()
|
|
62
|
+
for encoding in response.headers.get_list(
|
|
63
|
+
"content-encoding",
|
|
64
|
+
split_commas=True,
|
|
65
|
+
)
|
|
66
|
+
]
|
|
67
|
+
for encoding in encodings:
|
|
68
|
+
if encoding not in {"", "identity", *_COMPRESSING_CONTENT_ENCODINGS}:
|
|
69
|
+
return encoding
|
|
70
|
+
# httpx decodes stacked layers in a single step, so a second compressing
|
|
71
|
+
# layer would inflate past read_capped_body before it can check the size.
|
|
72
|
+
compressing = [e for e in encodings if e in _COMPRESSING_CONTENT_ENCODINGS]
|
|
73
|
+
if len(compressing) > 1:
|
|
74
|
+
return ", ".join(compressing)
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
|
|
51
78
|
class BasicCrawlerService(BaseCrawler[BasicCrawlRequest]):
|
|
52
79
|
"""Fetch URLs over HTTP and return the response body plus content type."""
|
|
53
80
|
|
|
@@ -107,14 +134,38 @@ class BasicCrawlerService(BaseCrawler[BasicCrawlRequest]):
|
|
|
107
134
|
) -> CrawlUrlResult:
|
|
108
135
|
async with semaphore:
|
|
109
136
|
try:
|
|
110
|
-
|
|
137
|
+
async with safe_pinned_httpx_stream(
|
|
111
138
|
client,
|
|
112
139
|
resolved_target,
|
|
113
|
-
headers={
|
|
140
|
+
headers={
|
|
141
|
+
"User-Agent": random_user_agent(),
|
|
142
|
+
"Accept-Encoding": _ACCEPT_ENCODING,
|
|
143
|
+
},
|
|
114
144
|
timeout=Timeout(timeout),
|
|
115
145
|
max_redirect_hops=url_safety_settings.max_redirect_hops,
|
|
116
146
|
enforce_url_safety=url_safety_settings.enabled,
|
|
117
|
-
)
|
|
147
|
+
) as response:
|
|
148
|
+
content_type = _content_type_from_response(response)
|
|
149
|
+
unsupported_encoding = _unsupported_content_encoding(response)
|
|
150
|
+
if unsupported_encoding is not None:
|
|
151
|
+
_LOGGER.warning(
|
|
152
|
+
"Basic crawl rejected content encoding %s",
|
|
153
|
+
unsupported_encoding,
|
|
154
|
+
)
|
|
155
|
+
return crawl_upstream_error(
|
|
156
|
+
display_url,
|
|
157
|
+
f"Unsupported content encoding: {unsupported_encoding}",
|
|
158
|
+
content_type=content_type,
|
|
159
|
+
status_code=response.status_code,
|
|
160
|
+
)
|
|
161
|
+
body = await read_capped_body(
|
|
162
|
+
response,
|
|
163
|
+
max_bytes=http_client_settings.max_response_bytes,
|
|
164
|
+
)
|
|
165
|
+
raw_body = body.decode(
|
|
166
|
+
response.encoding or "utf-8",
|
|
167
|
+
errors="replace",
|
|
168
|
+
)
|
|
118
169
|
except CrawlTargetValidationError as exc:
|
|
119
170
|
blocked = exc.blocked_targets[0]
|
|
120
171
|
record_crawl_blocked(blocked.category)
|
|
@@ -123,6 +174,14 @@ class BasicCrawlerService(BaseCrawler[BasicCrawlRequest]):
|
|
|
123
174
|
blocked.category,
|
|
124
175
|
)
|
|
125
176
|
return crawl_forbidden_target(display_url, blocked.reason)
|
|
177
|
+
except ResponseTooLargeError as exc:
|
|
178
|
+
_LOGGER.warning("Basic crawl response too large: %s", exc.message)
|
|
179
|
+
return crawl_upstream_error(
|
|
180
|
+
display_url,
|
|
181
|
+
exc.message,
|
|
182
|
+
content_type=None,
|
|
183
|
+
code=ProxyErrorCode.RESPONSE_TOO_LARGE.value,
|
|
184
|
+
)
|
|
126
185
|
except httpx.TimeoutException as exc:
|
|
127
186
|
_LOGGER.warning(
|
|
128
187
|
"Basic crawl timed out error_type=%s",
|
|
@@ -147,8 +206,6 @@ class BasicCrawlerService(BaseCrawler[BasicCrawlRequest]):
|
|
|
147
206
|
raw=transport_error_raw(exc),
|
|
148
207
|
)
|
|
149
208
|
|
|
150
|
-
content_type = _content_type_from_response(response)
|
|
151
|
-
raw_body = response.text
|
|
152
209
|
if response.is_error:
|
|
153
210
|
_LOGGER.warning(
|
|
154
211
|
"Basic crawl HTTP error http_status=%s",
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|