This documentation explains the different handler patterns supported by Azion Edge Functions and how to migrate between them.
The ES Modules pattern is the recommended way to structure your Edge Functions on Azion.
export default {
fetch: (request, env, ctx) => {
return new Response('Hello World');
},
firewall: (request, env, ctx) => {
// Firewall logic
ctx.deny();
}
};Advantages:
- Modern and clean syntax
- Native support in production
- Better performance
- Easy to test
The Service Worker pattern is maintained for legacy code compatibility.
addEventListener('fetch', (event) => {
event.respondWith(handleRequest(event.request));
});
addEventListener('firewall', (event) => {
// Firewall logic
event.deny(); // Block the request
});
async function handleRequest(request) {
return new Response('Hello World');
}Note: This pattern is considered legacy and we recommend migrating to ES Modules.
- request: Request - HTTP request object
- env: Object - Environment variables and bindings
- ctx: Object - Execution context
ctx.waitUntil(promise)- Extends the worker's lifetime
- request: Request - HTTP request object
- env: Object - Environment variables and bindings
- ctx: Object - Execution context
ctx.deny()- Blocks the request immediately (ES Modules pattern only)- If
ctx.deny()is not called, the request continues to the fetch handler
- event: FirewallEvent - Firewall event object
event.deny()- Blocks the request immediately (Service Worker pattern only)event.request- Access to the Request object- If
event.deny()is not called, the request continues to the fetch handler
export default {
fetch: async (request, env, ctx) => {
const url = new URL(request.url);
if (url.pathname === '/api/hello') {
return new Response(JSON.stringify({ message: 'Hello World' }), {
headers: { 'Content-Type': 'application/json' }
});
}
return new Response('Not Found', { status: 404 });
}
};export default {
fetch: async (request, env, ctx) => {
return new Response('Access granted');
},
firewall: async (request, env, ctx) => {
const clientIP = request.headers.get('CF-Connecting-IP');
// Block specific IPs
if (clientIP === '192.168.1.100') {
ctx.deny();
return;
}
// Continue to fetch handler
return;
}
};export default {
fetch: async (request, env, ctx) => {
// Use waitUntil for async tasks
ctx.waitUntil(logRequest(request));
return new Response('Hello World');
}
};
async function logRequest(request) {
// Log request asynchronously
console.log(`Request to: ${request.url}`);
}export default {
fetch: async (request, env, ctx) => {
return new Response('Access granted');
},
firewall: async (request, env, ctx) => {
const url = new URL(request.url);
const userAgent = request.headers.get('User-Agent');
const clientIP = request.headers.get('CF-Connecting-IP');
// Block bot requests
if (userAgent && userAgent.includes('bot')) {
ctx.deny();
return;
}
// Block specific paths
if (url.pathname.startsWith('/admin')) {
// Allow only from specific IP range
if (!clientIP || !clientIP.startsWith('192.168.')) {
ctx.deny();
return;
}
}
// Allow request to continue to fetch handler
return;
}
};addEventListener('fetch', (event) => {
event.respondWith(handleRequest(event.request));
});
addEventListener('firewall', (event) => {
const clientIP = event.request.headers.get('CF-Connecting-IP');
const userAgent = event.request.headers.get('User-Agent');
// Block bot requests
if (userAgent && userAgent.includes('bot')) {
event.deny();
return;
}
// Block specific IPs
if (clientIP === '192.168.1.100') {
event.deny();
return;
}
// Allow request to continue to fetch handler
});
async function handleRequest(request) {
return new Response('Hello World');
}addEventListener('fetch', (event) => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
return new Response('Hello World');
}export default {
fetch: async (request, env, ctx) => {
return new Response('Hello World');
}
};Some common patterns from other platforms are not directly supported:
// ❌ Direct function export
export default function(request) {
return new Response('Hello');
}
// ❌ Named exports
export function fetch(request) {
return new Response('Hello');
}
// ❌ No export
function handleRequest(request) {
return new Response('Hello');
}For these cases, use the recommended ES Modules Pattern.
This message appears when your code doesn't follow any of the supported patterns. To resolve:
-
Migrate to ES Modules (recommended):
export default { fetch };
-
Or use Service Worker (legacy):
addEventListener('fetch', (event) => { event.respondWith(handleRequest(event.request)); });
If you're having problems with "export" syntax, check:
- package.json contains
"type": "module" - Or rename file to
.mjs - Or use CommonJS:
module.exports = { fetch }