Intercepting Filter
Posted by Dustin Boston .
The Intercepting Filter processes requests and responses before and after the main application logic. It works by defining a chain of filters that handle specific concerns. For example: logging, authentication, input validation, or data transformation. The Filter Manager executes each filter in sequence; This allows for modular and reusable processing steps.
References
Alur, D., Crupi, J., & Malks, D. (2003). Core JSEE patterns: Best practices and design strategies. Myrna Rivera.
Source Code Listing
code.ts
export class CustomRequest extends Request {
public attributes: Record<string, any> = {};
}
export interface FilterChain {
doFilter(request: CustomRequest): Promise<void>;
}
export interface Filter {
doFilter(request: CustomRequest, chain: FilterChain): Promise<void>;
}
export class FilterManager {
private filters: Filter[] = [];
private filterChain: FilterChain;
constructor(filterChain: FilterChain) {
this.filterChain = filterChain;
}
addFilter(filter: Filter): void {
this.filters.push(filter);
}
async doFilter(request: CustomRequest): Promise<void> {
for (const filter of this.filters) {
await filter.doFilter(request, this.filterChain);
}
}
}
export class SimpleFilterChain implements FilterChain {
async doFilter(request: CustomRequest): Promise<void> {
console.log("Attributes", request.attributes);
}
}
export class JsonFilter implements Filter {
async doFilter(request: CustomRequest, chain: FilterChain): Promise<void> {
const contentType = request.headers.get("Content-Type");
if (contentType && contentType.includes("application/json")) {
const json = await request.json();
request.attributes["json"] = json;
}
chain.doFilter(request);
}
}
export class QueryFilter implements Filter {
async doFilter(request: CustomRequest, chain: FilterChain): Promise<void> {
const url = new URL(request.url);
const queryParams = new URLSearchParams(url.search);
request.attributes["query"] = queryParams;
chain.doFilter(request);
}
}
/**
* @example Start the server
* bun run server.ts
*
* @example
* curl -X POST "http://localhost:3000/echo?foo=1&bar=2" -H "Content-Type: application/json" -d '{"key": "value"}'
*/
Bun.serve({
routes: {
"/*": async (req) => {
// Wrap request in a custom object
const customRequest = new CustomRequest(req);
// Initialize filters and manager
const filterManager = new FilterManager(new SimpleFilterChain());
filterManager.addFilter(new QueryFilter());
filterManager.addFilter(new JsonFilter());
// Execute filters
await filterManager.doFilter(customRequest);
// Return a basic response
return new Response("Filters executed successfully");
},
},
});