Endpoint Handlers 101
👋 Hey, folks!
Today, we will be discussing endpoint handlers!

As the above diagram showcases, an endpoint handler is a kind of watcher and verifier of all the incoming requests to your server. It runs important security validations on every incoming request for any endpoint.
If everything goes well, the request is processed by the server, otherwise, a 400/403 Forbidden error is thrown based on the validation results to the client.
PS: Any errors starting with 4XX are related to client-side.
Build up your Endpoint Handler Typescript.
So this is my favourite part. We will see how to implement endpoint handlers.
First, let’s create an endpoint.
const getCatImages = async(req, res)=>{
if(req.method!=='GET') return res.status(400).end();
return res.status(200).json({url: "s3.images.blah/cat1.jpg"})
}export default getCatImages
We have created an endpoint that pretty much does the job of getting cat images.
Now we have the following restrictions.
1. Only Cat Lovers should get cat images.
2. Only Authenticated Users should get images.
3. Any user banned from getting cat images should receive forbidden request.
Now we could have built the endpoint, with these restrictions included.
But, what if, we have 100 endpoints? And when it’s time to update the restrictions, we probably need to update all those 100 endpoints.
There comes the role of endpoint handler.
So let’s build an endpoint handler which returns a “function returning promise”.
const EndpointHandler = async(endpoint, validations)=>{
return async(req,res) =>{
//Only Authenticated Users
if(validations.onlyAuthenticated){
const response = await checkAuth(req)
if(response.status !== 200)
return res.status(403).json({message: 'Unauthenticated User"})
}
//Cat Lovers Only Allowed
if(validations.onlyCatLovers)
{
const response = await CheckCatLovers(req.cookies)
if(response.status !== 200)
return res.status(403).json({message:"You are not a cat lover"}) } // Banned Users Check
if(validations.bannedUsersNotAllowed){
const response = await checkUserisBanned(req.cookies);
if(response.status !== 200)
return res.status(403).json({message:"You have been banned. Contact Group Admin"});
} }
}
export default EndpointHandler
So now, our endpoint checks the required validations.
Now we have to wrap this endpoint handler to our endpoint.
Let’s go back to the first snippet of code.
import EndpointHandler from './EndpointHandler';const getCatImages = async(req, res)=>{
if(req.method!=='GET') return res.status(400).end();
return res.status(200).json({url: "s3.images.blah/cat1.jpg"})
}export default EndpointHandler(getCatImages,
{
onlyAuthenticated:true,
onlyCatLovers:true,
bannedUsersNotAllowed:true
});
This is how we successfully, integrated the endpoint handler with an endpoint. This approach helps us to write better and more secure code, with a single source of validations file.
Benefits
You can focus more on writing business logic, and wrap the handler inside, without worrying about securing the endpoint.
You have a maintainable and easily debuggable codebase.
You know a best practice that you can apply anywhere
Cons
Nothing as such, but it is more suitable for services having consistent endpoints. Systems with diverse operations may need different endpoint handlers.
That’s all folks.
Would love to RT it.
More content at plainenglish.io. Sign up for our free weekly newsletter here.