{"id":17873,"library":"phin-retry","title":"phin-retry","description":"phin-retry is an ultra-lightweight Node.js HTTP client that wraps the `phin` library, adding robust retry and delay capabilities. It aims to provide a similar API experience to the now-deprecated `request-promise` library, making it familiar for developers transitioning from older HTTP clients. The current stable version is 2.0.0. While a specific release cadence isn't defined, it typically updates in response to `phin`'s evolution or community needs. Key differentiators include customizable retry strategies (based on network errors, HTTP status codes, or custom logic), configurable exponential or fixed delays between retries, and flexible error handling strategies. It supports standard HTTP methods (GET, POST, PUT, DELETE, PATCH) and exposes all underlying `phin` options, allowing for fine-grained control over requests. Its lightweight nature and focus on resilient API calls make it particularly suitable for microservices or applications requiring dependable external API interactions.","status":"active","version":"2.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/ASaiAnudeep/phin-retry","tags":["javascript","phin","http","https","request","request-promise","ajax","url","uri"],"install":[{"cmd":"npm install phin-retry","lang":"bash","label":"npm"},{"cmd":"yarn add phin-retry","lang":"bash","label":"yarn"},{"cmd":"pnpm add phin-retry","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core HTTP client library that phin-retry wraps and extends with retry logic.","package":"phin","optional":false}],"imports":[{"note":"This is the primary CommonJS import pattern shown in the documentation. The package exports a default object with HTTP methods (get, post, etc.) directly.","wrong":"import request from 'phin-retry';","symbol":"request","correct":"const request = require('phin-retry');"},{"note":"For ES Module environments, this pattern *may* work if the package provides a default ESM export or is transpiled. However, the documentation primarily features CommonJS examples, so verify compatibility if issues arise.","wrong":"const request = require('phin-retry');","symbol":"request","correct":"import request from 'phin-retry';"},{"note":"The underlying `phin` instance can be accessed via `request.phin` for direct calls to `phin` or for advanced configurations that are not directly exposed by `phin-retry`'s wrapper.","symbol":"phin","correct":"const { phin } = require('phin-retry');\n// or\nconst request = require('phin-retry');\nconst phinInstance = request.phin;"}],"quickstart":{"code":"const request = require('phin-retry');\nconst http = require('http'); // For a local server example\n\n// --- Dummy local server for demonstration purposes ---\nconst server = http.createServer((req, res) => {\n  if (req.url === '/api/post' && req.method === 'POST') {\n    let body = '';\n    req.on('data', chunk => { body += chunk.toString(); });\n    req.on('end', () => {\n      console.log('Received POST body:', body);\n      res.writeHead(200, { 'Content-Type': 'application/json' });\n      res.end(JSON.stringify({ received: JSON.parse(body), status: 'success' }));\n    });\n  } else if (req.url === '/api/delete' && req.method === 'DELETE') {\n    const authHeader = req.headers.authorization;\n    if (authHeader === 'Basic bmFtZTpzZWNyZXQ=') { // base64 for name:secret\n      res.writeHead(200, { 'Content-Type': 'application/json' });\n      res.end(JSON.stringify({ status: 'deleted' }));\n    } else {\n      res.writeHead(401, { 'Content-Type': 'application/json' });\n      res.end(JSON.stringify({ status: 'unauthorized' }));\n    }\n  } else if (req.url === '/error' && req.method === 'GET') {\n    const failCount = (server.failCount || 0);\n    if (failCount < 2) { \n        server.failCount = failCount + 1;\n        res.writeHead(500, { 'Content-Type': 'text/plain' });\n        res.end('Internal Server Error (simulated)');\n    } else {\n        server.failCount = 0; \n        res.writeHead(200, { 'Content-Type': 'text/plain' });\n        res.end('Success after retries!');\n    }\n  } else {\n    res.writeHead(404);\n    res.end();\n  }\n});\n\nconst PORT = 9393;\nserver.listen(PORT, async () => {\n  console.log(`Dummy server running on http://localhost:${PORT}`);\n\n  try {\n    // Example 1: Simple GET request\n    console.log('\\n--- Example: Simple GET ---');\n    const getResponse = await request.get('https://jsonplaceholder.typicode.com/posts/1');\n    console.log('GET Response Status:', getResponse.statusCode);\n    console.log('GET Response Body (first 100 chars):', getResponse.body.slice(0, 100));\n\n    // Example 2: POST request with retry and delay\n    console.log('\\n--- Example: POST with Retry & Delay ---');\n    const postResponse = await request.post({\n      url: `http://localhost:${PORT}/api/post`,\n      body: { msg: 'input' },\n      retry: 3,\n      delay: 500\n    });\n    console.log('POST Response Status:', postResponse.statusCode);\n    console.log('POST Response Body:', JSON.parse(postResponse.body));\n\n    // Example 3: DELETE request with custom retry/error/delay strategy\n    console.log('\\n--- Example: DELETE with Custom Strategies ---');\n    const deleteResponse = await request.delete({\n      url: `http://localhost:${PORT}/api/delete`,\n      auth: { user: 'name', pass: 'secret' },\n      errorStrategy: ({ response, error }) => {\n        if (error) return true; // Retry on network error\n        if (response.statusCode >= 400 && response.statusCode !== 401) return false; \n        return true; // Consider other 4xx codes as retryable\n      },\n      retryStrategy: ({ response, error, options }) => {\n        if (error) return true;\n        if (options.method === 'DELETE' && response.statusCode === 401) return true;\n        if (response.statusCode >= 200 && response.statusCode < 300) return false;\n        return true;\n      },\n      delayStrategy: ({ error }) => { if (error) return 5000; return 2000; },\n      retry: 2 \n    });\n    console.log('DELETE Response Status:', deleteResponse.statusCode);\n    console.log('DELETE Response Body:', JSON.parse(deleteResponse.body));\n\n    // Example 4: GET with retries due to server error\n    console.log('\\n--- Example: GET with Server Error Retries ---');\n    const errorRetryResponse = await request.get({\n        url: `http://localhost:${PORT}/error`,\n        retry: 3,\n        delay: 200\n    });\n    console.log('Error Retry Response Status:', errorRetryResponse.statusCode);\n    console.log('Error Retry Response Body:', errorRetryResponse.body);\n\n  } catch (err) {\n    console.error('\\nAn error occurred during request examples:', err.message);\n    if (err.response) {\n      console.error('Error Response Status:', err.response.statusCode);\n      console.error('Error Response Body:', err.response.body);\n    }\n  } finally {\n    server.close(() => console.log('\\nDummy server closed.'));\n  }\n});\n","lang":"javascript","description":"Demonstrates basic GET and POST requests, including custom retry logic for server errors and authentication with tailored error and delay strategies using a local dummy server and public API."},"warnings":[{"fix":"Implement a custom `errorStrategy` function in your request options to override the default behavior and handle non-2xx status codes as desired without throwing, or wrap calls in `try/catch` blocks.","message":"Responses with status codes less than 200 or greater than or equal to 300 are automatically thrown as errors by default, unlike some other HTTP clients (e.g., `request-promise`).","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"For ESM projects, try `import request from 'phin-retry'` or `import * as request from 'phin-retry'`. If issues persist, consider using `require()` within an ESM wrapper or verify `package.json` `exports` field configuration.","message":"The documentation primarily uses CommonJS `require()` syntax. While Node.js generally supports both, direct ESM `import` might require specific project configuration or different import paths depending on the package's module resolution.","severity":"gotcha","affected_versions":">=2.0.0"},{"fix":"Explicitly configure the `retry` option (number of retries), `delay` (milliseconds), and provide custom `retryStrategy` and `delayStrategy` functions in your request options to fine-tune retry behavior for specific endpoints or error types.","message":"By default, `phin-retry` only retries once on network errors or status codes >= 500, with a relatively short delay. This default behavior might not be sufficient for highly unstable external services or specific retry requirements.","severity":"gotcha","affected_versions":">=2.0.0"}],"env_vars":null,"last_verified":"2026-04-23T00:00:00.000Z","next_check":"2026-07-22T00:00:00.000Z","problems":[{"fix":"Ensure you are using `const request = require('phin-retry');` for CommonJS environments. If using ESM, try `import request from 'phin-retry';` and confirm your file is treated as an ES module. Also, ensure `await` calls are within an `async` function.","cause":"This usually indicates an incorrect import or require statement, or attempting to use `request` before it's properly assigned, or outside an async context when using `await`.","error":"TypeError: request.get is not a function"},{"fix":"Wrap the `await request(...)` call in a `try...catch` block to handle the thrown error, or provide a custom `errorStrategy` option in your request configuration to prevent `phin-retry` from throwing on specific status codes.","cause":"The default `errorStrategy` in `phin-retry` throws an error for any response with a status code < 200 or >= 300 (e.g., 4xx, 5xx).","error":"UnhandledPromiseRejectionWarning: Error: Bad status code: 404"},{"fix":"Change your import statement from `const request = require('phin-retry');` to `import request from 'phin-retry';`. Additionally, ensure your `package.json` specifies `\"type\": \"module\"` or that the file ends with a `.mjs` extension.","cause":"Attempting to use the CommonJS `require()` function in an ES Module (ESM) context.","error":"ReferenceError: require is not defined"}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}