@safer-api/axios v1.1.0
@safer-api/axios
API Validation - Centralized & Simplified
Overview
The @safer-api/axios library lets you define request & response interceptors by http method & path.
While Axios provides interceptors to process requests and responses, it has no elegant way to do so conditionally per URL.
Example @safer-api/axios 'validation router'
// Create a wrapper for `/api/notes` service:
const axiosNotesApi = saferAxios({
`GET /api/notes`: {
response: (notes) => notes.every(note => validate_id_and_note(note)),
},
`POST /api/notes`: {
request: (data) => data?.id == undefined,
response: (data) => data.id !== undefined,
}
});It's similar in concept to Express Server/Router. You provide route handlers by path & method. So a GET /some/thing/ would be handled by something like: app.get('/some/thing', respondWithTheThing).
Install
npm install @safer-api/axios
yarn add @safer-api/axiosDesign Notes
- Centrally manage API validation by HTTP Method + Path.
- Runs Validation functions per HTTP
requestpayload and/orresponsebody. Any request to unrecognized paths will be allowed without any validation.
A Validation function matches
(errorDetails) => true | false | Error- Accept a JSON object.
- Succeed by returning any truthy value.
- Fail with either
throw Error('....')orreturn false.
There are 2 main modes of operation:
- Fail on Error. Breaks the flow of the Promise chain. Prevents bad data flowing in or out.
- Use cases: log unexpected data from 3rd party data providers to Sentry or DataDog, microservice-to-microservice integration code.
- Log Silently. A callback option can capture details about validation failures silently.
- Use cases: log failures to Sentry or DataDog, microservice-to-microservice integration code, update React/Redux state (form error messages).
Related Libraries
See @safer-api/fetch for a browser fetch and node-fetch compatible version of this library.
Example
Step 1/2: Define your path & function mapping
Choose the mode that fits your use case: Fail on Error or Log Silently.
Fail on Error
This configuration will bail out of the promise chain on any false-y return value or thrown error.
// `./src/services/notes.js`
import saferAxios from '@safer-api/axios';
export default saferAxios({
`GET /api/notes`: data => schema_id_and_note.parse(data),
`POST /api/notes`: {
request: (data) => schema_note.parse(data),
response: (data) => schema_id_and_note.parse(data),
}
}); // Note: no options - default behavior is to reject on error.Log Silently
To silently handle validation failures, we'll need to pass in an options parameter:
{ ignoreErrors: true, callback: (details) => console.info(details) }
// `./src/services/notes.js`
import saferAxios from '@safer-api/axios';
export default saferAxios({
`GET /api/notes`: data => schema_id_and_note.parse(data),
`POST /api/notes`: {
request: (data) => schema_note.parse(data),
response: (data) => schema_id_and_note.parse(data),
}
}, {
ignoreErrors: true,
callback: (details) => console.info(details),
});Step 2/2: Replace axios calls with new saferAxios wrapper
Use the module exported with saferAxios(pathConfig) just as you would axios(url, config), axios.get(url, config), etc.
// `./src/modules/notes.js`
import axiosNotesApi from './src/services/notes'
export const listNotes = () => axiosNotesApi('/api/notes');
export const createNote = (data) =>
axiosNotesApi('/api/notes', {method: 'post', data});
export const updateNote = (id, data) =>
axiosNotesApi(`/api/notes/${id}`, {method: 'post', data});TODO
- Support transforming payloads.
- Support full URL, w/ domain. (Query string pattern matching?)
- Dynamic path & validation interface. (
registerHandler(method, path, handler: fn | fn[]),appendHandler(method, path, handler: fn | fn[]),listHandlers(): PathMapping[]) - Chaining arrays of functions. (Or include a
pipelinecomposition example.)