{"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.","language":"javascript","status":"active","last_verified":"Thu Apr 23","install":{"commands":["npm install phin-retry"],"cli":null},"imports":["const request = require('phin-retry');","import request from 'phin-retry';","const { phin } = require('phin-retry');\n// or\nconst request = require('phin-retry');\nconst phinInstance = request.phin;"],"auth":{"required":false,"env_vars":[]},"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.","tag":null,"tag_description":null,"last_tested":null,"results":[]},"compatibility":null}