Functional REST endpoints

To create a functional--rather than class-based--REST API endpoint using the new ApiRouter, create an .es6 file in your plugin's rest/ folder, e.g. "UM/cmsbs-conf/cse/plugins/de.mycompany.restdemo/rest/demo.es6":

/// <reference path="../../../.vscode.js"/> import { RouterBuilder } from '@de.pinuts.apirouter/shared/routing.es6'; const list = (req, res) => { // Will be called when requesting GET <http://localhost:8080/cmsbs/rest/de.mycompany.restdemo.api/document> res.json({ message: 'list has been called' }); } const show = (req, res) => { // Will be called when requesting GET <http://localhost:8080/cmsbs/rest/de.mycompany.restdemo.api/document/123> res.json({ message: 'show has been called!', req.params }); } const update = (req, res) => { // Will be called when requesting PUT <http://localhost:8080/cmsbs/rest/de.mycompany.restdemo.api/document/123> res.json({ message: 'update has been called', req.params }); } const create = (req, res) => { // Will be called when requesting POST <http://localhost:8080/cmsbs/rest/de.mycompany.restdemo.api/document> res.json({ message: 'create has been called', req.params }); } const remove = (req, res) => { // Will be called when requesting DELETE <http://localhost:8080/cmsbs/rest/de.mycompany.restdemo.api/document/123> res.json({ message: 'remove has been called', req.params }); } const basicAuth = (username, password) => { const e = UM.getEntry('login_name', username); return e && e.testPassword(password) && e.get('entrytype') == 'apiuser'; } const routerBuilder = new RouterBuilder() // .protectFromForgery() .protectFromCaching() .allowCors() .handlePreflightRequests() // .requireOpenPassword() // .requireBasicAuth('api-realm', basicAuth) .get('/document/:id', show) .get('/document', list) .put('/document/:id', update) .post('/document', create) .delete('/document/:id', remove); de.mycompany.restdemo.apiController = routerBuilder.build();

protectFromForgery

protectFromForgery() tells the Router to accept POST, PUT and DELETE requests only if the request header X-CSRF-Token is provided and contains the correct CSRF Token.
The CSRF Token will be returned with every request as the response header named X-CSRF-Token to the client.

protectFromCaching

Sets the Cache-Control header appropriately to prevent client and reverse proxies from caching any of the responses.

allowCors

allowCors() tells the Router to send Access-Control-Allow headers for POST, PUT and DELETE requests.

The Access-Control-Allow-Origin header is set to the URL from the global CORS plugin instance that matches the given Origin header. If at least one such URL is given in the CORS plugin, the request will be denied (status 403) if none of the URLs matches the Origin.

Also see Consuming a REST API below.

handlePreflightRequests

handlePreflightRequests() tells the Router to respond to all OPTIONS (=preflight) requests by setting the appropriate Access-Control-Allow headers according to the global default settings defined in the CORS app instance.
This is necessary to allow POST, PUT and DELETE requests in a Cross Origin situation.

requireOpenPassword

requireOpenPassword tells the Router to expect the API token (aka “open password”) to be present in a request header named X-Cmsbs-Open.

This allows to provide basic protection for a non-public REST API.

requireBasicAuth

requireBasicAuth tells the Router to require Basic Auth for all routes.

The Basic Auth Realm and a callback to check the given credentials must be specified. (See const basicAuth in the example above.)

Consuming a REST API

REST APIs that make use of the allowCors() function require a special request header to be sent with every non-GET request:

  • X-CSRF-Safe or

  • X-CSRF-Token if protectFromForgery() has also been called.

This is true no matter what kind of client is used to perform the request.

If the client is a standard web browser, the presence of either of theses two headers proves that the request has not been triggered by posting a simple POST form, but rather is an XHR request, which ensures that CORS rules apply and Cross Site Request Forgery can be prohibited.