Skip to main content

Python SDK for the DataHorders CDN API

Project description

DataHorders CDN Python SDK

A Python SDK for the DataHorders CDN API, providing programmatic access to manage domains, zones, SSL/TLS certificates, WAF configuration, health checks, and analytics.

Features

  • Full coverage of the DataHorders CDN API
  • Both synchronous and asynchronous support
  • Type hints throughout for IDE support
  • Pydantic models for data validation
  • Custom exceptions for error handling
  • Python 3.9+ support

Installation

pip install datahorders-cdn

Or install from source:

pip install git+https://github.com/datahorders/cdn-python-sdk.git

Quick Start

from datahorders_cdn import DataHordersCDN

# Initialize the client
client = DataHordersCDN(api_key="your-api-key")

# List all domains
domains, meta = client.domains.list()
for domain in domains:
    print(f"{domain.domain} - verified: {domain.verified}")

# Close the client when done
client.close()

Using Context Manager

from datahorders_cdn import DataHordersCDN

with DataHordersCDN(api_key="your-api-key") as client:
    domains, _ = client.domains.list()
    for domain in domains:
        print(domain.domain)

Async Usage

import asyncio
from datahorders_cdn import DataHordersCDN

async def main():
    async with DataHordersCDN(api_key="your-api-key") as client:
        domains, _ = await client.domains.list_async()
        for domain in domains:
            print(domain.domain)

asyncio.run(main())

Configuration

from datahorders_cdn import DataHordersCDN

client = DataHordersCDN(
    api_key="your-api-key",
    base_url="https://dashboard.datahorders.org/api/user/v1",  # Custom base URL
    timeout=60,  # Request timeout in seconds
    verify_ssl=True,  # Verify SSL certificates
)

API Reference

Domains

# List domains with pagination
domains, meta = client.domains.list(page=1, per_page=20)

# Filter by verification status
verified_domains, _ = client.domains.list(verified=True)

# Get a specific domain
domain = client.domains.get(domain_id="dom_abc123")

# Register a new domain
response = client.domains.create(
    domain="example.com",
    health_check_enabled=False,
)
print(f"Verification code: {response.verification.code}")
print(response.verification.instructions)

# Verify domain ownership
result = client.domains.verify(domain="example.com")
if result.verified:
    print("Domain verified!")

# Delete a domain
client.domains.delete(domain_id="dom_abc123")

Zones

from datahorders_cdn import LoadBalanceMethod

# List zones
zones, meta = client.zones.list()

# Get zone by ID
zone = client.zones.get(zone_id="zone_abc123")

# Get zone by FQDN
zone = client.zones.get_by_fqdn("app.example.com")

# Create a zone
zone = client.zones.create(
    name="app",
    domains=["dom_abc123"],
    servers=[
        {
            "address": "10.0.1.100",
            "port": 8080,
            "protocol": "http",
            "healthCheckPath": "/health",
        },
        {
            "address": "10.0.1.101",
            "port": 8080,
            "protocol": "http",
            "weight": 2,
            "backup": True,
        },
    ],
    load_balance_method=LoadBalanceMethod.ROUND_ROBIN,
    upgrade_insecure=True,
    health_check_enabled=True,
)

# Update a zone
zone = client.zones.update(
    zone_id="zone_abc123",
    health_check_enabled=True,
)

# Delete a zone
client.zones.delete(fqdn="app.example.com")

Certificates

from datahorders_cdn import AcmeProvider

# List certificates
certs, meta = client.certificates.list()

# Get certificate by domain
cert = client.certificates.get(domain="example.com")

# Create a manual certificate
cert = client.certificates.create(
    name="example.com SSL",
    cert_content="-----BEGIN CERTIFICATE-----\n...",
    key_content="-----BEGIN PRIVATE KEY-----\n...",
)

# Request an ACME certificate
status = client.certificates.create_acme(
    name="example.com Wildcard",
    domains=["example.com", "*.example.com"],
    email="admin@example.com",
    acme_provider=AcmeProvider.LETSENCRYPT,
)
print(f"Certificate ID: {status.certificate_id}")
print(f"Status: {status.status}")

