DEV Community

Sovan Kandar
Sovan Kandar

Posted on

Stop writing the same custom HTTP wrapper in every project

Every time I start a new frontend or full-stack project, the same ritual happens.

We install axios or grab native fetch, and within a few weeks, we find ourselves building a massive layer of custom wrappers, interceptors, and helpers around it. Why? Because out-of-the-box HTTP clients handle basic data fetching fine, but they completely ignore real-world app constraints like rapid user actions, state duplication, and client-side payload security.

Later, every project codebase ends up with its own "homegrown" network utility to solve four specific headaches.

1. In-Flight Request Flooding

Typical HTTP clients make repeated parallel requests to an API when a user double clicks a button or UI re-renders multiple times. You end up needing to write your own AbortController business logic and/or custom flag locks to avoid wasting any server CPU cycles.

2. Payload Security Boilerplate

In the event that you're handling sensitive customer information, medical records, or financial payloads, using HTTPS just in transit may not be sufficient. Typically, one has to import large cryptographic libraries and build a lot of request/response interceptors to implement the AES-GCM payload encryption on the client-side.

3. Basic TTL Caching

It doesn't have to be a 3 second GET double hit. However, implementing a simple in-memory cache for short-lived often requires adding on a whole state management library or complicated caching layers for something as simple as a request freshness.

4. Boilerplate HMAC Signing

If you need to sign requests for API security, you have to manually manipulate the header on all requests you send out, which is a bit cumbersome.

I was sick of duplicating and re-architecting the same 4 mechanisms into various codebases. I thought of combining everything into a single helper utility for each use case, but it seemed like too much work to me, so I just copied them into a single helper utility that was written first in TypeScript: PHTPS.

Let's look at how these common patterns look when incorporated into the network layer natively:

import { phtps } from 'phtps';

// Deduplication, TTL caching, and AES payload encryption out of the box
const response = await phtps.post('https://api.example.com/sensitive-data', {
  body: { accountId: '12345' },
  encrypt: true,       // Native AES-GCM client-side encryption
  dedupe: true,        // Automatically merges identical in-flight requests
  ttl: 5000            // In-memory cache for 5 seconds
});
Enter fullscreen mode Exit fullscreen mode

Not only these 4, PHTPS has 11 official plugin with proper documentation.

Interactive Playground & Documentation: https://phtps-app.vercel.app

How are you currently handling request deduplication and client-side encryption in your apps? Do you rely on custom wrappers, or do you handle it at the state management layer? I'd love to hear your approach in the comments below!

Top comments (1)

Collapse
 
sovan_kandar_cfc10d231218 profile image
Sovan Kandar

Whether you love this approach, hate it, or think I over-engineered the solution—I'm all ears! Feel free to tear the architecture apart, suggest features, or share how you handle these headaches in your own projects. Every critique helps me understand real-world workflows better!