All Products
Search
Document Center

Alibaba Cloud DNS:Harmony SDK development guide

Last Updated:Apr 01, 2026

This guide explains how to integrate and use the HTTPDNS Harmony SDK.

Install the SDK

You can import the SDK into your DevEco Studio project using automatic import or manual import. For a complete example of how to use the SDK, see the Demo sample project source code.

  • Automatic import: Install using ohpm

    You can get the SDK from the OpenHarmony third-party library repository.

    In the root directory of your project, run the following command:

    ohpm install @alidns/httpdns

    For more information about the ohpm tool and installing third-party SDKs for OpenHarmony, see Instructions for the OpenHarmony Third-Party Library Repository.

  • Manual import: Use a local HAR package

    Download the Harmony SDK from the SDK Download page and integrate it into your app project.

    In your project's oh-package.json5 file, set the dependency. The following example shows the configuration if the HAR package is in the project's root directory. Make sure you use the actual path to your HAR package.

    "dependencies": {
        "@alidns/httpdns": "file:alidns-harmony-sdk-2.0.2.har"
     }

    After you configure the dependency, run the ohpm install command to install the package. The package is stored in the oh_modules directory of your project.

    ohpm install

Use the SDK

Import the module

import { Alipdns,schemaType,DNSDomainInfo, DNSLogger } from '@alidns/httpdns'

Set up authentication

Enable authentication to protect user identities and prevent unauthorized use. To configure the SDK, add the following code to your ability's onCreate lifecycle callback.

Important

See Create a key to create an AccessKey ID and AccessKey Secret in the console.

import { Alipdns,schemaType,DNSDomainInfo, DNSLogger } from '@alidns/httpdns'

const AccountID = 'TODO: Replace with your Account ID from the console.';
const AccessKeyID = 'TODO: Replace with the AccessKey ID of the key you created in the "Access Configuration" section of the console.';
const AccessKeySecret = 'TODO: Replace with the AccessKey Secret of the key you created in the "Access Configuration" section of the console.';

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    // ************* Alibaba Cloud HTTPDNS SDK configuration - START *************
    DNSLogger.getInstance().setEnableLogger = true;
    let alipdns = Alipdns.getInstance();
    alipdns.Init(this.context,AccountID,AccessKeyID,AccessKeySecret);
    alipdns.setKeepAliveDomains(['your-domain-1.com','your-domain-2.com']);
    alipdns.setSchemaType(schemaType.https);
    alipdns.preLoadDomains(alipdns.QTYPE_V4,['your-domain-1.com','your-domain-2.com','your-domain-3.com']);
    // ************* Alibaba Cloud HTTPDNS SDK configuration - END *************
  }

  // Other code omitted
}

API

1. Account ID and authentication

The Account ID is a required parameter. After you register your application in the console, a unique Account ID is generated for it. Authentication secures user identities and prevents unauthorized use. See Create a key to create an AccessKey in the console, and then set it in your app by using the following code:

Alipdns.getInstance().Init(this.context,AccountID,AccessKeyID,AccessKeySecret);
Warning
  • To prevent your Account ID, AccessKey ID, AccessKey Secret, or application runtime data from being exposed in logs, disable SDK debug logs in production environments.

  • To prevent credential theft from malicious decompilation, avoid passing them as plaintext in production environments. For example, you can encode or encrypt the credentials and then decode or decrypt them only when they are passed to the SDK. We also recommend obfuscating and hardening your application code. Otherwise, third parties can decompile your application to obtain these credentials.

2. Resolution protocol

The SDK lets you specify the protocol for DNS resolution requests. You can choose between HTTP and HTTPS by setting the scheme property.

By default, the SDK uses the HTTPS protocol for resolution, which we recommend for better security. HTTPDNS billing is based on the number of HTTP resolution requests, and HTTPS requests are billed at five times the rate of HTTP requests. Choose a scheme based on your security and cost requirements. To set the protocol, use the following code:

Alipdns.getInstance().setSchemaType(schemaType.https);

3. Domain cache persistence

When caching is enabled, you can configure domain cache persistence for specific domains. The SDK then automatically updates expired cache entries for these domains to keep the data current. However, this may increase the number of domain resolution requests and client-side traffic. If this feature is disabled, the cache is updated only when you call a resolution method. To configure domain cache persistence for specific domains, use the following code:

