technitium 0.4.0

Typed async Rust client for the Technitium DNS Server API
Documentation
use std::net::IpAddr;

use serde::Deserialize;

/// Filter for querying DNS logs.
#[derive(Debug, Clone, Default)]
pub struct LogFilter {
    /// Filter by queried domain.
    pub domain: Option<String>,
    /// Filter by client IP address.
    pub client_ip: Option<IpAddr>,
    /// Page number (1-indexed). Defaults to server's default.
    pub page_number: Option<u32>,
    /// Number of entries per page. Defaults to server's default.
    pub entries_per_page: Option<u32>,
}

/// A single DNS query log entry.
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct LogEntry {
    /// Timestamp of the query.
    #[serde(default)]
    pub timestamp: Option<String>,
    /// Client IP address.
    #[serde(default)]
    pub client_ip: Option<IpAddr>,
    /// Queried domain name.
    #[serde(default)]
    pub domain: Option<String>,
    /// Query type (A, AAAA, etc.).
    #[serde(rename = "type", default)]
    pub query_type: Option<String>,
    /// Response type.
    #[serde(default)]
    pub response_type: Option<String>,
    /// All other fields.
    #[serde(flatten)]
    pub extra: serde_json::Value,
}

/// Response wrapper for log queries.
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct LogQueryResponse {
    pub entries: Vec<LogEntry>,
}

/// A log file entry.
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct LogFile {
    /// The log file name (typically a date like "2026-03-18").
    pub file_name: String,
    /// Human-readable file size.
    #[serde(default)]
    pub size: Option<String>,
}

/// Response wrapper for log file listing.
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct LogListResponse {
    pub log_files: Vec<LogFile>,
}