# Check ACME certificate status
status = client.certificates.get_acme_status(certificate_id="cert_abc123")
if status.status == "active":
    print("Certificate is ready!")

# Download certificate
zip_content = client.certificates.download(certificate_id="cert_abc123")
with open("certificate.zip", "wb") as f:
    f.write(zip_content)

# Delete certificate
client.certificates.delete(domain="example.com")

Upstream Servers

from datahorders_cdn import ServerProtocol

# List upstream servers
servers = client.upstream_servers.list(zone_id="zone_abc123")

# Add a server
server = client.upstream_servers.create(
    zone_id="zone_abc123",
    name="backend-3",
    address="10.0.1.102",
    port=8080,
    protocol=ServerProtocol.HTTP,
    weight=1,
    health_check_path="/health",
)

# Update a server
server = client.upstream_servers.update(
    zone_id="zone_abc123",
    server_id="srv_abc123",
    weight=3,
)

# Delete a server
client.upstream_servers.delete(
    zone_id="zone_abc123",
    server_id="srv_abc123",
)

Health Checks

from datahorders_cdn import HealthCheckProtocol, HealthCheckMethod

# List health check profiles
profiles, pagination = client.health_checks.list_profiles()

# Create a profile
profile = client.health_checks.create_profile(
    name="API Health Check",
    protocol=HealthCheckProtocol.HTTPS,
    port=443,
    path="/api/health",
    method=HealthCheckMethod.GET,
    expected_status_codes="200",
    check_interval=30,
    timeout=10,
    verify_ssl=True,
)

# Disable health checks for a server
client.health_checks.disable_server(
    server_id="srv_abc123",
    reason="Scheduled maintenance",
)

# Re-enable health checks
client.health_checks.enable_server(server_id="srv_abc123")

# List CDN nodes
nodes = client.health_checks.list_cdn_nodes()

WAF (Web Application Firewall)

from datahorders_cdn import (
    WafMode,
    WafRuleType,
    WafMatchTarget,
    WafAction,
    WafSeverity,
    IpListType,
)

# Get WAF configuration
waf = client.waf.get_config(zone_id="zone_abc123")
print(f"WAF enabled: {waf.config.enabled}")
print(f"Mode: {waf.config.mode}")

# Update WAF configuration
waf = client.waf.update_config(
    zone_id="zone_abc123",
    enabled=True,
    mode=WafMode.BLOCKING,
    sqli_detection=True,
    xss_detection=True,
)

# Create a WAF rule
rule = client.waf.create_rule(
    zone_id="zone_abc123",
    name="Block Admin Access",
    rule_type=WafRuleType.PATTERN,
    match_target=WafMatchTarget.URI,
    match_pattern="^/admin",
    action=WafAction.BLOCK,
    severity=WafSeverity.HIGH,
    priority=100,
)

# Block an IP address
ip_entry = client.waf.block_ip(
    zone_id="zone_abc123",
    ip_address="198.51.100.50",
    reason="Malicious activity",
)

# Allow an IP (whitelist)
ip_entry = client.waf.allow_ip(
    zone_id="zone_abc123",
    ip_address="203.0.113.0/24",
    reason="Office network",
)

# Block a country
country_rule = client.waf.add_country(
    zone_id="zone_abc123",
    country_code="XX",
    action=WafAction.BLOCK,
    reason="High risk region",
)

# Block an ASN
asn_rule = client.waf.add_asn(
    zone_id="zone_abc123",
    asn=12345,
    asn_name="Bad Hosting Provider",
    action=WafAction.BLOCK,
    reason="Known abuse source",
)

Analytics

from datetime import date

# Get usage metrics
usage = client.analytics.get_usage()
print(f"Total bandwidth: {usage.total_traffic.gigabytes} GB")
print(f"Total zones: {usage.total_zones}")

for zone in usage.zones:
    print(f"  {zone.zone}: {zone.gigabytes_sent} GB, {zone.requests} requests")