Alipdns.getInstance().setKeepAliveDomains(['your-domain-1.com','your-domain-2.com']);
Note
  • Advantages:

    • Updates records in a timely manner before the TTL expires.

    • Reduces first-resolution latency to 0 ms when combined with pre-resolution.

  • Disadvantage: If a cached entry's age exceeds 75% of its TTL, the SDK sends another request, which incurs additional fees.

4. Pre-resolution

Once the first resolution for a domain populates the cache, subsequent requests are resolved with zero latency. Therefore, we recommend using pre-resolution for domains your app is likely to need after startup.

Example:

Alipdns.getInstance().preLoadDomains(alipdns.QTYPE_V4,['your-domain-1.com','your-domain-2.com','your-domain-3.com']);

5. SDK debug logs

You can enable or disable SDK debug logs. Set the value to true to enable debug logs or false to disable them. Call this method before initializing the SDK.

DNSLogger.getInstance().setEnableLogger = true;

6. Enable HTTPDNS to local DNS

By default, the SDK automatically falls back to local DNS if HTTPDNS resolution fails.

Alipdns.getInstance().setEnableLocalDns(true); // By default, fallback to local DNS is enabled if HTTPDNS resolution fails.

7. Resolution timeout

The timeout property specifies the timeout for domain resolution. The default timeout is 3s, but you can customize this value. We recommend a setting between 2s and 5s.

Alipdns.getInstance().setTimeout(3); // The default timeout is 3s.

8. Resolution methods

The SDK provides several methods for domain resolution. The following code provides an example:

/// Asynchronous resolution method
/// Alipdns.getInstance().QTYPE_V4: Specifies the IP address type to resolve: IPv4.
/// host: The domain to resolve.
/// ips: The callback that returns all IP addresses.
Alipdns.getInstance().getIpsByHostAsync(Alipdns.getInstance().QTYPE_V4, host,(ips:string[]) => {});

/// Synchronous resolution method that retrieves data from the cache.
/// Alipdns.getInstance().QTYPE_V4: Specifies the IP address type to resolve: IPv4.
/// host: The domain to resolve.
/// true: Specifies whether to allow the method to return expired IP results.
const result = Alipdns.getInstance().getIpsByHostFromCache(Alipdns.getInstance().QTYPE_V4,host,true);

Integrate with network requests

Use addCustomDnsRule

Before you initiate a network request, call the SDK's domain resolution API. Then, use the connection.addCustomDnsRule API to apply the result. This adds a custom host-to-IP mapping for the current application. The following code shows an example of an HTTP request:

import { http } from '@kit.NetworkKit';
import connection from '@ohos.net.connection';
import { Alipdns,schemaType,DNSDomainInfo } from '@alidns/httpdns'
import Url from '@ohos.url';

export async function requestWithHttpDns(url: string, options: http.HttpRequestOptions): Promise<http.HttpResponse> {
  let urlObject = Url.URL.parseURL(url);
  const host = urlObject.hostname;
  // ************* Use HTTPDNS to resolve the domain name - START *************
  const result = Alipdns.getInstance().getIpsByHostFromCache(Alipdns.getInstance().QTYPE_V4,host,true);
  // ************* Use HTTPDNS to resolve the domain name - END *************
  // ************* Set DNS rules by using the system API - START *************
  try {
    await connection.removeCustomDnsRule(host);
  } catch (ignored) {
  }
  if (result.length ?? 0 > 0) {
    await connection.addCustomDnsRule(host, result);
  } else {
    console.log(`HTTPDNS resolution returned no result. DNS rule is not set.`);
  }
  // ************* Set DNS rules by using the system API - END *************
  // ************* Initiate a network request by using the system API - START *************
  const httpRequest = http.createHttp();
  return httpRequest.request(url, options);
  // ************* Initiate a network request by using the system API - END *************
}
Important

Custom DNS rules in HarmonyOS

HarmonyOS provides the following APIs for you to customize DNS resolution rules: addCustomDnsRule, removeCustomDnsRule, and clearCustomDnsRules.

The addCustomDnsRule API lets your application add custom mappings between hosts and their corresponding IP addresses.

The removeCustomDnsRule API lets your application delete the custom DNS rule for a specified host.

The clearCustomDnsRules API lets your application delete all custom DNS rules.

Therefore, if you want to customize DNS rules for network requests, set the rules by using these APIs before you initiate the network requests.

dnsRules with the Remote Communication Kit

When you use the Remote Communication Kit package to make network requests, first resolve the domain with the SDK. Then, apply the result by configuring the dnsRules field. The following code shows an example of a fetch request:

