import re

def validate_url(url):
    """
    Validates a URL with the format: protocol://domain:port/path?security#fragment
    Returns True if valid, False if invalid, along with any validation messages.

    Parameters:
    url (str): The URL to validate

    Returns:
    tuple: (bool, list) - (is_valid, list of validation messages)
    """
    messages = []

    # Basic URL pattern
    pattern = r'^(?P<protocol>https?|ftp|file)://'  # Protocol
    pattern += r'(?P<domain>([a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?\.)*[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)'  # Domain
    pattern += r'(?P<port>:\d{1,5})?'  # Optional port
    pattern += r'(?P<path>/[^?#]*)?'  # Optional path
    pattern += r'(?P<query>\?[^#]*)?'  # Optional query
    pattern += r'(?P<fragment>#.*)?$'  # Optional fragment

    match = re.match(pattern, url)

    if not match:
        return False, ["Invalid URL format"]

    # Extract components
    components = match.groupdict()

    # Validate protocol
    protocol = components['protocol']
    if protocol not in ['http', 'https', 'ftp', 'file']:
        messages.append(f"Invalid protocol: {protocol}")

    # Validate domain
    domain = components['domain']
    if len(domain) > 255:
        messages.append("Domain name too long")

    # Validate port
    if components['port']:
        port = int(components['port'][1:])  # Remove the ':' prefix
        if port < 1 or port > 65535:
            messages.append(f"Invalid port number: {port}")

    # Validate path
    if components['path']:
        if not all(c.isprintable() for c in components['path']):
            messages.append("Path contains invalid characters")

    # Return validation result
    is_valid = len(messages) == 0
    return is_valid, messages

# Example usage
def test_url_validator():
    test_urls = [
        "http://example.com:8080/path?query=123#fragment",
        "https://subdomain.example.com/path",
        "ftp://invalid:99999/path",
        "invalid://example.com",
        "http://example.com:8080/path?security=token#section"
    ]

    for url in test_urls:
        is_valid, messages = validate_url(url)
        print(f"\nTesting URL: {url}")
        print(f"Valid: {is_valid}")
        if messages:
            print("Messages:", messages)

if __name__ == '__main__':
    test_url_validator()

Generated with Claude sonnet 3.5 :)

Edit

Pub: 15 Feb 2025 08:04 UTC

Edit: 15 Feb 2025 08:05 UTC

Views: 60