restful-api-helper v0.0.1
restful-api-helper
Small utilities that help writing consistent and controlled API endpoints more easily.
The idea
restful-api-helper
helps you write better API, which I explored in this blog post. Subjectively, a good API has several key ideas:
- Consistency
- Has a
status
key to inform if the request is successful or not. - Envelope
data
. No API response data (payload) should be in the root. - Provide a user-readable message in the key
message
.
Obviously, this is a matter of debate. Therefore, restful-api-helper
will allow you to customize this in a future version. For now, an API response will have the following format:
{
"status": "ok / error",
"message": "a user-readable message",
"data": "<payload object>"
}
Installation
npm install restful-api-helper
Usage
restful-api-helper
supports any frameworks that have the signature (req, res)
. This includes Node.js HTTP Server, express.js, Next.js API Routes, etc.
Get started by importing the package:
api = require('restful-api-helper');
api(req, res, handlerObject)
req
and res
correspond to those in Node.js HTTP Server
, express.js
or Next.js API Routes
.
handlerObject
defines how each method is handled. It is an object in which:
keys
are the names of the methods (POST/GET/etc.)values
are functions that handle the corresponding methods
{
POST: theFunctionToHandlePostRequest
GET: theFunctionToHandleGetRequest
...otherMethods
}
The handle functions
A function to handle POST/GET/etc. request can either be synchronous or asynchronous (like Promise).
There are two ways to returns data
and message
.
Return the message
and payload
The function may returns:
- An object contains both or either
message
anddata
keys. - An object that contains the payload (data). It must not have the keys
message
anddata
. - A string which will be parsed as the
message
(in case there is no payload)
res.rSend(data, message, statusCode, headers)
Instead of returning a value, you may call res.rSend()
with:
data
: The payloadmessage
: The user-readable messagestatusCode
: The HTTP Status Code to set when response.headers
: An object - The headers to set when response.
You do not need to call return
as res.rSend()
will stop the execution immediately (The code after res.rSend
will not be executed).
Failed request
You can make the request a failure (incorrect password, permission error, etc.) at any time by:
throw new Error('The error message')
orreturn Promise.reject(Error('The error message'))
.- Calling
res.rSend.fail
instead ofres.rSend
(same arguments).
I have bundled several other Error objects for your convenience:
HttpError(code, message)
: The API will respond with amessage
, having the HTTP status code ofcode
.
Example
// Using commonjs
const api = require('restful-api-helper');
const { HttpError } = require('restful-api-helper');
// OR: Using ES6 Import
import api, { HttpError } from 'restful-api-helper';
const handler = (req, res) =>
api(req, res, {
GET: () => {
// Define the function to handle GET request
const postData = getPost(req.query.postId);
// Return the payload and a message
return {
data: postData,
message: `Fetched post with Id ${req.query.postId} successfully`,
};
// OR: Return just the payload
return postData;
// OR: Return just a message
return `Fetched post with Id ${req.query.postId} successfully... but I do not have the postData because this is just a message`;
},
PATCH: () => {
if (!isAuthenticated) {
throw new HttpError(401, 'You must be authenticated to update a post');
// OR
return Promise.reject(
HttpError(401, 'You must be authenticated to update a post')
);
// OR
res.rSend.fail(null, 'You must be authenticated to update a post', 401);
}
if (!req.body.postData) {
// you can throw a generic Error()
throw new Error('You need to write something to update a post');
}
// Let's say our updatePost function returns a promise
return updatePost(req.body.postId, req.body.postData).then(
() => 'Post updated!'
);
// You do not have to (and should not) catch the failed promise because it will be handled by restful-api-helper
},
});
// Usage in express.js
app.all('/api/posts', handler);
// Usage in Next.js (in pages/api/posts.js)
export default handler;
// usage it in node.js HTTP Server
const server = http.createServer((req, res) => {
// oh boy, no native routing solution...
if (req.url === '/api/posts') return handler(req, res);
});
Contributing
Please see my contributing.md.
License
5 years ago