Skip to content

Endpoint Configurations

In order to encourage "Happy Path Programming" and make it easier for developers to validate request fully, the Acai comes with a host of built-in validations as well as the ability to extend with custom validations and middleware. See the full validation list here:

Examples

Don't like reading documentation? Then look at our examples, which can run locally! 🤓

Validation Configurations

requirement type description
requiredHeaders array every header in this array must be in the headers of request
availableHeaders array only headers in this array will be allowed in the request
requiredQuery array every item in the array is a required query string parameter
availableQuery array only items in this array are allowed in the request
requiredPath str when using parameters, this is the required parameters
requiredBody str references a JSschema component in your schemaFile
requiredResposne str references a JSschema component in your schemaFile
requiredAuth bool will trigger withAuth function defined in the router config
before func a custom function to be ran before your method function
after func a custom function to be ran after your method function
dataClass class a custom class that will be passed instead of the request obj
timeout int a timeout value in microseconds to stop endpoint from running
[custom-requirement] any see bottom of page

requiredHeaders

Info

Headers are case-sensitive, make sure your casing matches your expectations.

1
2
3
4
5
exports.requirements = {
    post: {
        requiredHeaders: ['x-onbehalf-of']
    }
};

availableHeaders

Warning

This is not recommended for frequent use as it raises errors for every header which does not conform to the array provided. Many browsers, http tools, and libraries will automatically add headers to request, unbeknownst to the user. By using this setting, you will force every user of the endpoint to take extra care with the headers provided and may result in poor API consumer experience.

1
2
3
4
5
exports.requirements = {
    post: {
        availableHeaders: ['x-onbehalf-of']
    }
};

requiredQuery

1
2
3
4
5
exports.requirements = {
    get: {
        requiredQuery: ['requester_id']
    }
};

availableQuery

1
2
3
4
5
exports.requirements = {
    get: {
        availableQuery: ['grower_email', 'grower_phone', 'grower_first', 'grower_last'],
    }
};

requiredPath

Warning

This is required if you are using dynamic routing (ex. {id}.js) with path parameters. The router will provide a path values in request.pathParams

1
2
3
4
5
exports.requirements = {
    put: {
        requiredPath: 'grower/{id}'
    }
};

requiredBody

Info

This is referencing a components.schemas section of your openapi.yml file defined in the schemaFile value in your router config.

1
2
3
4
5
exports.requirements = {
    post: {
        requiredBody: 'post-grower-request'
    }
};

requiredResponse

Info

This is referencing a components.schemas section of your openapi.yml file defined in the schemaFile value in your router config.

1
2
3
4
5
exports.requirements = {
    post: {
        requiredResponse: 'post-grower-response'
    }
};

requiredAuth

Info

This will trigger the function you provided in the router config under the withAuth configuration

1
2
3
4
5
exports.requirements = {
    post:{
        requiredAuth: true
    }
};

before

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
exports.requirements = {
    patch: {
        before: async (request, response, requirements) => {
            const result = await db.checkGrowerIdExists(request.pathParams.id);
            if (!result){
                response.setError('grower/{id}', `grower with id: ${id} does not exist.`);
            }
        }
    }
};

after

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
exports.requirements = {
    get: {
        after: async (request, response, requirements) => {
            const relations = await db.getRequesterRelations(request.headers['x-requester-id']);
            const results = []
            for (const grower in response.rawBody){
                if (relations.includes(grower.id)){
                    results.push(grower);
                }
            }
            response.body = results;
            return response;
        }
    }
};

dataClass

Info

Instead of getting a request and response as arguments passed to your API function, you will get an instance of the class you provided here

1
2
3
4
5
exports.requirements = {
    post: {
        dataClass: Grower
    }
};

timeout

Info

This value will OVERRIDE any value set in the global timeout settings, set in the router config

1
2
3
4
5
exports.requirements = {
    post: {
        timeout: 20000 // overrides other timeouts set in router config
    }
};

custom requirements (example)

Info

You can add as many custom requirements as you want, with any variable type you want, and they will be passed to your beforeAll, before, afterAll, after and withAuth middleware defined functions.

1
2
3
4
5
exports.requirements = {
    post:{
        myCustomBeforeAllPermission: {permission: 'allow-delete-grower'}
    }
};