URL Endpoint Functions let you run custom JavaScript code on incoming requests before ImageKit processes them. Use them for migrations where standard URL rewriters don't fit your legacy URL patterns.
Use cases: Migrate from legacy systems with custom URL formats, extract and convert transformation parameters from non-standard patterns, and handle complex path rewrites during consolidation.
How it works
Functions are created and published by the ImageKit team. Once published, you can attach them to any URL endpoint. Clone our GitHub template with support for multiple handlers, write your functions with tests, then contact ImageKit to deploy them. View and attach published functions in your dashboard.
The repository supports multiple handlers (handler1.js, handler2.js, etc.), each with its own test suite.
Execution order: Functions run first, then URL rewriters (if configured), so you can use both together. Functions have a 1-second timeout and support standard Node.js modules (crypto, url, querystring, path) but not external npm packages.
Function specification
function handler(url, urlPrefix, context) {
// Your logic here
return { url: modifiedUrl }
}
module.exports.handler = handler
Parameters:
url- Full request URL with protocol, hostname, path, and query stringurlPrefix- URL endpoint identifier (e.g.,"product-images")context.clientNumber- Client identifiercontext.logger- Logger for errors and info
Return values:
Continue processing:
{
url: string, // Required: Full URL with protocol and hostname
signURL: boolean // Optional: Sign the URL? (default: false)
}
Early response (stop processing):
{
status: number, // Required: HTTP status code
body: string | object, // Required: Response body
headers: Record<string, string> // Optional: Response headers
}
Examples
Example 1: Simple Path Rewrite for Migration
When migrating from a legacy system where URLs used different versioning paths:
function handler(url, urlPrefix, context) {
// Migrate old /v1/ paths to /v2/ paths
// Useful when you can't change URLs in your application
return {
url: url.replace("/v1/", "/v2/"),
}
}
module.exports.handler = handler
Use case: You have thousands of URLs in your CMS, emails, or printed materials pointing to /v1/ paths, but your new storage structure uses /v2/ paths.
Example 2: Parameter Extraction Pattern
Extract transformation parameters from legacy URL formats and convert them to ImageKit's format:
function handler(url, urlPrefix, context) {
// Convert: /w_100/h_200/image.jpg → /image.jpg?tr=w-100,h-200
const parsedUrl = new URL(url)
const params = []
const regex = /\/(w|h)_(\d+)/g
// Extract parameters and build transformation string
let cleanPath = parsedUrl.pathname.replace(regex, (match, key, value) => {
params.push(`${key}-${value}`)
return ""
})
// Clean up multiple slashes
cleanPath = cleanPath.replace(/\/{2,}/g, "/")
if (params.length > 0) {
parsedUrl.pathname = cleanPath
parsedUrl.search = `?tr=${params.join(",")}`
}
return {
url: parsedUrl.toString(),
signURL: true, // ImageKit will sign the modified URL
}
}
module.exports.handler = handler
Example transformation:
- Input:
https://ik.imagekit.io/demo/w_300/h_200/product.jpg - Output:
https://ik.imagekit.io/demo/product.jpg?tr=w-300,h-200
Use case: Migrating from a system that embedded transformation parameters in the path (like an older CDN or custom solution) where changing application code isn't feasible.
Example 3: Using with URL Rewriters
Combine URL Endpoint Functions with URL rewriters for complex migrations:
function handler(url, urlPrefix, context) {
const parsedUrl = new URL(url)
// First, remove your old CDN's specific prefix
parsedUrl.pathname = parsedUrl.pathname.replace(/^\/legacy-cdn\//, "/")
// The modified URL will then be processed by Cloudinary URL rewriter
// if you have it enabled on this endpoint
return {
url: parsedUrl.toString(),
}
}
module.exports.handler = handler
Use case: Migrating from a custom CDN setup that wrapped Cloudinary URLs. The function strips your custom prefix, then the Cloudinary URL rewriter handles the Cloudinary-specific transformations.
Example 4: Error Handling and Logging
Always handle errors and log for debugging:
function handler(url, urlPrefix, context) {
try {
context.logger.info({ url }, "Processing request")
const modifiedUrl = complexTransform(url)
context.logger.info({ modifiedUrl }, "Transform complete")
return { url: modifiedUrl }
} catch (error) {
context.logger.error({ error: error.message }, "Transform failed")
return { url } // Fallback to original
}
}
function complexTransform(url) {
// Your transformation logic
return url
}
module.exports.handler = handler
Development workflow
1. Clone the template repository
Clone our GitHub template which supports multiple handlers in one repository. Each handler follows the naming pattern handler1.js + handler1.test.js, handler2.js + handler2.test.js, etc. The template includes ready-to-use examples in the /examples folder, a Jest test suite, GitHub Actions CI/CD, and coverage reporting.
git clone https://github.com/imagekit-developer/url-endpoint-function-ACME.git cd url-endpoint-function-ACME npm install
2. Write and test your handlers
Create or modify handler files (e.g., handler1.js):
function handler(url, urlPrefix, context) {
// Your logic
return { url: modifiedUrl }
}
module.exports.handler = handler;
Add corresponding tests in handler1.test.js and run:
npm test # Run all tests npm run test:watch # Watch mode npm run test:coverage # With coverage
All handler*.js files are tested automatically by the CI pipeline.
3. Request deployment
Contact support@imagekit.io with your GitHub repository URL, the handler filename(s) you want published (e.g., handler1.js, handler2.js), function name(s) and descriptions, and target URL endpoints. The ImageKit team will create and publish your functions.
4. Attach to URL endpoints
Once published, view available functions in your dashboard and attach them to URL endpoints under "Advanced settings".
Combining with URL rewriters
Functions run before URL rewriters, enabling powerful combinations:
function handler(url, urlPrefix, context) {
// Strip legacy prefix
const modifiedUrl = url.replace("/legacy/media/", "/")
// URL then processed by Cloudinary rewriter (if enabled)
// which handles w_300,h_200 syntax
return { url: modifiedUrl }
}
module.exports.handler = handler
Functions vs URL Rewriters
| Feature | URL Rewriters | URL Endpoint Functions |
|---|---|---|
| Use case | Standard platform migrations (Cloudinary, Imgix, Akamai) | Custom legacy URL patterns |
| Configuration | Select from dropdown | Custom JavaScript code |
| Execution order | Second | First |
| Best for | Quick migrations from known platforms | Complex custom requirements |
Related resources
See also: URL Rewriters for Cloudinary, Imgix, and Akamai migrations, URL Endpoints for endpoint configuration, and Transformations for ImageKit transformation parameters.
Need help?
Contact support@imagekit.io for assistance with function development or deployment.