import { Alipdns,schemaType,DNSDomainInfo } from '@alidns/httpdns'
import { rcp } from '@kit.RemoteCommunicationKit';
import Url from '@ohos.url';

export async function rcpWithHttpDns(url: string): Promise<rcp.Response> {
  let urlObject = Url.URL.parseURL(url);
  const host = urlObject.hostname;
  // ************* Use HTTPDNS to resolve the domain and get the IP addresses - START *************
  const result = Alipdns.getInstance().getIpsByHostFromCache(Alipdns.getInstance().QTYPE_V4,host,true);
  // ************* Use HTTPDNS to resolve the domain and get the IP addresses - END *************
  const request = new rcp.Request(url, "GET");
  if (result.length ?? 0 > 0) {
      request.configuration = {
        dns: {
          // ************* Set IP addresses by using dnsRules - START *************
          dnsRules: [{ host, port: 443, ipAddresses: result },{ host, port: 80, ipAddresses: result }]
          // ************* Set IP addresses by using dnsRules - END *************
        }
      }
    }
  // ************* Initiate a network request by using the system API - START *************
  const session = rcp.createSession();
  return session.fetch(request);
  // ************* Initiate a network request by using the system API - END *************
}

Domain resolution best practices

Combine pre-resolution with expired responses for optimal performance.

In high-performance network scenarios, you can combine pre-resolution with a strategy of using expired cache entries. This combination significantly improves DNS resolution speed and can even achieve "zero-latency" resolution.

With the SDK's built-in caching mechanism, subsequent resolution requests for a domain can directly hit the cache after pre-resolution is complete. This avoids network round-trips and significantly improves the user experience.

1. Pre-resolution

Enable caching and pre-resolve critical domains. We recommend performing this operation when the app starts.

In the onCreate() method of EntryAbility, proactively resolve the domain names used in your service and cache the results in local memory.

1. For IPv4-only scenarios

// For IPv4-only scenarios
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');

    let alipdns = Alipdns.getInstance();
    alipdns.Init(this.context,AccountID,AccessKeyID,AccessKeySecret);
    // Pre-resolve A records (IPv4). 
    alipdns.preLoadDomains(alipdns.QTYPE_V4,['your-domain-to-preload-1.com','your-domain-to-preload-2.com']);
}

2. For IPv6 scenarios

// For scenarios that require IPv6 support
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');

    let alipdns = Alipdns.getInstance();
    alipdns.Init(this.context,AccountID,AccessKeyID,AccessKeySecret);
    // Pre-resolve A and AAAA records (IPv4 and IPv6).  
    alipdns.preLoadDomains(alipdns.QTYPE_Auto,['your-domain-to-preload-1.com','your-domain-to-preload-2.com']);
}

2. Allow expired responses

When you resolve a domain, prioritize using the cache, allowing the use of expired but still-valid records. This way, even if the TTL of a record has expired, the result can be returned immediately as long as the cache is not cleared. This achieves "zero-wait" resolution.

1. For IPv4-only scenarios

    // For IPv4-only scenarios
    
    // ************* Use HTTPDNS to resolve the domain name - START *************
    // Resolve A records (IPv4).
    let finalIps = await this.resolverHost(Alipdns.getInstance().QTYPE_V4,host);
    // ************* Use HTTPDNS to resolve the domain name - END *************
    
  /**
   * HTTPDNS domain resolution (cache-first with network fallback)
   * @param qtype - The DNS query type, such as Alipdns.getInstance().QTYPE_V4 for A records.
   * @param host - The destination domain.
   * @returns An array of successfully resolved IP addresses.
   */
  async resolverHost(qtype: string, host: string): Promise<string[]> {
    // ************* HTTPDNS resolution: Cache with network fallback *************
    let finalIps: string[] = [];

    // 1. Prioritize retrieving the IP address from the cache. The third parameter is set to true to allow returning expired but available records.
    try {
      const cacheResult = Alipdns.getInstance().getIpsByHostFromCache(qtype, host, true);
      // Validate the cache result.
      if (Array.isArray(cacheResult) && cacheResult.length > 0) {
        finalIps = cacheResult;
        console.log(`pdns: [Cache hit] Domain ${host} resolved to: ${finalIps.join(', ')}`);
      } else {
        console.log(`pdns: [Cache miss/invalid] Domain ${host}. Initiating network request.`);
      }
    } catch (e) {
      console.warn(`pdns: Cache query exception: ${e?.message || e}`);
    }

    // 2. If the cache is invalid, initiate a network request.
    if (finalIps.length === 0) {
      try {
        finalIps = await this.getIpsFromNetwork(qtype, host);
        if (finalIps.length > 0) {
          console.log(`pdns: [Network request successful] Domain ${host} resolved to: ${finalIps.join(', ')}`);
        } else {
          console.warn(`pdns: [Network request] Domain ${host} returned an empty result.`);
        }
      } catch (err) {
        console.error(`pdns: [Network request failed] Domain ${host}: ${err?.message || JSON.stringify(err)}`);
        // Keep finalIps as an empty array and fall back to the system DNS.
      }
    }
    return finalIps;
  }

  // If no cache is available, send a network request to resolve the domain and get the IP address.
  getIpsFromNetwork(qtype: string, domain: string): Promise<string[]> {
    return new Promise((resolve) => {
      Alipdns.getInstance().getIpsByHostAsync(qtype, domain, (ips: string[]) => {
        if (Array.isArray(ips)) {
          resolve(ips);
        } else {
          resolve([]);
        }
      });
    });
  }

