{"id":17561,"library":"d2l-fetch","title":"d2l-fetch: Fetch Middleware Wrapper","description":"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.","status":"active","version":"2.7.0","language":"javascript","source_language":"en","source_url":null,"tags":["javascript"],"install":[{"cmd":"npm install d2l-fetch","lang":"bash","label":"npm"},{"cmd":"yarn add d2l-fetch","lang":"bash","label":"yarn"},{"cmd":"pnpm add d2l-fetch","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"This approach makes `d2lfetch` available on the global `window` object. Ensure the script path is correct relative to your HTML. Avoid mixing with ES module imports of the same symbol if unintended.","wrong":"import { d2lfetch } from 'd2l-fetch'; // If used after global script","symbol":"d2lfetch (global)","correct":"<script type=\"module\" src=\"../d2l-fetch/d2l-fetch.js\"></script>\n// d2lfetch is now available globally"},{"note":"The primary ES module import is a named export from the `src/index.js` entry point. It is not a default export and `require()` is not supported.","wrong":"import d2lfetch from 'd2l-fetch';\nconst d2lfetch = require('d2l-fetch');","symbol":"d2lfetch","correct":"import { d2lfetch } from 'd2l-fetch/src/index.js';"},{"note":"Middleware functions receive `request` and `next`. They *must* return the result of `next(request)` or a Promise (e.g., a `Response`) to continue the chain or exit early, respectively. Forgetting to pass `request` to `next` or omitting the return can lead to unexpected behavior.","wrong":"const myMiddleware = async (request, next) => { /* ... */ return next(); };","symbol":"Middleware Function","correct":"const myMiddleware = (request, next) => { /* ... */ return next(request); };"}],"quickstart":{"code":"import { d2lfetch } from 'd2l-fetch/src/index.js';\n\nconst authMiddleware = (request, next) => {\n  console.log('Auth Middleware: Adding Authorization header...');\n  request.headers.set('Authorization', `Bearer ${process.env.AUTH_TOKEN ?? 'your-jwt-here'}`);\n  return next(request);\n};\n\nconst loggingMiddleware = async (request, next) => {\n  console.log(`Logging Middleware: Request to ${request.url}`);\n  try {\n    const response = await next(request);\n    console.log(`Logging Middleware: Received response for ${request.url} with status ${response.status}`);\n    return response;\n  } catch (error) {\n    console.error(`Logging Middleware: Request to ${request.url} failed:`, error);\n    throw error;\n  }\n};\n\nd2lfetch.use({ name: 'authMiddleware', fn: authMiddleware });\nd2lfetch.use({ name: 'loggingMiddleware', fn: loggingMiddleware });\n\nasync function fetchData() {\n  try {\n    const request = new Request('https://api.example.com/data', {\n      method: 'GET',\n      headers: { 'Content-Type': 'application/json' }\n    });\n    const response = await d2lfetch.fetch(request);\n    if (!response.ok) {\n      throw new Error(`HTTP error! status: ${response.status}`);\n    }\n    const data = await response.json();\n    console.log('Fetched data:', data);\n    return data;\n  } catch (error) {\n    console.error('Failed to fetch data:', error);\n    throw error;\n  }\n}\n\n// Example usage (replace with actual API endpoint and token)\nfetchData();","lang":"javascript","description":"This quickstart demonstrates how to register two middleware functions (authentication and logging) with `d2lfetch` and then use `d2lfetch.fetch` to make an API request, showing how the middleware intercepts and modifies the request/response flow."},"warnings":[{"fix":"Always include `return next(request);` at the end of middleware functions that should continue the chain, or `return Promise.resolve(myResponse);` for early exits.","message":"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.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Choose one import method (either global script or ES module import) and stick to it consistently throughout your application to ensure a single, shared `d2lfetch` instance.","message":"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.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Carefully design your middleware order. Place early-exit middleware (like caching) strategically so that they only intercept requests where an early exit is appropriate and desired.","message":"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.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-23T00:00:00.000Z","next_check":"2026-07-22T00:00:00.000Z","problems":[{"fix":"If using ES modules, ensure `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.","cause":"`d2lfetch` was not correctly imported or the global script failed to load before being accessed.","error":"ReferenceError: d2lfetch is not defined"},{"fix":"Ensure middleware functions are defined as `(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.","cause":"A middleware function either did not receive the `request` object as its first argument, or a subsequent middleware returned something other than a `Request` or `Response` object to the next function.","error":"TypeError: Cannot read properties of undefined (reading 'headers') (or similar for Request/Response properties)"},{"fix":"Review middleware functions for early exits that might be unintentionally preventing `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.","cause":"Often indicates an issue in a middleware preventing the `window.fetch` call from being executed, or a misconfigured request, or a network issue.","error":"Unhandled Promise Rejection: TypeError: Failed to fetch (or network error)"}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}