
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
With Middlewall you can build plugable validation middlewares, Separate all validation functionality to different layer than your business logic, making a leaner, reusable, more readable code.
Working with Middlewall involve using
In a nutshell, with the given operators you're composing a single block of validation from multiple individual validation operations then you can reuse that single block validation or transforming it to a middleware.
Let say you're building an API that support reading shows, artists and venues all with pagination, each of the readable item type implemented on an individual controller.
Pagination in your API implemented with a single protocol, using 'page' and 'pageSize' provided as a query parameters,
in the following code piece we're creating a middleware to validate and parse 'page' and 'pageSize' parameters, it will be plugged before each API call used for reading.
import { compose, goTo, each } from 'middlewall';
import * as ops from 'middlewall';
const app = express();
app.use((err, req, res, next) => {
/* any found validation errors will end up here ..
for example: for the call '/show?page=-3&pageSize=100', err will look like :
{
"pass": false,
"errors": [
{
"pass": false,
"error": "value is not pass as a positive number",
"value": -3,
"path": "query.page",
"validation": "isPositive"
}
]
}
*/
});
const paginationValidator = compose(
// validate query.page is a string-number and if so parse it
ops.isIntegerString('page', // point to the target field
(page, req) => parseInt(page) || 1, // provide an if-pass cb
undefined, // a costume error massage can be provided
{ overwriteValue: true, optional: true, default: 1 } // setting field as optional and overwrite it with if-pass cb return value
),
ops.isPositive('page', undefined, undefined, { optional: true }),
// validate query.pageSize is a string-number and if so parse it
ops.isIntegerString('pageSize',
(pageSize, req) => parseInt(pageSize),
undefined,
{ overwriteValue: true, optional: true, default: 20 }),
ops.isBetween('pageSize', 1, 100),
).query(); // top target object is req.query.
app.get('/show', paginationValidator, (req, res, next) => {
/* pass all validations! continue your flow */
}
);
// and so on for '/artist' and '/venue' calls ..
Continue building your API validation layer, your API provides a filtering functionality base on dates, the parameters 'start' and 'end' provided with the range dates.
in the following code piece we're creating a middleware to validate the dates range could be something like :
static dateValidator = compose(
ops.isDateString('start', 'mm-dd-yyyy',
(start, req) => moment(start, 'mm-dd-yyyy'),
undefined,
{ overwriteValue: true, optional: true, default: moment().year(1970) }),
ops.isDateString('end', 'mm-dd-yyyy',
(end, req) => moment(end, 'mm-dd-yyyy'),
undefined,
{ overwriteValue: true, optional: true, default: moment().year(2100) }),
).query(); // top target object is req.query.
app.get('/show', paginationValidator, dateValidator, (req, res, next) => {
/* pass all validations! continue your flow
for example: for the call '/show?page=1&start=04-20-2015, req.query will look like :
{
"page": 1,
"start": "2019-08-08T21:04:00.000Z",
"end": "2100-08-09T11:10:43.251Z",
"pageSize": 20
}
*/
}
);
Now your API support post content functionalities, for that an authorization process must take place,
in the following code piece we're creating a custom authorization middleware for the incoming request and validate posed content.
const authHeaderValidator = compose(
ops.isExist('req.headers.authorization'),
ops.isStartWith(
'req.headers.authorization', 'Bearer ',
(auth: string) => auth.slice('Bearer '.length),
undefined, { overwriteValue: true }
),
ops.run('', // empty string meaning stay on the root object.
async ({ req, res }) => {
try {
const { authorization } = req.headers;
const decodedToken = await firebaseAdmin.auth().verifyIdToken(authorization);
if(!decodedToken || !decodedToken.uid) {
return false;
}
res.locals.uid = decodedToken.uid;
return true;
} catch (error) {
return false;
}
}, undefined, 'Authentication failed'
)
).args();
const showListValidator = compose(
ops.isArray('shows'), // validate body.shows is an array
goTo('shows', // navigate to body.shows
each( // perform the validations list on each of the items in the 'shows' array
ops.isAlpha('name'),
ops.isDateString('showDate', 'mm-dd-yyyy'),
ops.isBoolean('visible', undefined, undefined, { optional: true, default: true })
)
)
).body(); // top target object is req.body.
app.post('/show', authHeaderValidator, showListValidator, (req, res, next) => {
/* pass all validations! continue your flow */
}
);
Middlewall
encapsulate a collection of validation operations in a middleware compatible with express API.
Middlewall.prototype.args()
generate a middleware where the validation root object is an object structured {req: Request res: Response}.
Middlewall.prototype.req()
generate a middleware where the validation root object is the incoming request object.
Middlewall.prototype.body()
generate a middleware where the validation root object is the incoming request.body object.
Middlewall.prototype.query()
generate a middleware where the validation root object is the incoming request.query object.
Middlewall.prototype.params()
generate a middleware where the validation root object is the incoming request.params object.
Middlewall.prototype.headers()
generate a middleware where the validation root object is the incoming request.headers object.
Middlewall.prototype.locals()
generate a middleware where the validation root object is the incoming response.locals object.
Note:
Middleware class was not intended to be instantiate directly, instead use compose operator (see Usage section)Note :
AsyncBrickFn, the bricks are used for build up your middlewall.
Validation operators used for customize the validation operations.
compose(...bricks: Array<AsyncBrickFn | Middlewall>): Middlewall
Use to compose one or more validation operations to a Middlewall, function as a logical and.
and(...bricks: Array<AsyncBrickFn | Middlewall>): AsyncBrickFn
Use to reduce one or more validation to a single validation operation (a brick), function as a logical and.
or(...bricks: Array<AsyncBrickFn | Middlewall>): AsyncBrickFn
Use to reduce one or more validation to a single validation operation (a brick), function as a logical or.
goTo(path: string, ...bricks: Array<AsyncBrickFn | Middlewall>): AsyncBrickFn
Use to navigate inside the target object.
each(...bricks: Array<AsyncBrickFn | Middlewall>): AsyncBrickFn
Use to perform validation on each item in an array, where only all the items must pass the validation.
some(...bricks: Array<AsyncBrickFn | Middlewall>): AsyncBrickFn
Use to perform validation on each item in an array, where only one item must pass the validation.
Operations follow the same API structure in general,
different operations can receive different amount of parameters with different types.
The general structure:
operation(path: string, args1: any, args2: any, ... , ifPass?: IfPassFn, options?: ValidationOptions)
path: string
...args: Array<any>
ifPass?: IfPassFn
error?: string
options?: ValidationOptions
interface ValidationOptions
fields :
optional
booleanoverwriteValue
booleandefault
anyfunction IfPassFn
arguments :
target
anyroot
booleansoon ..
FAQs
Modulated validation library for express
The npm package middlewall receives a total of 0 weekly downloads. As such, middlewall popularity was classified as not popular.
We found that middlewall demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.