d2l-fetch: Fetch Middleware Wrapper
raw JSON →d2l-fetch is a JavaScript library that provides a middleware layer for the standard `window.fetch` API. It enables developers to intercept and modify requests and responses before they reach the network or are returned to the caller. This allows for centralized handling of concerns like authentication, caching, logging, and error handling. The current stable version is 2.7.0. While the release cadence is not explicitly stated, the package appears to be actively maintained, with regular updates. Its key differentiator lies in its straightforward, chainable middleware pattern, offering a flexible way to extend `fetch` behavior without deep polyfilling or direct modification of `window.fetch` itself, making it suitable for environments where `fetch` is natively available.
Common errors
error ReferenceError: d2lfetch is not defined ↓
import { d2lfetch } from 'd2l-fetch/src/index.js'; is at the top of your file. If using a global script, verify the <script> tag's src path is correct and that it has loaded before d2lfetch is accessed. error TypeError: Cannot read properties of undefined (reading 'headers') (or similar for Request/Response properties) ↓
(request, next) => {...} and that next(request) is called. If you modify the request/response, ensure you return a valid Request or Response object or a Promise resolving to one. error Unhandled Promise Rejection: TypeError: Failed to fetch (or network error) ↓
window.fetch from running. Check the request object's URL, headers, and method within a middleware to ensure it's well-formed before next(request) is called. Warnings
gotcha When using middleware, ensure each middleware function explicitly returns the result of `next(request)` or a Promise representing an early exit. Failing to return `next(request)` will cause the middleware chain to break and the `window.fetch` call to not be executed, often leading to unresolved promises or unexpected behavior in subsequent middleware. ↓
gotcha Mixing global script imports (`<script type="module" src="...">`) with ES module imports (`import { d2lfetch } from '...'`) can lead to two separate instances of `d2lfetch` being created in the application, resulting in middleware being registered with one instance but `fetch` being called on another, or global scope pollution conflicts. ↓
gotcha Early exiting from the middleware chain by returning a Promise (e.g., `Promise.resolve(new Response())`) will prevent all subsequent middleware and the underlying `window.fetch` call from executing. While useful for caching or mock responses, ensure this is the intended behavior. ↓
Install
npm install d2l-fetch yarn add d2l-fetch pnpm add d2l-fetch Imports
- d2lfetch (global) wrong
import { d2lfetch } from 'd2l-fetch'; // If used after global scriptcorrect<script type="module" src="../d2l-fetch/d2l-fetch.js"></script> // d2lfetch is now available globally - d2lfetch wrong
import d2lfetch from 'd2l-fetch'; const d2lfetch = require('d2l-fetch');correctimport { d2lfetch } from 'd2l-fetch/src/index.js'; - Middleware Function wrong
const myMiddleware = async (request, next) => { /* ... */ return next(); };correctconst myMiddleware = (request, next) => { /* ... */ return next(request); };
Quickstart
import { d2lfetch } from 'd2l-fetch/src/index.js';
const authMiddleware = (request, next) => {
console.log('Auth Middleware: Adding Authorization header...');
request.headers.set('Authorization', `Bearer ${process.env.AUTH_TOKEN ?? 'your-jwt-here'}`);
return next(request);
};
const loggingMiddleware = async (request, next) => {
console.log(`Logging Middleware: Request to ${request.url}`);
try {
const response = await next(request);
console.log(`Logging Middleware: Received response for ${request.url} with status ${response.status}`);
return response;
} catch (error) {
console.error(`Logging Middleware: Request to ${request.url} failed:`, error);
throw error;
}
};
d2lfetch.use({ name: 'authMiddleware', fn: authMiddleware });
d2lfetch.use({ name: 'loggingMiddleware', fn: loggingMiddleware });
async function fetchData() {
try {
const request = new Request('https://api.example.com/data', {
method: 'GET',
headers: { 'Content-Type': 'application/json' }
});
const response = await d2lfetch.fetch(request);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
console.log('Fetched data:', data);
return data;
} catch (error) {
console.error('Failed to fetch data:', error);
throw error;
}
}
// Example usage (replace with actual API endpoint and token)
fetchData();