Redirect Client SDK

The Redirect Client (RedirectClient from @uniformdev/redirect) provides programmatic access to Uniform's redirect management system. Use it to resolve redirects for incoming URLs, manage redirect rules, export redirects to external CDN formats, and build redirect resolution into custom middleware or edge functions.


npm install @uniformdev/redirect

import { RedirectClient } from "@uniformdev/redirect"; const redirectClient = new RedirectClient({ apiKey: process.env.UNIFORM_API_KEY, apiHost: process.env.UNIFORM_CLI_BASE_URL || "https://uniform.global", projectId: process.env.UNIFORM_PROJECT_ID, });

processUrlBestMatch finds the single best redirect match for a URL. This is the most common use case for redirect resolution in middleware:

const result = await redirectClient.processUrlBestMatch("/old-page"); if (result) { console.log("Redirect to:", result.url); console.log("Status code:", result.definition?.redirect.targetStatusCode); }

By default, processUrlBestMatch queries the API directly. This is suitable for low-traffic scenarios or when you don't need the full redirect set in memory:

const result = await redirectClient.processUrlBestMatch( "/old-page", undefined, // options false // useTrie = false (default) );

For high-traffic scenarios, pass true for useTrie to load all redirects into an in-memory trie structure for instant resolution:

const result = await redirectClient.processUrlBestMatch( "/old-page", undefined, // options true // useTrie = true );

warning

The trie approach loads all redirects into memory. This is fast but may use significant memory for large redirect sets (thousands of rules).

processUrlAllMatches returns all redirect rules that match a URL, not just the best one:

const results = await redirectClient.processUrlAllMatches("/old-page"); for (const result of results) { console.log("Match:", result.url, result.definition?.redirect.targetStatusCode); }

Both processUrlBestMatch and processUrlAllMatches return RedirectResult objects:

PropertyTypeDescription
urlstringThe resolved target URL
definitionRedirectDefinitionThe full redirect rule definition
labelstring(Optional) URL with wildcard segments highlighted in <em> tags
lastHopRedirectResult(Optional) Previous redirect in a chain

Each redirect definition contains:

PropertyTypeDescription
redirect.sourceUrlstringSource URL pattern
redirect.targetUrlstringTarget URL
redirect.targetStatusCodenumberHTTP status code (301, 302, etc.)
redirect.sourceMustMatchDomainbooleanWhether to enforce domain matching
redirect.sourceRetainQuerystringbooleanWhether to retain the source query string
redirect.targetMergeQuerystringbooleanWhether to merge query strings
redirect.targetPreserveIncomingDomainbooleanWhether to preserve the incoming domain
redirect.targetPreserveIncomingProtocolbooleanWhether to preserve the incoming protocol
metadata.createdstringCreation timestamp
metadata.modifiedstringLast modified timestamp

Both processUrlBestMatch and processUrlAllMatches accept an options object:

OptionTypeDescription
reversebooleanWhen true, finds the source URL that could have produced a given target URL
labelbooleanWhen true, returns a label property with wildcard segments highlighted in <em> tags

Useful for finding what source URL redirects to a given target:

const result = await redirectClient.processUrlBestMatch( "/new-page", { reverse: true }, true ); if (result) { console.log("This page is redirected from:", result.url); }

const redirect = await redirectClient.getRedirect({ id: "redirect-uuid", });
const response = await redirectClient.getRedirects({ sourceUrl: "/old-page", limit: 50, offset: 0, orderBy: "updated_at desc", }); for (const r of response.redirects) { console.log(r.redirect.sourceUrl, "->", r.redirect.targetUrl); }
ParameterTypeDescription
sourceUrlstringFilter by source URL
targetUrlstringFilter by target URL
searchstringFree-text search across URLs
idsstringComma-separated list of IDs
limitnumberMax results per page
offsetnumberPagination offset
orderBystringSort order (e.g., "updated_at desc")

For large redirect sets, use the async generator getAllRedirects which pages through results automatically:

for await (const redirect of redirectClient.getAllRedirects()) { console.log( redirect.redirect.sourceUrl, "->", redirect.redirect.targetUrl, `(${redirect.total} total)` ); }
const redirectId = await redirectClient.upsertRedirect({ sourceUrl: "/old-path", targetUrl: "/new-path", targetStatusCode: 301, }); console.log("Created/updated redirect:", redirectId);
await redirectClient.deleteRedirect("redirect-uuid");

Uniform redirects support wildcard segments using the :paramName syntax in source URLs. The matched segments are automatically substituted into the target URL:

SourceTargetExample
/blog/:slug/articles/:slug/blog/hello -> /articles/hello
/docs/:version/:page/documentation/:version/:page/docs/v2/intro -> /documentation/v2/intro

The client automatically follows redirect chains (where one redirect's target is another redirect's source) with built-in cycle detection. The lastHop property on the result provides the previous redirect in the chain:

const result = await redirectClient.processUrlBestMatch("/page-a", undefined, true); if (result?.lastHop) { console.log("Redirect chain detected:"); console.log(" First hop:", result.lastHop.url); console.log(" Final destination:", result.url); }

For high-performance scenarios, use the WithMemoryCache cache to keep redirect data in process memory with automatic background refresh:

import { RedirectClient, WithMemoryCache } from "@uniformdev/redirect"; const redirectClient = new RedirectClient({ apiKey: process.env.UNIFORM_API_KEY, projectId: process.env.UNIFORM_PROJECT_ID, dataCache: new WithMemoryCache({ prePopulate: true, // Load redirects into cache on initialization refreshRate: 60_000, // Refresh cache every 60 seconds }), });
OptionTypeDescription
prePopulatebooleanImmediately load redirect data into cache on client creation
refreshRatenumberInterval in milliseconds between automatic cache refreshes. The refresher pauses after 5 idle cycles with no cache reads.
await redirectClient.resetRedirectTrieDataCache();

Use RedirectFileConverter to export Uniform redirects into a format consumable by external CDN redirect systems (e.g., Vercel vercel.json, Netlify _redirects, Cloudflare):

import { RedirectFileConverter } from "@uniformdev/redirect"; import fs from "fs"; await RedirectFileConverter({ redirectEntryObject: (redirect) => ({ source: redirect.redirect.sourceUrl, destination: redirect.redirect.targetUrl, statusCode: redirect.redirect.targetStatusCode, }), wildcardConverter: ({ sourceUrl, targetUrl, sourceWildcards }) => ({ // Convert Uniform :param wildcards to your CDN's format sourceUrl: sourceUrl.replace(/:(\w+)/g, ":$1"), targetUrl: targetUrl.replace(/:(\w+)/g, ":$1"), }), writeFile: (redirects) => { fs.writeFileSync("redirects.json", JSON.stringify(redirects, null, 2)); console.log(`Exported ${redirects.length} redirects`); }, });

For scenarios requiring bypassing the API cache (e.g., admin tools, testing):

import { UncachedRedirectClient } from "@uniformdev/redirect"; const client = new UncachedRedirectClient({ apiKey: process.env.UNIFORM_API_KEY!, projectId: process.env.UNIFORM_PROJECT_ID!, });

The RedirectClient.validateRedirect static method checks whether a given URL matches a redirect definition, including domain and query string validation:

const isValid = RedirectClient.validateRedirect( "https://example.com/old-page?ref=123", redirectDefinition.redirect );

ExportPackageDescription
RedirectClient@uniformdev/redirectMain redirect client
UncachedRedirectClient@uniformdev/redirectCache-bypassing redirect client
WithMemoryCache@uniformdev/redirectIn-memory cache with auto-refresh
RedirectFileConverter@uniformdev/redirectExport redirects for external CDN formats
ExtractWildcards@uniformdev/redirectExtract wildcard segments from URLs
PathTrie@uniformdev/redirectTrie data structure for fast path matching