qiniu-http-client 0.2.4

Qiniu HTTP Client for Rust
Documentation
use super::super::{ResolveOptions, ResolveResult, Resolver, ResponseError, ResponseErrorKind};
use rand::{prelude::*, thread_rng};
use std::{
    net::{IpAddr, Ipv4Addr},
    sync::Arc,
};

pub(crate) fn make_dumb_resolver() -> impl Resolver + Clone {
    #[derive(Debug, Clone)]
    struct FakeResolver;

    impl Resolver for FakeResolver {
        fn resolve(&self, _domain: &str, _opts: ResolveOptions) -> ResolveResult {
            Ok(vec![].into())
        }
    }

    FakeResolver
}

pub(crate) fn make_static_resolver(ip_addrs: Arc<[IpAddr]>) -> impl Resolver + Clone {
    #[derive(Debug, Clone)]
    struct StaticResolver(Arc<[IpAddr]>);

    impl Resolver for StaticResolver {
        fn resolve(&self, _domain: &str, _opts: ResolveOptions) -> ResolveResult {
            Ok(self.0.to_vec().into())
        }
    }

    StaticResolver(ip_addrs)
}

pub(crate) fn make_random_resolver() -> impl Resolver + Clone {
    #[derive(Debug, Clone, Copy)]
    struct RandomResolver;

    impl Resolver for RandomResolver {
        fn resolve(&self, _domain: &str, _opts: ResolveOptions) -> ResolveResult {
            let ips = vec![IpAddr::V4(Ipv4Addr::from(thread_rng().gen::<u32>()))];
            Ok(ips.into())
        }
    }

    RandomResolver
}

pub(crate) fn make_error_resolver(error_kind: ResponseErrorKind, message: impl Into<String>) -> impl Resolver + Clone {
    #[derive(Debug, Clone)]
    struct ErrorResolver {
        error_kind: ResponseErrorKind,
        message: String,
    }

    impl Resolver for ErrorResolver {
        fn resolve(&self, _domain: &str, _opts: ResolveOptions) -> ResolveResult {
            Err(ResponseError::new_with_msg(self.error_kind, self.message.to_owned()))
        }
    }

    ErrorResolver {
        error_kind,
        message: message.into(),
    }
}

#[cfg(all(feature = "async", any(feature = "c_ares", feature = "trust_dns")))]
mod mock_dns_server {
    use super::*;
    use std::collections::{BTreeMap, HashMap};
    use tokio::net::UdpSocket;
    use trust_dns_server::{
        authority::{AuthorityObject, Catalog, ZoneType},
        client::rr::RrKey,
        proto::rr::{rdata::SOA, DNSClass, Name, RData, Record, RecordSet, RecordType},
        store::in_memory::InMemoryAuthority,
        ServerFuture,
    };

    pub(crate) fn start_mock_dns_server(
        listen: UdpSocket,
        zone_authorities: HashMap<Name, Box<dyn AuthorityObject>>,
    ) -> ServerFuture<Catalog> {
        let mut server_future = ServerFuture::new(make_dns_authority_catalog(zone_authorities));
        server_future.register_socket(listen);
        return server_future;

        fn make_dns_authority_catalog(zone_authorities: HashMap<Name, Box<dyn AuthorityObject>>) -> Catalog {
            let mut catalog = Catalog::new();
            for (name, authority) in zone_authorities {
                catalog.upsert(name.into(), authority);
            }
            catalog
        }
    }

    pub(crate) fn make_zone<I: IntoIterator<Item = (Name, RecordType, RecordSet)>>(
        origin: Name,
        record_infos: I,
    ) -> Result<Box<dyn AuthorityObject>, String> {
        let mut records = BTreeMap::<RrKey, RecordSet>::new();
        for (name, record_type, record_set) in record_infos.into_iter() {
            let key = RrKey::new(name.into(), record_type);
            records.insert(key, record_set);
        }
        {
            let (key, soa_record_set) = make_soa(origin.to_owned());
            records.insert(key, soa_record_set);
        }
        return make_dns_authority_object(origin, records);

        fn make_dns_authority_object(
            origin: Name,
            records: BTreeMap<RrKey, RecordSet>,
        ) -> Result<Box<dyn AuthorityObject>, String> {
            let authority = InMemoryAuthority::new(origin, records, ZoneType::Primary, false)?;
            Ok(Box::new(Arc::new(authority)))
        }

        fn make_soa(name: Name) -> (RrKey, RecordSet) {
            let mut record_set = RecordSet::new(&name, RecordType::SOA, 0);
            let mut record = Record::new();
            record
                .set_name(name.to_owned())
                .set_ttl(3600)
                .set_rr_type(RecordType::SOA)
                .set_dns_class(DNSClass::IN)
                .set_data(Some(RData::SOA(SOA::new(
                    Name::from_str_relaxed("sns.dns.icann.org.").unwrap(),
                    Name::from_str_relaxed("noc.dns.icann.org.").unwrap(),
                    20,
                    7200,
                    600,
                    3600000,
                    60,
                ))));

            record_set.insert(record, 0);
            (RrKey::new(name.into(), RecordType::SOA), record_set)
        }
    }

    pub(crate) fn make_record_set<I: IntoIterator<Item = (Name, u32, RData)>>(
        name: Name,
        record_type: RecordType,
        ttl: u32,
        records: I,
    ) -> RecordSet {
        let mut record_set = RecordSet::with_ttl(name, record_type, ttl);
        for (name, ttl, rdata) in records.into_iter() {
            record_set.insert(Record::from_rdata(name, ttl, rdata), 0);
        }
        record_set
    }
}

#[cfg(all(feature = "async", any(feature = "c_ares", feature = "trust_dns")))]
pub(crate) use mock_dns_server::{make_record_set, make_zone, start_mock_dns_server};