Specialized URL and Network Types
To validate and parse complex network identifiers like standard URLs or multi-host database connection strings, use the UrlSchema and MultiHostUrlSchema definitions. These schemas produce Url and MultiHostUrl objects that provide structured access to components like schemes, hosts, ports, and credentials.
Validating Standard URLs
Use core_schema.url_schema to validate standard URL strings. The resulting Url object provides properties for each part of the URL.
from pydantic_core import SchemaValidator, core_schema, Url
# Define a schema for standard URLs
schema = core_schema.url_schema(allowed_schemes=['https', 'http'])
v = SchemaValidator(schema)
# Validate a URL string
url = v.validate_python('https://user:pass@example.com:8080/path?query=1#frag')
assert isinstance(url, Url)
assert url.scheme == 'https'
assert url.host == 'example.com'
assert url.port == 8080
assert url.path == '/path'
assert url.query == 'query=1'
assert url.fragment == 'frag'
assert url.username == 'user'
assert url.password == 'pass'
# Access query parameters as a list of tuples
assert url.query_params() == [('query', '1')]
Validating Multi-Host URLs
For connection strings that support multiple hosts (common in Redis or PostgreSQL clusters), use core_schema.multi_host_url_schema. The MultiHostUrl object includes a hosts() method that returns a list of MultiHostHost dictionaries.
from pydantic_core import SchemaValidator, core_schema, MultiHostUrl
schema = core_schema.multi_host_url_schema(allowed_schemes=['redis', 'postgresql'])
v = SchemaValidator(schema)
# Validate a multi-host string
url = v.validate_python('redis://node1:6379,node2:6380/0')
assert isinstance(url, MultiHostUrl)
assert str(url) == 'redis://node1:6379,node2:6380/0'
# Extract structured host information
hosts = url.hosts()
assert hosts == [
{'username': None, 'password': None, 'host': 'node1', 'port': 6379},
{'username': None, 'password': None, 'host': 'node2', 'port': 6380},
]
Programmatic Construction
You can build Url and MultiHostUrl objects programmatically using the .build() method. This is useful when you have structured data and need to generate a valid URL string.
from pydantic_core import Url, MultiHostUrl, MultiHostHost
# Building a standard URL
url = Url.build(
scheme='https',
host='example.com',
path='api/v1',
query='debug=true'
)
assert str(url) == 'https://example.com/api/v1?debug=true'
# Building a multi-host URL using MultiHostHost dictionaries
hosts: list[MultiHostHost] = [
{'host': 'db-primary', 'port': 5432, 'username': 'admin', 'password': 'pw'},
{'host': 'db-replica', 'port': 5432, 'username': 'admin', 'password': 'pw'},
]
multi_url = MultiHostUrl.build(
scheme='postgresql',
hosts=hosts,
path='customer_data'
)
assert str(multi_url) == 'postgresql://admin:pw@db-primary:5432,admin:pw@db-replica:5432/customer_data'
Applying Constraints
Both UrlSchema and MultiHostUrlSchema support constraints to enforce specific URL formats.
from pydantic_core import SchemaValidator, core_schema
schema = core_schema.url_schema(
allowed_schemes=['https'],
host_required=True,
max_length=50
)
v = SchemaValidator(schema)
# This will fail because the scheme is not https
# v.validate_python('http://example.com')
# This will fail because the host is missing
# v.validate_python('https:///path')
Handling Empty Paths
By default, pydantic-core normalizes empty paths to /. If you need to preserve the absence of a path, set url_preserve_empty_path to True in the CoreConfig.
from pydantic_core import SchemaValidator, core_schema, CoreConfig
# Default behavior: empty path becomes '/'
v_default = SchemaValidator(core_schema.url_schema())
assert v_default.validate_python('https://example.com').path == '/'
# Preserving empty path
config = CoreConfig(url_preserve_empty_path=True)
v_preserve = SchemaValidator(core_schema.url_schema(), config)
assert v_preserve.validate_python('https://example.com').path is None
Troubleshooting
- Validation Errors: URL validation failures typically raise a
ValidationErrorwith the typeurl_parsing. - Multi-Host Conflicts: When using
MultiHostUrl.build(), you cannot provide bothhostandhostsarguments simultaneously; doing so will raise aValueError. - Port Defaults: If a port is not specified in the URL string, the
portproperty will return the default port for the scheme (e.g., 443 forhttps) if the scheme is recognized.