Implement URL signing for Edge Security Accelerator (ESA) using Edge Function templates. Three methods (A, B, and C) use MD5-based signatures to protect resources such as files and API endpoints. Each method includes code examples and parameter descriptions.
How it works
URL signing protects your origin resources by blocking requests that fail authentication.
Authentication methods
ESA provides three authentication methods (A, B, and C). Each compares an MD5 hash in the URL against one computed at the point of presence (POP). Matching hashes allow the request; mismatches deny it.
Method A
-
Signed URL format:
http://DomainName/Filename?auth_key={timestamp}-{rand}-{uid}-{md5hash}. Each field is defined in Parameters. -
Example code
import { createHash } from "node:crypto"; async function handleRequest(request) { const url = new URL(request.url); const path = url.pathname; const delta = 3600; const authKeyTypeA = url.searchParams.get('auth_key'); const privateKey = 'your_secret_key' const currentTimestamp = Math.floor(Date.now() / 1000); if (!authKeyTypeA) { return new Response('Unauthorized', { status: 401 }); } const [timestamp, rand, uid, signature] = authKeyTypeA.split('-'); if (currentTimestamp > parseInt(timestamp)+ delta) { return new Response('Link expired', { status: 403 }); } const signString = [path, timestamp, rand, uid, privateKey].join('-'); const md5 = createHash('md5').update(signString).digest('hex'); if (md5 !== signature) { return new Response('Unauthorized', { status: 401 }); } // If the resource is on another domain, fetch it and return the response // const yourUrl = `https://your-dcdn-domain.com${path}${url.search}` // const cdnResponse = await fetch(yourUrl, request) // return new Response(cdnResponse.body, cdnResponse) // In most cases, one origin fetch is sufficient return fetch(request.url) } export default { async fetch(request) { return handleRequest(request) } } -
Test and verify
-
Test a valid signed URL:
curl -I http://esa.aliyun.top/video/test.mp4?auth_key=1743388566-61b20a42d14f403ba3790d1b82502027-1-ee1c2c463a41ef4d72fcff5987f1e08c. A200response confirms successful authentication.
-
Test an unsigned URL:
curl -I http://esa.aliyun.top/test.mp4. A401response confirms the request was denied.
-
Method B
-
Signed URL format:
http://DomainName/{timestamp}/{md5hash}/FileName. Each field is defined in Parameters. -
Example code
import { createHash } from "node:crypto"; function handleRequest(request) { const url = new URL(request.url); const path = url.pathname; const parts = path.split('/'); const delta = 3600; const privateKey = 'your_secret_key' const currentTimestamp = Math.floor(Date.now() / 1000); const timestamp = parts[1]; const signature = parts[2]; if (!timestamp || !signature) { return new Response('Unauthorized', { status: 401 }); } const filePath = '/' + parts.slice(3).join('/'); const signString = [privateKey, timestamp, filePath].join(''); const md5 = createHash('md5').update(signString).digest('hex'); if (md5 !== signature) { return new Response('Unauthorized', { status: 401 }); } if (currentTimestamp > parseInt(timestamp)+ delta) { return new Response('Link expired', { status: 403 }); } // If the resource is on another domain, fetch it and return the response // const yourUrl = `https://your-dcdn-domain.com${path}${url.search}` // const cdnResponse = await fetch(yourUrl, request) // return new Response(cdnResponse.body, cdnResponse) // For Authentication Method B, reconstruct the original file path for the origin fetch. return fetch(url.origin + filePath) } export default { async fetch(request) { return handleRequest(request) } } -
Test and verify
-
Test a valid signed URL:
curl -I http://esa.aliyun.top/1743391454/f1415e282ae5ae650455e7b525231eff/test.mp4. A `200` response confirms successful authentication.
-
Test an unsigned URL:
http://esa.aliyun.top/test.mp4. A `401` response confirms the request was denied.
-
Method C
-
Signed URL format:
http://DomainName/{md5hash}/{timestamp}/FileName. Each field is defined in Parameters. -
Example code
import { createHash } from "node:crypto"; function handleRequest(request) { const url = new URL(request.url); const path = url.pathname; const parts = path.split('/'); const delta = 3600; const privateKey = 'your_secret_key' const currentTimestamp = Math.floor(Date.now() / 1000); const signature = parts[1]; const hexTime = parts[2]; const timestamp = parseInt(hexTime, 16); if (!hexTime || !signature) { return new Response('Unauthorized', { status: 401 }); } const filePath = '/' + parts.slice(3).join('/'); const signString = [privateKey, filePath, hexTime].join('-'); const md5 = createHash('md5').update(signString).digest('hex'); if (md5 !== signature) { return new Response('Unauthorized', { status: 401 }); } if (currentTimestamp > parseInt(timestamp)+ delta) { return new Response('Link expired', { status: 403 }); } // If the resource is on another domain, fetch it and return the response // const yourUrl = `https://your-dcdn-domain.com${path}${url.search}` // const cdnResponse = await fetch(yourUrl, request) // return new Response(cdnResponse.body, cdnResponse) // For Authentication Method C, reconstruct the original file path for the origin fetch. return fetch(url.origin + filePath) } export default { async fetch(request) { return handleRequest(request) } } -
Test and verify
-
Test a valid signed URL:
curl -I http://esa.aliyun.top/e59c904c85f19a48413b6283fc9d2f5a/1743400480/test.mp4. A `200` response confirms successful authentication.
-
Test an unsigned URL:
http://esa.aliyun.top/test.mp4. A `401` response confirms the request was denied.
-
Parameters
-
DomainName: The DNS record for your ESA site. -
timestamp: Unix timestamp (seconds since epoch) of when the signed URL was generated. Together with the TTL, this determines expiration. In Method C, the value is a hexadecimal string.NoteA signed URL expires at
timestampplus a validity period configured in ESA. The example code sets this period in the `delta` variable. -
FileName: Path to the requested file on the origin server. Must start with a forward slash (/). -
md5hash: A 32-character hexadecimal string (0-9, a-z) generated by the MD5 algorithm.The
md5hashis calculated as follows:-
Authentication Method A:
getMd5(FileName + "-" + timestamp + "-" + rand + "-" + uid + "-" + your_secret_key). -
Authentication Method B:
getMd5(your_secret_key + timestamp + FileName). -
Authentication Method C:
getMd5(your_secret_key + "-" + FileName + "-" + timestamp).
NoteYou must implement the
getMd5function manually. -
-
rand: A random string that makes each signed URL unique. Use a UUID without hyphens, such as477b3bbc253f467b8def6711128c7bec. -
uid: User ID. Set based on your business requirements. -
auth_key: Authentication string composed oftimestamp,rand,uid, andmd5hash.
