Skip to main content

Wall

A Wall serves as the primary gatekeeper for every HTTP request in a Fort.js application. It determines whether a request should be allowed or rejected. Additionally, walls can perform tasks and pass data to the other Components.

In summary, Walls play a crucial role as the initial layer of a Fortjs application, controlling global aspects, executing tasks, and facilitating seamless data transfer to subsequent layers.

Use cases

  • Setting cors
  • Counting no of requests
  • Calculating some global data like ip address of the client

Wall members

A wall has following member-

Wall Events

A Wall in Fortjs has two essential events:

onIncoming

  • Description:

    • Called when a request is initiated.
    • If this event returns null, it means the request is allowed to enter. Otherwise, it is rejected with the returned result.
  • Sequential Execution:

    • If there are multiple walls, the onIncoming event is called in the order they are defined.

onOutgoing

  • Description:

    • Called when a request has been executed from component lifecycles.
    • This event is optional, and the result returned from this event is ignored.
    • onOutgoing is invoked with the returned response, allowing you to perform actions such as adding/removing headers or modifying the result.
  • Sequential Execution:

    • If there are multiple walls, the onOutgoing event is called in reverse order from how they are defined.

These events provide hooks for executing custom logic during the incoming and outgoing phases of a request's lifecycle. They enhance the flexibility of Walls in managing the flow and behavior of your Fort.js application.

Creating wall

A Wall is a class which extends the class "Wall" from fortjs.

import { Wall } from "fortjs"

export class AppWall extends Wall {

async onIncoming() {
console.log("request is asking for entering into the fort");
if (some condition) {
// block request
return textResult("This request is blocked by wall");
} else {
// allow request
return null;
}

}

async onOutgoing(result) {
// can be used to set headers, log events, modify returning result etc
console.log("request finished with result", result);
}
}

To use your custom wall, open the app.ts`` (or app.js`) file and add your wall to the walls` array.

import { Fort } from "fortjs";
import { UserController } from "./controllers";
import { AppWall } from "./walls/app_wall";

//add routes
Fort.routes = [{
controller: UserController,
path: "/user"
}]

// adding AppWall to the walls array
Fort.walls = [AppWall]

Use case examples

Setting cors

import { Wall } from 'fortjs';

export class HeaderWall extends Wall {
// This Wall is designed to handle CORS (Cross-Origin Resource Sharing) by setting appropriate headers
async onIncoming() {
// Set headers for CORS handling
this.response.setHeader(
'Access-Control-Allow-Headers',
'Access-Control-Allow-Headers, Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, Workspaceid',
);
this.response.setHeader('Access-Control-Allow-Credentials', 'true');
this.response.setHeader('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS, PATCH');

// Define allowed hosts
const ALLOWED_HOSTS = [
'http://localhost:8080'
];

// Check if the request origin is allowed
const { origin } = this.request.headers;
if (ALLOWED_HOSTS.indexOf(origin as string) >= 0) {
this.response.setHeader('Access-Control-Allow-Origin', origin);
}
}
}

Pass ip address of the incoming request to other components

import { Wall, textResult, HttpResult, assign } from "fortjs";

export class RequestLogger extends Wall {

private getIP(req) {
const ip = (req.headers['x-forwarded-for'] || '').split(',').pop() ||
req.connection.remoteAddress ||
req.socket.remoteAddress ||
req.connection.socket.remoteAddress;
return ip;
}

async onIncoming() {
this.data.ip = this.getIP(this.request);
}
}

In the above snippet, we are evaluating the IP address of the incoming request inside the onIncoming method of the wall. The obtained IP address is then set to the data property of the wall. This data value is passed to subsequent components, including controller methods, in the request flow.

How to modify returning result

The returning result of the request can be modified in onOutgoing method by replacing with a custom http result.

class AppWall extends Wall {
async onIncoming() {
return null;
}

async onOutgoing(result) {
Object.assign(result, textResult("result modified by wall outgoing");
}
}