Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions crawl4ai/async_configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import importlib
import os
import warnings
from urllib.parse import urlparse
import requests
from .config import (
DEFAULT_PROVIDER,
Expand Down Expand Up @@ -681,13 +682,8 @@ def __init__(
def _extract_ip_from_server(self) -> Optional[str]:
"""Extract IP address from server URL."""
try:
# Simple extraction assuming http://ip:port format
if "://" in self.server:
parts = self.server.split("://")[1].split(":")
return parts[0]
else:
parts = self.server.split(":")
return parts[0]
server = self.server if "://" in self.server else "//" + self.server
return urlparse(server).hostname
except Exception:
return None

Expand Down
10 changes: 3 additions & 7 deletions crawl4ai/proxy_strategy.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import List, Dict, Optional, Tuple
from abc import ABC, abstractmethod
from itertools import cycle
from urllib.parse import urlparse
import os
import asyncio
import time
Expand Down Expand Up @@ -35,13 +36,8 @@ def __init__(
def _extract_ip_from_server(self) -> Optional[str]:
"""Extract IP address from server URL."""
try:
# Simple extraction assuming http://ip:port format
if "://" in self.server:
parts = self.server.split("://")[1].split(":")
return parts[0]
else:
parts = self.server.split(":")
return parts[0]
server = self.server if "://" in self.server else "//" + self.server
return urlparse(server).hostname
except Exception:
return None

Expand Down
36 changes: 36 additions & 0 deletions tests/unit/test_proxy_hostname_extraction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import pytest

from crawl4ai.async_configs import ProxyConfig
from crawl4ai.proxy_strategy import ProxyConfig as LegacyProxyConfig


@pytest.mark.parametrize("config_cls", [ProxyConfig, LegacyProxyConfig])
@pytest.mark.parametrize(
"server, expected",
[
("http://[2001:db8::1]:8080", "2001:db8::1"),
("[2001:db8::2]:8080", "2001:db8::2"),
("http://user:password@192.0.2.1:8080", "192.0.2.1"),
("socks5://user:password@[2001:db8::1]:1080", "2001:db8::1"),
("https://proxy.example.test/", "proxy.example.test"),
("http://192.0.2.1:8080", "192.0.2.1"),
("proxy.example.test:8080", "proxy.example.test"),
],
)
def test_auto_ip_uses_hostname(config_cls, server, expected):
config = config_cls(server=server)
assert config.ip == expected
assert config.server == server
assert config.to_dict()["ip"] == expected


@pytest.mark.parametrize("config_cls", [ProxyConfig, LegacyProxyConfig])
def test_explicit_verification_ip_is_preserved(config_cls):
assert config_cls(server="http://[::1]:8080", ip="192.0.2.2").ip == "192.0.2.2"


def test_url_factory_keeps_ipv6_endpoint_and_auth():
config = ProxyConfig.from_string("socks5://user:password@[2001:db8::1]:1080")
assert config.ip == "2001:db8::1"
assert config.server == "socks5://[2001:db8::1]:1080"
assert (config.username, config.password) == ("user", "password")