cacheable-lookup

repository·master·Indexed 42 days ago

https://github.com/szmarczak/cacheable-lookup

A cacheable version of Node.js's dns.lookup() that respects TTL (Time To Live) to improve performance for applications making frequent HTTP requests. Version 7.0.0 provides a CacheableLookup class that can be passed to HTTP request options or installed globally on HTTP/HTTPS agents. It supports custom cache implementations (such as QuickLRU), configurable maxTtl, and provides both Promise-based (lookupAsync) and callback-style (lookup) APIs.

Tokens
4.1K
Snippets
14
Records
20
Agent score
53%

What's inside cacheable-lookup

  1. Configure CacheableLookup options

    master

    When instantiating new CacheableLookup(options), you can provide several configuration options to control caching behavior:

    • cache: A Map or Keyv instance used for storage. Default is new Map().
      • Tip: Use QuickLRU for a Map-compatible way to limit cache size.
    • maxTtl: The maximum lifetime of entries in seconds. Default is Infinity. Setting to 0 disables caching.
    • fallbackDuration: Time in seconds to use dns.lookup() directly when the DNS server returns ENOTFOUND or ENODATA. Default is 3600.
    • errorTtl: How long to remember queries that threw ENOTFOUND or ENODATA in seconds. Default is 0.15.
    • resolver: A dns.Resolver or dns.promises.Resolver instance. Default is new dns.promises.Resolver().
    • lookup: The fallback function to use when the DNS server responds with ENOTFOUND or ENODATA. Default is dns.lookup. If you don't query internal hostnames, it is recommended to set this to false.
    import http from 'node:http';
    import CacheableLookup from 'cacheable-lookup';
    import QuickLRU from 'quick-lru';
    
    const cacheable = new CacheableLookup({
    	cache: new QuickLRU({maxSize: 1000})
    });
    
    http.get('http://example.com', {lookup: cacheable.lookup}, response => {
    	// Handle the response here
    });
  2. Attach CacheableLookup to an Agent

    master

    Instead of passing the lookup function to every request, you can attach a CacheableLookup instance to a global HTTP or HTTPS agent using the .install() method. This will automatically apply the cached lookup to all requests made via those agents.

    import http from 'node:http';
    import https from 'node:https';
    import CacheableLookup from 'cacheable-lookup';
    
    const cacheable = new CacheableLookup();
    
    cacheable.install(http.globalAgent);
    cacheable.install(https.globalAgent);
    
    http.get('http://example.com', response => {
    	// Handle the response here
    });
  3. Use CacheableLookup with HTTP requests

    master

    You can use CacheableLookup to cache DNS lookups for HTTP requests by passing cacheable.lookup to the lookup option of an HTTP request.

    import http from 'node:http';
    import CacheableLookup from 'cacheable-lookup';
    
    const cacheable = new CacheableLookup();
    
    http.get('http://example.com', {lookup: cacheable.lookup}, response => {
    	// Handle the response here
    });
  4. Configure cache size with QuickLRU

    master

    To prevent memory issues and limit the amount of cached entries, you can pass a QuickLRU instance to the cache option. QuickLRU is fully compatible with the Map API required by CacheableLookup.

    import http from 'node:http';
    import CacheableLookup from 'cacheable-lookup';
    import QuickLRU from 'quick-lru';
    
    const cacheable = new CacheableLookup({
    	cache: new QuickLRU({maxSize: 1000})
    });
    
    http.get('http://example.com', {lookup: cacheable.lookup}, response => {
    	// Handle the response here
    });
  5. new CacheableLookup(options)

    master

    Returns a new instance of CacheableLookup.

    Options (Type: object, Default: {}):

    OptionTypeDefaultDescription
    cacheMapnew Map()Custom cache instance. Using Keyv may drop performance by 10x and cause memory leaks.
    maxTtlnumberInfinityMax lifetime of entries in seconds. Set to 0 to disable caching.
    fallbackDurationnumber3600Seconds to use dns.lookup() directly when server returns ENOTFOUND/ENODATA.
    errorTtlnumber0.15Seconds to remember queries that threw ENOTFOUND or ENODATA.
    resolverdns.Resolvernew dns.promises.Resolver()DNS Resolver instance used for queries.
    lookupFunctiondns.lookupFallback function for ENOTFOUND/ENODATA. Set to false if not querying internal hostnames.
  6. Initialize CacheableLookup with Options

    master

    To use CacheableLookup, instantiate the CacheableLookup class with an optional Options object. This allows you to configure custom caching behavior, DNS resolvers, and fallback mechanisms.

    Configuration Options

    OptionTypeDefaultDescription
    cacheCacheInstanceundefinedA custom cache implementation. If undefined, a new one is created.
    maxTtlnumberInfinityLimits the cache time (TTL). Setting to 0 forces a new DNS query every time.
    resolverResolver | AsyncResolvernew dns.promises.Resolver()The DNS Resolver used for queries.
    fallbackDurationnumber3600Duration (in seconds) to use dns.lookup directly if the DNS server returns ENOTFOUND or ENODDATA. Set to 0 if not querying internal hostnames.
    errorTtlnumber0.15How long to remember failed queries (TTL in seconds). Independent of maxTtl.
    lookuptypeof lookup | falsedns.lookupThe fallback function used when fallbackDuration is active.

    CacheInstance Interface

    If providing a custom cache, it must implement:

    • set(hostname: string, entries: EntryObject[], ttl: number): TPromise<void | boolean | this>
    • get(hostname: string): TPromise<EntryObject[] | undefined>
    • delete(hostname: string): TPromise<boolean>
    • clear(): TPromise<void>
    import CacheableLookup from 'cacheable-lookup';
    
    const cacheableLookup = new CacheableLookup({
      maxTtl: 3600,
      errorTtl: 1,
      fallbackDuration: 0
    });
  7. Clear the cache

    master

    You can clear the internal cache of a CacheableLookup instance.

    • Clear all: Call clear() with no arguments to wipe the entire cache.
    • Clear specific hostname: Call clear(hostname) to remove only the entry for the specified hostname.
    // Clear everything
    cacheableLookup.clear();
    
    // Clear one host
    cacheableLookup.clear('example.com');
  8. Manage the Cache

    master

    The CacheableLookup instance provides methods to manually manage the internal cache state.

    • clear(hostname?: string): void: Clears the cache. If a hostname is provided, only that hostname's entries are removed. If no hostname is provided, the entire cache is emptied.
    • updateInterfaceInfo(): void: Call this when network interfaces change (e.g., toggling WiFi) to ensure the cache remains valid. Note that this only triggers clear() if a network interface is removed.
  9. Perform callback-style DNS lookups with lookup()

    master

    The lookup(hostname, options, callback) method provides a traditional Node.js callback API. It wraps the asynchronous lookup logic.

    Parameters

    • hostname: The hostname to resolve.
    • options: Can be a callback function, a number (representing the family), or an options object (same as lookupAsync).
    • callback: A function called with (err, address, family, expires, ttl, source) if options.all is false, or (err, entries) if options.all is true.

    Example

    cacheableLookup.lookup('example.com', { family: 4 }, (err, address, family, expires, ttl, source) => {
      if (err) throw err;
      console.log(address, source);
    });
  10. Perform asynchronous DNS lookups with lookupAsync()

    master

    Use lookupAsync(hostname, options) to retrieve a DNS entry from the cache or perform a new query if not present.

    Parameters

    • hostname: The hostname to resolve.
    • options: An object containing:
      • family: The IP version to filter for (4 or 6).
      • all: If true, returns an array of all matching entries instead of just the first one.
      • hints: Bitwise flags for special handling:
        • V4MAPPED: Maps IPv4 addresses to IPv6 (e.g., ::ffff:1.2.3.4).
        • ADDRCONFIG: Filters results based on the local system's configured interfaces.
        • ALL: Used in conjunction with V4MAPPED to return all entries.

    Returns

    Returns a Promise that resolves to a single entry object or an array of entry objects (if options.all is true). Each entry includes a source field (either 'cache' or 'query').

    If no entry is found, it throws an error with code ENOTFOUND.

    // Single entry
    const entry = await cacheableLookup.lookupAsync('example.com', { family: 4 });
    console.log(entry.address, entry.source);
    
    // All entries
    const entries = await cacheableLookup.lookupAsync('example.com', { all: true });
  11. Perform DNS lookups with CacheableLookup

    master

    The CacheableLookup class provides both callback-style and Promise-based methods for performing DNS lookups that utilize the internal cache.

    Asynchronous Lookups (lookupAsync)

    Use lookupAsync for modern async/await workflows. It returns either a single EntryObject or an array of EntryObjects depending on the all flag in LookupOptions.

    • lookupAsync(hostname: string): Promise<EntryObject>
    • lookupAsync(hostname: string, family: IPFamily): Promise<EntryObject>
    • lookupAsync(hostname: string, options: LookupOptions): Promise<EntryObject>
    • lookupAsync(hostname: string, options: LookupOptions & {all: true}): Promise<ReadonlyArray<EntryObject>>

    Callback Lookups (lookup)

    Use lookup for traditional Node.js callback patterns.

    • lookup(hostname: string, callback: (error: Error | null, address: string, family: IPFamily) => void): void
    • lookup(hostname: string, options: LookupOptions & {all: true}, callback: (error: Error | null, result: ReadonlyArray<EntryObject>) => void): void
    // Promise-based single entry
    const entry = await cacheableLookup.lookupAsync('example.com');
    console.log(entry.address);
    
    // Promise-based all entries
    const entries = await cacheableLookup.lookupAsync('example.com', { all: true });
    console.log(entries.map(e => e.address));
  12. Manage CacheableLookup servers

    master

    You can configure the DNS servers used by the CacheableLookup instance via the servers property. This interacts with the underlying resolver.

    • Set servers: Assign an array of server addresses to instance.servers. This will also clear the current cache.
    • Get servers: Access the current server configuration via instance.servers.
    cacheableLookup.servers = ['8.8.8.8', '8.8.4.4'];
    const currentServers = cacheableLookup.servers;