{"id":16492,"library":"popsicle","title":"Popsicle HTTP Client","description":"Popsicle is an advanced HTTP client library designed for both Node.js and browser environments, currently stable at version 12.1.2. It provides a fetch-like API, built upon the `Servie` request and response interfaces, offering a universal solution without requiring environment-specific configuration by default. Releases typically involve patch updates for bug fixes and dependency management, with major versions introducing significant architectural changes, such as the `Servie 4` migration in v12.0.0. Key differentiators include its modular middleware architecture, which allows for extensive customization, and its optimized bundles for different environments. Node.js environments benefit from built-in features like User-Agent handling, content encoding decoding, redirect following, and an in-memory cookie cache, while browser builds are lighter, focusing solely on the `XMLHttpRequest` transport layer. This design allows developers to compose functionality and create highly tailored HTTP clients.","status":"active","version":"12.1.2","language":"javascript","source_language":"en","source_url":"git://github.com/serviejs/popsicle","tags":["javascript","request","http","middleware","node","ajax","browser","promise","typescript"],"install":[{"cmd":"npm install popsicle","lang":"bash","label":"npm"},{"cmd":"yarn add popsicle","lang":"bash","label":"yarn"},{"cmd":"pnpm add popsicle","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core request and response interfaces, providing the underlying fetch-like API.","package":"servie","optional":false},{"reason":"Handles in-memory cookie caching and management for Node.js environments.","package":"popsicle-cookie-jar","optional":false},{"reason":"Provides the HTTP/HTTPS transport layer for Node.js requests.","package":"popsicle-transport-http","optional":false}],"imports":[{"note":"The primary `fetch` function is a named export. For Node.js or browser-only environments, consider `import { fetch } from 'popsicle/dist/node';` or `import { fetch } from 'popsicle/dist/browser';` respectively to avoid `dom` types and optimize bundle size.","wrong":"import fetch from 'popsicle';","symbol":"fetch","correct":"import { fetch } from 'popsicle';"},{"note":"Re-exported from the underlying `servie` library, similar to the Web API `AbortController`.","wrong":"const AbortController = require('popsicle').AbortController;","symbol":"AbortController","correct":"import { AbortController } from 'popsicle';"},{"note":"These classes are re-exported from `servie` and are compatible with the Web Fetch API interfaces.","wrong":"const Request = require('popsicle').Request;","symbol":"Request, Response, Headers","correct":"import { Request, Response, Headers } from 'popsicle';"}],"quickstart":{"code":"import { fetch, AbortController } from \"popsicle\";\n\nconst controller = new AbortController();\nconst signal = controller.signal;\n\n// Simulate aborting the request after 500ms\nsetTimeout(() => {\n  console.log('Aborting request...');\n  controller.abort();\n}, 500);\n\nasync function makeRequest() {\n  try {\n    // Replace with a valid API endpoint for testing\n    const res = await fetch(\"https://jsonplaceholder.typicode.com/todos/1\", { signal });\n    if (!res.ok) {\n      throw new Error(`HTTP error! Status: ${res.status}`);\n    }\n    const data = await res.json();\n    console.log(\"Response data:\", data);\n  } catch (error: any) {\n    if (signal.aborted) {\n      console.log(`Request was aborted: ${error.name}`);\n    } else {\n      console.error(`Request failed unexpectedly: ${error.message}`);\n    }\n  }\n}\n\nmakeRequest();","lang":"typescript","description":"Demonstrates making an HTTP GET request using `fetch` and gracefully handling request abortion via `AbortController`."},"warnings":[{"fix":"Review the new `Servie 4` documentation and update your request/response handling. Migrate custom middleware to the new plugin system, potentially leveraging `throwback` and `servie` for composition.","message":"Version 12.0.0 introduced significant breaking changes by migrating to `Servie 4` interfaces and refactoring middleware. The `popsicle` package now primarily provides a `fetch`-like entry point, with most advanced middleware functionality extracted into separate reusable packages. Code relying on older middleware patterns or `Servie 3` interfaces will require updates.","severity":"breaking","affected_versions":">=12.0.0"},{"fix":"For Node.js-only projects, import from `popsicle/dist/node`. For browser-only projects, import from `popsicle/dist/browser`. This ensures you get an optimized bundle without unnecessary DOM types.","message":"The default universal entry point (`popsicle`) requires DOM types in TypeScript projects, which can cause issues in pure Node.js environments if not configured correctly. This is due to its browser compatibility. To avoid this, explicit environment-specific imports are recommended.","severity":"gotcha","affected_versions":">=12.0.0"},{"fix":"Upgrade to `popsicle@12.1.1` or newer to ensure you have the patched version of `popsicle-cookie-jar` and are protected from this vulnerability.","message":"A vulnerability in `popsicle-cookie-jar` (which `popsicle` uses in Node.js) was identified that could affect custom setups, particularly in versions prior to 12.1.1. This could lead to unexpected cookie handling or potential security issues.","severity":"gotcha","affected_versions":"<12.1.1"},{"fix":"Explicitly set the `User-Agent` header in your requests. Implement logic to parse and respect `robots.txt` directives for the target domain, and consider rate-limiting your requests.","message":"When performing non-trivial HTTP requests (e.g., scraping, interacting with public APIs), it is crucial to override the default `User-Agent` and respect `robots.txt` to avoid being blocked or violating server policies.","severity":"gotcha","affected_versions":"*"},{"fix":"Review the `serviejs` organization for specific `popsicle-*` middleware packages and adapt your application to explicitly import and compose the required middleware for advanced features.","message":"Middleware functionality underwent a significant architectural change in version 12.0.0. The core `popsicle` package now serves more as an example of middleware composition, with advanced functionalities like user-agent setting, content encoding, redirects, and cookie handling moved to independent `popsicle-*` packages. Existing custom middleware or configurations might break.","severity":"breaking","affected_versions":">=12.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Verify network connectivity, confirm the URL is correct and accessible, and ensure the target server is running and listening on the specified port.","cause":"The HTTP client failed to establish a connection to the target server, often due to network issues, incorrect hostname, or the server being offline.","error":"Error: EUNAVAILABLE: Unable to connect to the remote URL"},{"fix":"Double-check the URL string passed to `fetch` for proper formatting, including the protocol (e.g., `http://` or `https://`), domain name, and path segments.","cause":"The URL provided to the `fetch` function is syntactically incorrect or malformed, preventing the request from being initiated.","error":"TypeError: Invalid URL"},{"fix":"Inspect the URL and server configuration for redirect loops. If legitimate, you might be able to configure a higher redirect limit, though this is often a symptom of misconfiguration.","cause":"The request followed too many HTTP redirects (default limit is typically 20), indicating a potential redirect loop or an overly long redirect chain on the server side (Node.js only).","error":"RangeError: EMAXREDIRECTS: Maximum number of redirects exceeded"},{"fix":"For ESM, use `import { fetch } from 'popsicle';`. For CommonJS, use `const { fetch } = require('popsicle');`.","cause":"This typically occurs when attempting to use `fetch` with CommonJS `require` syntax without correctly destructuring the named export, or incorrectly assuming it's a default export.","error":"TypeError: fetch is not a function"}],"ecosystem":"npm"}