ejvm v1.0.5
EJVM
Express middleware written in Typescript for validating request-payloads against JSON schemas.
The motivation for building this library were these constraints: 1. It should be written in Typescript 2. It should use the current JSON schema standard 3. It should be as simple as possible 4. It should have reasonable defaults
Installation
yarn add ejvm
Note: EJVM supports draft-07 only!
Note: The middleware expects the
req.body
property to contain proper JSON. Use the body-parser middleware to handle this for you. Keep in mind that you must include the content-type headerContent-Type: application/json
in your requests.
Usage
Example application
This library includes a documented example application at src/example
. To run it, clone the repository,
install the dependencies and start the application:
$ git clone https://github.com/MrSchneepflug/ejvm
$ cd ejvm
$ yarn install
$ yarn example
Example request with curl
:
curl \
-X POST \
-H "Content-Type: application/json" \
-d '{"name": "some name"}' \
http://localhost:3000/persons
{"success":true}
Simple Example
Lets say you want to build a CRUD interface for persons. To add a new person you would POST a JSON payload describing a person to a /persons
endpoint.
First thing is to describe the desired schema for the person-payload. See http://json-schema.org/ for an in-depth explanation.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/schemas/person.json",
"type": "object",
"required": ["name"],
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "number"
}
}
}
Put this schema definition either in a separate .json
file or directly in your code.
// load schema from separate file ...
const schema = JSON.parse(fs.readFileSync("/path/to/schema.json", "utf8"));
// ... or define schema directly in your code.
const schema = {
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/schemas/person.json",
"type": "object",
[...]
};
You need to import the validate
and isJsonSchemaValidationError
functions. Also add the body-parser middleware.
import {validate, isJsonSchemaValidationError} from "ejvm";
import bodyParser from "body-parser";
Use the body-parser middleware before any route definition:
app.use(bodyParser.json());
Use the schema to create a new validation-middleware by calling the validate
function.
app.post("/persons", validate(schema), (req: Request, res: Response): void => {
// logic to store the person
});
Lastly, in order to catch the validation-errors you need to have an error-handler in place:
app.use((err: Error | JsonSchemaValidationError, req: Request, res: Response, next: NextFunction): void => {
if (isJsonSchemaValidationError(err)) {
// handle the error here, e.g.:
res.status(400);
res.json({
statusText: "Bad Request",
jsonSchemaValidation: true,
validation: err.validationErrors,
});
} else {
// this is not a JsonSchemaValidationError, so do not handle it here
// and let the next middleware/finalhandler handle it
next(err);
}
});
To actually add a new person you need to include valid JSON with a name
and optionally an age
property. Example request with curl
:
curl \
-X POST \
-H "Content-Type: application/json" \
-d '{"name": "some name", "age": 65}' \
http://localhost:3000/persons
Using multiple schemas
Sometimes it makes sense to use multiple schemas. For example if you want to reuse a specific schema several times.
Example
employee.json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/schemas/employee.json",
"type": "object",
"required": ["department", "person"],
"properties": {
"department": {
"type": "string"
},
"person": {
"$ref": "http://example.com/schemas/person.json"
}
}
}
person.json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/schemas/person.json",
"type": "object",
"required": ["name"],
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "number"
}
}
}
In this case you would pass an array with any additional schema as the second parameter to validate()
.
const employeeSchema = require("/path/to/employee.json");
const personSchema = require("/path/to/person.json");
app.post("/employees", validate(employeeSchema, [personSchema]), (req: Request, res: Response): void => {
// ...
});
Note: Pass the configuration object for EJVM as third parameter to
validate()
if you want to use additional schemas.
Tests
$ yarn install
$ yarn test