# Get usage for a specific date range
usage = client.analytics.get_usage(
    start_date=date(2024, 1, 1),
    end_date=date(2024, 1, 31),
)

# Get CDN node status
nodes = client.analytics.get_cdn_nodes()
for node in nodes:
    print(f"{node.domain} ({node.ip_address})")

Error Handling

The SDK provides specific exception classes for different error types:

from datahorders_cdn import (
    DataHordersCDN,
    DataHordersError,
    AuthenticationError,
    NotFoundError,
    ValidationError,
    RateLimitError,
    DomainExistsError,
    CertificateInUseError,
)

client = DataHordersCDN(api_key="your-api-key")

try:
    domain = client.domains.create(domain="example.com")
except AuthenticationError:
    print("Invalid API key")
except DomainExistsError:
    print("Domain already registered")
except ValidationError as e:
    print(f"Validation failed: {e.message}")
    print(f"Details: {e.details}")
except RateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after} seconds")
except NotFoundError:
    print("Resource not found")
except DataHordersError as e:
    print(f"API error: {e.message} (code: {e.code})")

Exception Hierarchy

DataHordersError
    AuthenticationError     # 401 - Invalid credentials
    AuthorizationError      # 403 - Insufficient permissions
    NotFoundError           # 404 - Resource not found
    RateLimitError          # 429 - Rate limit exceeded
    ServerError             # 5xx - Server errors
    ConflictError           # 409 - Resource conflicts
        DomainExistsError
        DomainInUseError
        CertificateInUseError
    ValidationError         # 400 - Validation errors
        DuplicateCertificateError
        InvalidCertificateError
        InvalidDomainsError
        CircularUpstreamError

Pagination

List methods return a tuple of (items, metadata):

domains, meta = client.domains.list(page=1, per_page=20)

print(f"Page {meta.page} of {meta.total_pages}")
print(f"Total items: {meta.total}")

# Iterate through all pages
page = 1
while True:
    domains, meta = client.domains.list(page=page, per_page=100)
    for domain in domains:
        print(domain.domain)

    if page >= meta.total_pages:
        break
    page += 1

Development

Setup

# Clone the repository
git clone https://github.com/datahorders/cdn-python-sdk.git
cd cdn-python-sdk

# Install development dependencies
pip install -e ".[dev]"

Running Tests

pytest

Type Checking

mypy datahorders_cdn

Linting

ruff check datahorders_cdn
black --check datahorders_cdn

License

MIT License - see LICENSE for details.

Support

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

datahorders_cdn-1.0.0.tar.gz (26.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

datahorders_cdn-1.0.0-py3-none-any.whl (32.8 kB view details)

Uploaded Python 3

File details

Details for the file datahorders_cdn-1.0.0.tar.gz.

File metadata

  • Download URL: datahorders_cdn-1.0.0.tar.gz
  • Upload date:
  • Size: 26.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for datahorders_cdn-1.0.0.tar.gz
Algorithm Hash digest
SHA256 bd8e1d20cbc8962af0f8e582e827b61ce53dd258af21b7c4de4e311ee1b40eb0
MD5 6c481134a18be6e51a798a6d8bf26da6
BLAKE2b-256 d8d5356d5937d2ccd11d0e169e6a88d39a698b3bd218d3a64caac2ee6bba1bc6

See more details on using hashes here.

Provenance

The following attestation bundles were made for datahorders_cdn-1.0.0.tar.gz:

Publisher: publish.yml on datahorders/cdn-python-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file datahorders_cdn-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for datahorders_cdn-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e111b6f83080c2a7fa9c8549b2b16c784f3184901bb71110ac3432061600ea54
MD5 edbc9dee85fddc2aee9062f4dbfeb785
BLAKE2b-256 cde33924bac314de51809be6734badcb9b391ff17ca95184b24285ecbe1a6412

See more details on using hashes here.

Provenance

The following attestation bundles were made for datahorders_cdn-1.0.0-py3-none-any.whl:

Publisher: publish.yml on datahorders/cdn-python-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page