Integrate the HTTPDNS SDK into your Node.js application to replace local DNS resolution with faster, more reliable HTTPDNS resolution.
Node.js is a JavaScript runtime environment built on the Chrome V8 engine. It is widely used for server-side development, API building, and implementing the microservices model.
Alibaba Cloud provides the @alicloud-emas/httpdns SDK for the Node.js environment. You can integrate the SDK into your Node.js applications and follow the best practices in this topic to enable HTTPDNS resolution.
The following sections cover SDK usage and best practices.
Quick start
1.1 Activate the service
See Quick Start to activate HTTPDNS.
1.2 Obtain configurations
See Development Configurations to obtain your AccountId, SecretKey, and other information from the development configurations section of the EMAS console. This information is required to initialize the SDK.
Installation
Install the SDK using npm:
npm install @alicloud-emas/httpdns
Integration example:
For sample code and documentation, see the GitHub repository.
Configuration and usage
3.1 Initialize configurations
Initialize the SDK when your application starts. During initialization, configure your AccountId, SecretKey, and feature switches:
import { createClient } from '@alicloud-emas/httpdns';
const client = createClient({
accountId: 'your-account-id',
secretKey: 'your-secret-key',
enableExpiredIP: true,
enableHTTPS: true,
});
Setting the enableHTTPS parameter to true increases your billing costs. For more information, see the Product Billing document.
3.1.1 Log configuration
To output HTTPDNS logs during development, configure a logger during initialization:
const client = createClient({
...,
logger: console
});
3.2 Domain name resolution
3.2.1 Synchronous non-blocking resolution (Recommended)
This method returns cached results immediately without blocking program execution:
function resolve() {
const result = client.getHttpDnsResultForHostSyncNonBlocking('www.aliyun.com');
if (result) {
console.log('Resolution result:', result.ipv4);
console.log('Domain name:', result.domain);
console.log('IPv6:', result.ipv6);
} else {
console.log('Cache miss. Asynchronous resolution in progress...');
// Asynchronous resolution has started in the background. The next call will return the result.
}
}
3.2.2 Synchronous resolution
This method waits for the resolution to complete before returning a result:
async function resolve() {
try {
const result = await client.getHttpDnsResultForHostSync('www.aliyun.com');
console.log('Domain name:', result.domain);
console.log('IPv4:', result.ipv4);
console.log('IPv6:', result.ipv6);
} catch (error) {
console.error('Resolution failed:', error);
}
}
Node.js best practices
4.1 How it works
-
Create a custom DNS lookup function in the application.
-
For requests that need to be resolved using HTTPDNS, configure them to use the custom lookup function.
-
In the lookup function, retrieve the requested domain name and resolve it to an IP address using HTTPDNS.
-
In the lookup function, return the resolved IP address to initiate the actual request. This process avoids using the local DNS for resolution.
4.2 Network library integration
4.2.1 Axios integration
Integrate Axios using an agent. The core steps are as follows:
Step 1: Create a custom lookup function
const dns = require('dns');
function createHTTPDNSLookup(httpdnsClient) {
return (hostname, options, callback) => {
// Standardize parameters
if (typeof options === 'function') {
callback = options;
options = {};
}
// Ensure the callback exists
if (typeof callback !== 'function') {
throw new Error('callback must be a function');
}
// Use HTTPDNS to resolve the domain name
const result = httpdnsClient.getHttpDnsResultForHostSyncNonBlocking(hostname);
if (result) {
const hasIPv4 = result.ipv4 && result.ipv4.length > 0;
const hasIPv6 = result.ipv6 && result.ipv6.length > 0;
if (hasIPv4 || hasIPv6) {
if (options && options.all) {
// Return all IP addresses
const addresses = [
...(hasIPv4 ? result.ipv4.map(ip => ({ address: ip, family: 4 })) : []),
...(hasIPv6 ? result.ipv6.map(ip => ({ address: ip, family: 6 })) : [])
];
console.log(`[DNS Lookup] HTTPDNS resolved successfully: ${hostname} -> Returning all IP addresses (${addresses.length})`);
callback(null, addresses);
} else {
// Prioritize IPv4, then IPv6
if (hasIPv4) {
console.log(`[DNS Lookup] HTTPDNS resolved successfully: ${hostname} -> ${result.ipv4[0]} (IPv4)`);
callback(null, result.ipv4[0], 4);
} else {
console.log(`[DNS Lookup] HTTPDNS resolved successfully: ${hostname} -> ${result.ipv6[0]} (IPv6)`);
callback(null, result.ipv6[0], 6);
}
}
return;
}
}
console.log(`[DNS Lookup] No available IP from HTTPDNS. Falling back to system DNS for: ${hostname}`);
dns.lookup(hostname, options, callback);
};
}
Step 2: Create a custom agent
const https = require('https');
const httpsAgent = new https.Agent({
lookup: createHTTPDNSLookup(httpdnsClient),
keepAlive: true,
maxSockets: 10
});
Step 3: Create an Axios instance
const axios = require('axios');
const instance = axios.create({
httpsAgent: httpsAgent,
timeout: 10000
});
// Usage
const response = await instance.get('https://www.aliyun.com');
4.2.2 urllib integration
Integrate urllib using an agent. The core steps are as follows:
Step 1: Create a custom lookup function
const dns = require('dns');
function createHTTPDNSLookup(httpdnsClient) {
return (hostname, options, callback) => {
// Standardize parameters
if (typeof options === 'function') {
callback = options;
options = {};
}
// Ensure the callback exists
if (typeof callback !== 'function') {
throw new Error('callback must be a function');
}
// Use HTTPDNS to resolve the domain name
const result = httpdnsClient.getHttpDnsResultForHostSyncNonBlocking(hostname);
if (result) {
const hasIPv4 = result.ipv4 && result.ipv4.length > 0;
const hasIPv6 = result.ipv6 && result.ipv6.length > 0;
if (hasIPv4 || hasIPv6) {
if (options && options.all) {
// Return all IP addresses
const addresses = [
...(hasIPv4 ? result.ipv4.map(ip => ({ address: ip, family: 4 })) : []),
...(hasIPv6 ? result.ipv6.map(ip => ({ address: ip, family: 6 })) : [])
];
console.log(`[DNS Lookup] HTTPDNS resolved successfully: ${hostname} -> Returning all IP addresses (${addresses.length})`);
callback(null, addresses);
} else {
// Prioritize IPv4, then IPv6
if (hasIPv4) {
console.log(`[DNS Lookup] HTTPDNS resolved successfully: ${hostname} -> ${result.ipv4[0]} (IPv4)`);
callback(null, result.ipv4[0], 4);
} else {
console.log(`[DNS Lookup] HTTPDNS resolved successfully: ${hostname} -> ${result.ipv6[0]} (IPv6)`);
callback(null, result.ipv6[0], 6);
}
}
return;
}
}
console.log(`[DNS Lookup] No available IP from HTTPDNS. Falling back to system DNS for: ${hostname}`);
dns.lookup(hostname, options, callback);
};
}
Step 2: Create a custom agent
const urllib = require('urllib');
const https = require('https');
const httpsAgent = new https.Agent({
lookup: createHTTPDNSLookup(httpdnsClient),
keepAlive: true,
maxSockets: 10
});
Step 3: Send a request
async function request(url, options = {}) {
// Select an agent based on the URL type
if (url.startsWith('https://')) {
options.httpsAgent = httpsAgent;
} else {
options.agent = httpAgent; // Create an httpAgent similarly
}
options.timeout = options.timeout || 10000;
try {
return await urllib.request(url, options);
} catch (error) {
// Automatic retry logic
if (isConnectionError(error) && !options._retried) {
options._retried = true;
delete options.httpsAgent; // Retry using the system DNS
return await urllib.request(url, options);
}
throw error;
}
}
API
5.1 Initialization
Initialize the SDK when your application starts.
const { createClient } = require('@alicloud-emas/httpdns');
const client = createClient({
accountId: 'your-account-id',
secretKey: 'your-secret-key',
timeout: 5000, // Resolution timeout in milliseconds
maxRetries: 1, // Maximum number of retries
enableHTTPS: false, // Specifies whether to use HTTPS
enableCache: true, // Specifies whether to cache IP addresses
enableExpiredIP: true, // Specifies whether to allow the use of expired IP addresses
});
Parameters:
|
Parameter |
Type |
Required |
Features |
|
accountId |
String |
Required parameters |
AccountId |
|
secretKey |
String |
Optional parameters |
Signing key |
|
bootstrapIPs |
Array |
Optional parameters |
List of bootstrap IP addresses |
|
timeout |
Number |
Optional parameters |
Resolution timeout |
|
maxRetries |
Number |
Optional parameters |
Maximum number of retries |
|
enableHTTPS |
Boolean |
Optional Parameters |
Specifies whether to use HTTPS |
|
enableCache |
Boolean |
Optional parameters |
Specifies whether to cache IP addresses |
|
logger |
Object |
Optional parameters |
Logger |
|
enableExpiredIP |
Boolean |
Optional parameters |
Specifies whether to allow the use of expired IP addresses |
Setting the enableHTTPS parameter to true increases your billing costs. For more information, see the Product Billing document.
5.2 Pre-resolve domain names
Specify domain names to pre-resolve so the SDK resolves them in advance, reducing latency for subsequent requests.
// Set the pre-resolution list
client.setPreResolveHosts(['www.aliyun.com']);
5.3 Synchronous non-blocking resolution
Resolves a domain name and returns cached results immediately without blocking the process.
const result = client.getHttpDnsResultForHostSyncNonBlocking('www.aliyun.com');
if (result) {
console.log('Cached result:', result.ipv4);
}
Parameters:
|
Parameter |
Type |
Required |
Features |
|
domain |
String |
Required parameters |
Domain name |
|
options |
Object |
Optional parameters |
Resolution options |
Description of the returned JSON fields:
|
Field |
Type |
Features |
|
domain |
String |
Domain name |
|
ipv4 |
Array |
List of IPv4 addresses |
|
ipv6 |
Array |
List of IPv6 addresses |
|
ipv4Ttl |
Number |
IPv4 expiration time |
|
ipv6Ttl |
Number |
IPv6 expiration time |
|
ipv4Timestamp |
Date |
IPv4 resolution timestamp |
|
ipv6Timestamp |
Date |
IPv6 resolution timestamp |
5.4 Synchronous resolution
Resolves a domain name synchronously and waits for the result before returning.
const result = await client.getHttpDnsResultForHostSync('www.aliyun.com');
console.log('Resolution result:', result);
5.5 Client management
Check the client health status and manage its lifecycle.
// Check the client's health status
const isHealthy = client.isHealthy();
// Get the current list of service IP addresses
const serviceIPs = client.getServiceIPs();
// Manually update the service IP addresses
await client.updateServiceIPs();
// Shut down the client
await client.close();
Summary
The HTTPDNS SDK for Node.js provides high-performance, high-availability domain name resolution through network library integration. Key features include:
-
Easy to use: Provides simple API operations and supports both synchronous and synchronous non-blocking resolution.
-
High availability: Supports failover and downgrade policies to ensure service stability.
-
Performance optimization: Includes a built-in caching mechanism and connection reuse to improve resolution efficiency.
-
Secure and reliable: Supports authenticated resolution and HTTPS communication to ensure data security.
Follow these best practices to integrate HTTPDNS into your Node.js applications efficiently.