2. For IPv6 scenarios

    // For scenarios that require IPv6 support
    
    // ************* Use HTTPDNS to resolve the domain name - START *************
    // Resolve A and AAAA records (IPv4 and IPv6).
    let finalIps = await this.resolverHost(Alipdns.getInstance().QTYPE_Auto,host);
    // ************* Use HTTPDNS to resolve the domain name - END *************
    
  /**
   * HTTPDNS domain resolution (cache-first with network fallback)
   * @param qtype - The DNS query type, such as Alipdns.getInstance().QTYPE_Auto for A and AAAA records.
   * @param host - The destination domain.
   * @returns An array of successfully resolved IP addresses.
   */
  async resolverHost(qtype: string, host: string): Promise<string[]> {
    // ************* HTTPDNS resolution: Cache with network fallback *************
    let finalIps: string[] = [];

    // 1. Prioritize retrieving the IP address from the cache. The third parameter is set to true to allow returning expired but available records.
    try {
      const cacheResult = Alipdns.getInstance().getIpsByHostFromCache(qtype, host, true);
      // Validate the cache result.
      if (Array.isArray(cacheResult) && cacheResult.length > 0) {
        finalIps = cacheResult;
        console.log(`pdns: [Cache hit] Domain ${host} resolved to: ${finalIps.join(', ')}`);
      } else {
        console.log(`pdns: [Cache miss/invalid] Domain ${host}. Initiating network request.`);
      }
    } catch (e) {
      console.warn(`pdns: Cache query exception: ${e?.message || e}`);
    }

    // 2. If the cache is invalid, initiate a network request.
    if (finalIps.length === 0) {
      try {
        finalIps = await this.getIpsFromNetwork(qtype, host);
        if (finalIps.length > 0) {
          console.log(`pdns: [Network request successful] Domain ${host} resolved to: ${finalIps.join(', ')}`);
        } else {
          console.warn(`pdns: [Network request] Domain ${host} returned an empty result.`);
        }
      } catch (err) {
        console.error(`pdns: [Network request failed] Domain ${host}: ${err?.message || JSON.stringify(err)}`);
        // Keep finalIps as an empty array and fall back to the system DNS.
      }
    }
    return finalIps;
  }

  // If no cache is available, send a network request to resolve the domain and get the IP address.
  getIpsFromNetwork(qtype: string, domain: string): Promise<string[]> {
    return new Promise((resolve) => {
      Alipdns.getInstance().getIpsByHostAsync(qtype, domain, (ips: string[]) => {
        if (Array.isArray(ips)) {
          resolve(ips);
        } else {
          resolve([]);
        }
      });
    });
  }

On-premises DNS

The HTTPDNS Harmony SDK v2.0.0 and later supports the private deployment of on-premises DNS.

The on-premises DNS mode is ideal for scenarios with strict requirements for data compliance and custom resolution policies, such as the finance, government, and large-scale internet sectors. The SDK supports four typical deployment modes: public cloud DNS only, on-premises DNS only, and two hybrid primary/standby modes where public cloud DNS and on-premises DNS can serve as a fallback for each other. This flexibility accommodates diverse service architectures.

