Intercepting Filter On this page 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.
Code
Tests
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" );
}
}
});