Core capabilities

  • Private deployment support: You can configure on-premises DNS service endpoints by using IPv4 or IPv6 addresses, or hostnames.

  • Mutual authentication mechanism: Requests are signed using customer-specific accessKeyId and accessKeySecret to ensure communication security.

  • Circuit breaking and health check: If an on-premises DNS node fails three or more consecutive times, circuit breaking is automatically triggered. The SDK then uses the specified healthCheckDomain to probe its availability every minute. After the node recovers, it is automatically re-enabled.

  • Intelligent fallback: When the primary DNS (public cloud DNS or on-premises DNS) fails more than a specified number of times, the SDK automatically switches to the standby DNS. This ensures high availability for resolution.

  • Seamless API compatibility: The resolution API call is the same for both public cloud DNS and on-premises DNS, requiring no changes to your business logic.

Configuration

1. Public cloud DNS only

This mode is suitable for standard SaaS users who have not deployed an on-premises DNS.

let alipdns = Alipdns.getInstance();
alipdns.Init(this.context,AccountID,AccessKeyID,AccessKeySecret);

2. On-premises DNS only (private deployment)

This mode is suitable for customers who rely entirely on an on-premises DNS.

let alipdns = Alipdns.getInstance();
alipdns.InitFusionDNS(this.context,['1.1.X.X','2.2.X.X'],null, null,'443','your-health-check-domain.com','your-private-accessKeyId','your-private-accessKeySecret');

3. Public cloud primary, on-premises standby

If resolution from the primary Alibaba Cloud public HTTPDNS fails, the SDK automatically falls back to the on-premises DNS.

let alipdns = Alipdns.getInstance();

// Primary: public cloud DNS
alipdns.Init(this.context,AccountID,AccessKeyID,AccessKeySecret);
    
// Standby: on-premises DNS
alipdns.InitFusionDNS(this.context,['1.1.X.X','2.2.X.X'],null, null,'443','your-health-check-domain.com','your-private-accessKeyId','your-private-accessKeySecret');

4. On-premises primary, public cloud standby

If resolution from the primary on-premises DNS fails, the SDK automatically falls back to the Alibaba Cloud public cloud DNS.

let alipdns = Alipdns.getInstance();
    
// Primary: on-premises DNS
alipdns.InitFusionDNS(this.context,['1.1.X.X','2.2.X.X'],null, null,'443','your-health-check-domain.com','your-private-accessKeyId','your-private-accessKeySecret');

// Standby: public cloud DNS
alipdns.Init(this.context,AccountID,AccessKeyID,AccessKeySecret);

New APIs

To support private deployment and high-availability disaster recovery for on-premises DNS, the SDK provides the following new core APIs. You can use these interfaces to configure on-premises DNS services, control security policies, and implement automatic primary/standby fallback.

1. Configure endpoints and credentials

/** This method is for private deployments that use on-premises DNS. You do not need to call this method if you use only public DNS.
     *
     * Sets the server addresses and authentication credentials for the on-premises DNS.
     * You pass the addresses and credentials of your on-premises DNS servers through this API.
     * The SDK uses this information to initiate requests.
     * @param ctx The context.
     * @param serverIpv4Arr An array of IPv4 addresses. This can be null.
     * @param serverIpv6Arr An array of IPv6 addresses. This can be null.
     * @param serverHostArr An array of hostnames. This can be null.
     * @param port The service port, such as "443". If you pass null, the default port "443" is used.
     * @param healthCheckDomain The domain for health checks after circuit breaking. When a resolution service fails more than three consecutive times, circuit breaking is triggered, and the service's IP address enters the healthCheck state. Subsequent requests are not routed to this service.
     *                          A timer then probes the service's availability every minute by resolving the healthCheckDomain. If a probe is successful, the IP is marked as alive and can receive requests again.
     * @param accessKeyId The private AccessKey ID for authentication.
     * @param accessKeySecret The private AccessKey Secret for authentication.
     */
InitFusionDNS(
    ctx:Context,
    ipv4: string[] | null,
    ipv6: string[] | null,
    host: string[] | null,
    port: string | null,
    healthCheckDomain: string,
    accessKeyId: string,
    accessKeySecret: string
  )

2. Set fallback threshold

/** If you have configured both public cloud DNS and on-premises DNS, use this method to set the failure threshold that triggers an automatic fallback from the primary DNS to the standby DNS. You do not need to call this method if only one DNS type is configured.
   *
   * @param fallbackThreshold The number of failures. The default is 4 if the primary is a public cloud DNS, and 2 if the primary is an on-premises DNS.
   *  Valid values: 0 to 4. A value of 0 indicates an immediate fallback.
   */
   
setFallbackThreshold(fallbackThreshold:number);