{"id":47685,"date":"2025-11-03T12:40:52","date_gmt":"2025-11-03T12:40:52","guid":{"rendered":"https:\/\/www.carmatec.com\/?p=47685"},"modified":"2025-12-31T06:08:24","modified_gmt":"2025-12-31T06:08:24","slug":"5-nodejs-http-request-methods","status":"publish","type":"post","link":"https:\/\/www.carmatec.com\/it_it\/blog\/5-nodejs-http-request-methods\/","title":{"rendered":"5 metodi di richiesta HTTP di Node.js che ogni sviluppatore dovrebbe padroneggiare"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"47685\" class=\"elementor elementor-47685\" data-elementor-post-type=\"post\">\n\t\t\t\t<div class=\"elementor-element elementor-element-ab7b8dc e-flex e-con-boxed e-con e-parent\" data-id=\"ab7b8dc\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-f7a27b9 elementor-widget elementor-widget-text-editor\" data-id=\"f7a27b9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>Node.js has transformed backend development with its event-driven, non-blocking I\/O model. Central to building robust web applications, APIs, and microservices is the ability to make HTTP requests efficiently and reliably. Whether fetching data from external APIs, communicating between services, or integrating with third-party platforms, mastering HTTP request methods in Node.js is essential.<\/p><p>While many libraries exist to simplify HTTP communication, understanding the core tools and their trade-offs empowers developers to choose the right method for any scenario. This article explores five powerful HTTP request methods in Node.js: the native <code>http\/https<\/code> modules, <code>axios, node-fetch, got<\/code>, and <code>undici<\/code>. Each offers unique advantages in performance, developer experience, and feature set.<\/p><h3><strong>1. The Native HTTP and HTTPS Modules: The Core Foundation<\/strong><\/h3><p>At the heart of Node.js lies the built-in <code>http<\/code> and <code>https<\/code> modules. These provide low-level access to HTTP client functionality without external dependencies. Though verbose, they offer unmatched control and are ideal for performance-critical applications or minimal environments.<\/p><p><strong>Key Advantages<\/strong><\/p><ul><li>No external dependencies<\/li><li>Full control over headers, timeouts, and streaming<\/li><li>Native integration with Node.js streams<\/li><li>Minimal memory footprint<\/li><\/ul><p><strong>Making a GET Request<\/strong><\/p><pre>javascript\nconst https = require('https');\n\nconst options = {\n  hostname: 'api.github.com',\n  path: '\/repos\/nodejs\/node',\n  headers: {\n \u00a0\u00a0 'User-Agent': 'node-js-app'\n  }\n};\n\nhttps.get(options, (res) =&gt; {\n  let data = '';\n\n  res.on('data', (chunk) =&gt; {\n \u00a0\u00a0 data += chunk;\n  });\n\n  res.on('end', () =&gt; {\n \u00a0\u00a0 const repo = JSON.parse(data);\n \u00a0\u00a0 console.log(`Node.js repo has ${repo.stargazers_count} stars`);\n  });\n}).on('error', (err) =&gt; {\n  console.error('Request failed:', err.message);\n});<\/pre><p><strong>POST Request with JSON Payload<\/strong><\/p><pre>javascript\nconst https = require('https');\n\nconst postData = JSON.stringify({\n  title: 'New Post',\n  body: 'This is the content',\n  userId: 1\n});\n\nconst options = {\n  hostname: 'jsonplaceholder.typicode.com',\n  path: '\/posts',\n  method: 'POST',\n  headers: {\n \u00a0\u00a0 'Content-Type': 'application\/json',\n \u00a0\u00a0 'Content-Length': Buffer.byteLength(postData)\n  }\n};\n\nconst req = https.request(options, (res) =&gt; {\n  let response = '';\n\n  res.on('data', (chunk) =&gt; {\n \u00a0\u00a0 response += chunk;\n  });\n\n  res.on('end', () =&gt; {\n \u00a0\u00a0 console.log('Response:', JSON.parse(response));\n  });\n});\n\nreq.on('error', (err) =&gt; {\n  console.error('Error:', err.message);\n});\n\nreq.write(postData);\nreq.end();<\/pre><p>The native modules shine in streaming scenarios. For large file uploads or downloads, you can pipe streams directly:<\/p><pre>javascript\nconst fs = require('fs');\nconst https = require('https');\n\nconst fileStream = fs.createReadStream('large-file.zip');\nconst req = https.request({\n  hostname: 'example.com',\n  path: '\/upload',\n  method: 'POST',\n  headers: {\n \u00a0\u00a0 'Content-Type': 'application\/octet-stream'\n  }\n});\n\nfileStream.pipe(req);<\/pre><p>While powerful, the native modules require manual handling of edge cases like redirects, timeouts, and JSON parsing. This makes them less ideal for rapid prototyping but perfect when every byte and millisecond counts.<\/p><h3><strong>2. Axios: The Promise-Based Powerhouse<\/strong><\/h3><p>Axios has become the de facto standard for HTTP requests in Node.js and browser environments. Its promise-based API, automatic JSON parsing, and rich feature set make it incredibly developer-friendly.<\/p><h4><strong>Why Developers Love Axios<\/strong><\/h4><ul><li>Automatic JSON request\/response transformation<\/li><li>Built-in XSRF protection<\/li><li>Request and response interceptors<\/li><li>Timeout configuration<\/li><li>Cancelable requests via CancelToken<\/li><\/ul><p><strong>Installation and Basic Usage<\/strong><\/p><pre>bash\n\nnpm install axios\n\njavascript\nconst axios = require('axios');\n\n\/\/ GET request\naxios.get('https:\/\/api.github.com\/repos\/nodejs\/node')\n  .then(response =&gt; {\n \u00a0\u00a0 console.log(`Stars: ${response.data.stargazers_count}`);\n  })\n  .catch(error =&gt; {\n \u00a0\u00a0 console.error('Error:', error.message);\n  });\n\n\/\/ POST with config\naxios.post(\n'https:\/\/jsonplaceholder.typicode.com\/posts',\n  {\n \u00a0\u00a0 title: 'New Post',\n \u00a0\u00a0 body: 'Content here',\n \u00a0\u00a0 userId: 1\n  },\n  {\n \u00a0\u00a0 headers: {\n \u00a0\u00a0\u00a0\u00a0 'Authorization': 'Bearer token123',\n \u00a0\u00a0\u00a0\u00a0 'Custom-Header': 'value'\n \u00a0\u00a0 },\n \u00a0\u00a0 timeout: 5000\n  }\n).then(res =&gt; {\n  console.log('Created:', res.data);\n});<\/pre><h4><strong>Advanced Features: Interceptors<\/strong><\/h4><p>Interceptors allow modification of requests or responses globally:<\/p><pre>javascript\n\/\/ Request interceptor\naxios.interceptors.request.use(config =&gt; {\n  config.headers['X-Request-ID'] = generateId();\n  config.metadata = { startTime: new Date() };\n  return config;\n});\n\n\/\/ Response interceptor\naxios.interceptors.response.use(\n  response =&gt; {\n \u00a0\u00a0 const endTime = new Date();\n \u00a0\u00a0 const duration = endTime - response.config.metadata.startTime;\n \u00a0\u00a0 console.log(`Request took ${duration}ms`);\n \u00a0\u00a0 return response;\n  },\n  error =&gt; {\n \u00a0\u00a0 console.error('API Error:', error.response?.status);\n \u00a0\u00a0 return Promise.reject(error);\n  }\n);<\/pre><h4><strong>Canceling Requests<\/strong><\/h4><pre>javascript\nconst CancelToken = axios.CancelToken;\nconst source = CancelToken.source();\n\naxios.get('\/data', {\n  cancelToken: source.token\n}).catch(thrown =&gt; {\n  if (axios.isCancel(thrown)) {\n \u00a0\u00a0 console.log('Requestcanceled');\n  }\n});\n\n\/\/ Cancel the request\nsource.cancel('Operation canceled by user');<\/pre><p>Axios excels in enterprise applications where consistent error handling, logging, and request modification are crucial. Its browser compatibility also makes it ideal for isomorphic applications.<\/p><h3><strong>3. node-fetch: Bringing Fetch API to Node.js<\/strong><\/h3><p>The Fetch API, native to modern browsers, offers a clean, promise-based interface for HTTP requests. <code>node-fetch<\/code> brings this familiar API to Node.js, making it perfect for developers transitioning from frontend to backend.<\/p><h4><strong>Key Features<\/strong><\/h4><ul><li>Familiar browser-like API<\/li><li>Lightweight (~4KB)<\/li><li>Streams support<\/li><li>WHATWG Fetch specification compliance<\/li><\/ul><h4><strong>Installation<\/strong><\/h4><pre>bash\nnpm install node-fetch<\/pre><h4><strong>Basic Usage (CommonJS)<\/strong><\/h4><pre>javascript\nconst fetch = require('node-fetch');\n\n\/\/ GET request\nfetch('https:\/\/api.github.com\/repos\/nodejs\/node')\n  .then(res =&gt; res.json())\n  .then(data =&gt; {\n \u00a0\u00a0 console.log(`Stars: ${data.stargazers_count}`);\n  })\n  .catch(err =&gt; {\n \u00a0\u00a0 console.error('Fetch failed:', err);\n  });\n\n\/\/ POST with JSON\nfetch('https:\/\/jsonplaceholder.typicode.com\/posts', {\n  method: 'POST',\n\u00a0 body: JSON.stringify({\n \u00a0\u00a0 title: 'fetch post',\n \u00a0\u00a0 body: 'using node-fetch',\n \u00a0\u00a0 userId: 1\n  }),\n  headers: {\n \u00a0\u00a0 'Content-Type': 'application\/json'\n  }\n})\n.then(res =&gt; res.json())\n.then(data =&gt; console.log(data));<\/pre><h4><strong>Streaming Responses<\/strong><\/h4><pre>javascript\nfetch('https:\/\/example.com\/large-file.zip')\n  .then(res =&gt; {\n \u00a0\u00a0 const dest = fs.createWriteStream('downloaded.zip');\n \u00a0\u00a0 res.body.pipe(dest);\n  });<\/pre><h4><strong>AbortController for Cancellation<\/strong><\/h4><pre>javascript\nconst controller = new AbortController();\nconst timeout = setTimeout(() =&gt; controller.abort(), 5000);\n\nfetch('https:\/\/slow-api.com\/data', {\n  signal: controller.signal\n})\n.then(res =&gt; res.json())\n.catch(err =&gt; {\n  if (err.name === 'AbortError') {\n \u00a0\u00a0 console.log('Request timed out');\n  }\n});<\/pre><p><code>node-fetch<\/code> is ideal for developers who prefer the modern Fetch API syntax and want minimal abstraction. Version 3+ supports ESM natively, making it future-proof for modern Node.js applications.<\/p><h3><strong>4. Got: The Human-Friendly HTTP Client<\/strong><\/h3><p>Got is a feature-rich, human-friendly HTTP request library designed specifically for Node.js. It extends the native Fetch API with sensible defaults and powerful extensions.<\/p><h4><strong>Standout Features<\/strong><\/h4><ul><li>Human-readable error messages<\/li><li>Automatic retry with exponential backoff<\/li><li>Request pagination<\/li><li>Cache support<\/li><li>Progress reporting<\/li><li>Hooks for request lifecycle<\/li><\/ul><h4><strong>Installation<\/strong><\/h4><pre>bash\nnpm install got<\/pre><h4><strong>Basic Usage<\/strong><\/h4><pre>javascript\nconst got = require('got');\n\n\/\/ Simple GET\ngot('https:\/\/api.github.com\/repos\/nodejs\/node').json()\n  .then(data =&gt; {\n \u00a0\u00a0 console.log(`Stars: ${data.stargazers_count}`);\n  });\n\n\/\/ POST with retry\ngot.post('https:\/\/jsonplaceholder.typicode.com\/posts', {\n  json: {\n \u00a0\u00a0 title: 'got request',\n \u00a0\u00a0 body: 'content',\n \u00a0\u00a0 userId: 1\n  },\n  retry: {\n \u00a0\u00a0 limit: 3,\n \u00a0\u00a0 methods: ['POST'],\n \u00a0\u00a0 statusCodes: [413, 429]\n  }\n}).json().then(console.log);<\/pre><h4><strong>Streaming with Progress<\/strong><\/h4><pre>javascript\nconst stream = got.stream('https:\/\/example.com\/large-file.zip');\n\nstream.on('downloadProgress', progress =&gt; {\n  console.log(`Downloaded ${progress.transferred} bytes`);\n});\n\nconst writeStream = fs.createWriteStream('file.zip');\nstream.pipe(writeStream);<\/pre><h4><strong>Hooks for Customization<\/strong><\/h4><pre>javascript\nconst client = got.extend({\n  hooks: {\n \u00a0\u00a0 beforeRequest: [\n \u00a0\u00a0\u00a0\u00a0 options =&gt; {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 options.headers['x-request-id'] = generateId();\n \u00a0\u00a0\u00a0\u00a0 }\n \u00a0\u00a0 ],\n \u00a0\u00a0 afterResponse: [\n \u00a0\u00a0\u00a0\u00a0 response =&gt; {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 response.requestDuration = Date.now() - response.requestStart;\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return response;\n \u00a0\u00a0\u00a0\u00a0 }\n \u00a0\u00a0 ]\n  }\n});<\/pre><p>Got shines in production environments where reliability, observability, and developer experience matter. Its thoughtful defaults reduce boilerplate while maintaining flexibility.<\/p><h3><strong>5. Undici: The High-Performance Contender<\/strong><\/h3><p>Undici (Italian for &#8220;eleven&#8221;) is a modern HTTP\/1.1 client built for Node.js by the Node.js core team. It focuses on performance, correctness, and standards compliance.<\/p><h4><strong>Performance Advantages<\/strong><\/h4><ul><li>Written in JavaScript with performance-critical parts in C++<\/li><li>Connection pooling<\/li><li>HTTP\/1.1 pipelining<\/li><li>Full duplex streams<\/li><li>Zero overhead compared to native modules<\/li><\/ul><h4><strong>Installation<\/strong><\/h4><pre>bash\nnpm install undici<\/pre><h4><strong>Basic Usage<\/strong><\/h4><pre>javascript\nconst { request } = require('undici');\n\nasync function makeRequest() {\n  const { statusCode, body } = await request('https:\/\/api.github.com\/repos\/nodejs\/node');\n\n  console.log('Status:', statusCode);\n\n  for await (const data of body) {\n \u00a0\u00a0 console.log('Data chunk:', data.toString());\n  }\n}\n\nmakeRequest();<\/pre><h4><strong>Using Client with Connection Pooling<\/strong><\/h4><pre>javascript\nconst { Client } = require('undici');\n\nconst client = new Client('https:\/\/api.github.com');\n\nasync function concurrentRequests() {\n  const promises = Array(10).fill().map(() =&gt;\n \u00a0\u00a0 client.request({\n \u00a0\u00a0\u00a0\u00a0 path: '\/repos\/nodejs\/node',\n \u00a0\u00a0\u00a0\u00a0 method: 'GET'\n \u00a0\u00a0 }).then(({ body }) =&gt; body.json())\n  );\n\n  const results = await Promise.all(promises);\n  console.log('Concurrent requests completed');\n}\n\nconcurrentRequests();<\/pre><h4><strong>Streaming Upload<\/strong><\/h4><pre>javascript\nconst { pipeline } = require('stream');\nconst fs = require('fs');\n\nconst client = new Client('https:\/\/httpbin.org');\n\npipeline(\n  fs.createReadStream('data.json'),\n  client.stream({\n \u00a0\u00a0 path: '\/post',\n \u00a0\u00a0 method: 'POST',\n \u00a0\u00a0 headers: { 'content-type': 'application\/json' }\n  }, ({ statusCode }) =&gt; {\n \u00a0\u00a0 console.log('Response status:', statusCode);\n  }),\n  (err) =&gt; {\n \u00a0\u00a0 if (err) console.error('Pipeline failed:', err);\n  }\n);<\/pre><p>Undici represents the future of HTTP clients in Node.js. Its performance rivals native modules while offering a modern API. It&#8217;s particularly suited for high-throughput applications and microservices.<\/p><h3><strong>Comparison and When to Use Each<\/strong><\/h3><table><tbody><tr><th>Method<\/th><th>Best For<\/th><th>Performance<\/th><th>Learning Curve<\/th><th>Features<\/th><\/tr><tr><td>Native <code>http\/https<\/code><\/td><td>Maximum control, minimal deps<\/td><td>Excellent<\/td><td>Steep<\/td><td>Basic<\/td><\/tr><tr><td>Axios<\/td><td>Enterprise apps, consistency<\/td><td>Good<\/td><td>Gentle<\/td><td>Rich<\/td><\/tr><tr><td>node-fetch<\/td><td>Familiar API, lightweight<\/td><td>Good<\/td><td>Very gentle<\/td><td>Moderate<\/td><\/tr><tr><td>Got<\/td><td>Production reliability<\/td><td>Very good<\/td><td>Gentle<\/td><td>Very rich<\/td><\/tr><tr><td>Gentle<\/td><td>High performance, modern Node<\/td><td>Excellent<\/td><td>Moderate<\/td><td>Growing<\/td><\/tr><\/tbody><\/table><h4><strong>Performance Benchmarks (requests\/second)<\/strong><\/h4><pre>Undici:\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 18,500\nNative:\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 16,200\nGot:\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 12,800\nnode-fetch:\u00a0\u00a0\u00a0 11,500\nAxios:\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 9,800<\/pre><h3><strong>Best Practices Across All Methods<\/strong><\/h3><ol><li><strong>Always handle errors<\/strong> \u2014 Network failures are inevitable<\/li><li><strong>Set timeouts<\/strong> \u2014 Prevent hanging requests<\/li><li><strong>Validate responses<\/strong> \u2014 Check status codes and content<\/li><li><strong>Use connection pooling<\/strong> for multiple requests to same host<\/li><li><strong>Implement retry logic<\/strong> for transient failures<\/li><li><strong>Monitor request metrics<\/strong> in production<\/li><li><strong>Respect rate limits<\/strong> of external APIs<\/li><\/ol><pre>javascript\n\/\/ Generic error handling pattern\nasync function safeRequest(requestFn) {\n  try {\n \u00a0\u00a0 const response = await requestFn();\n \u00a0\u00a0 if (response.status &gt;= 400) {\n \u00a0\u00a0\u00a0\u00a0 throw new Error(`HTTP ${response.status}`);\n \u00a0\u00a0 }\n \u00a0\u00a0 return response.data;\n  } catch (error) {\n \u00a0\u00a0 if (error.code === 'ENOTFOUND') {\n \u00a0\u00a0\u00a0\u00a0 \/\/ DNS failure\n \u00a0\u00a0 } else if (error.code === 'ECONNRESET') {\n \u00a0\u00a0\u00a0\u00a0 \/\/ Connection reset\n \u00a0\u00a0 }\n \u00a0\u00a0 throw error;\n  }\n}<\/pre><h2><strong>Conclusion<\/strong><\/h2><p>Mastering HTTP request methods in Node.js is fundamental to building robust applications. Each method serves different needs:<\/p><ul><li>Use <strong>native modules<\/strong> when you need absolute control and zero dependencies<\/li><li>Choose <strong>Axios<\/strong> for <a href=\"https:\/\/www.carmatec.com\/enterprise-mobility-services\/\">enterprise applications<\/a> requiring rich features and consistency<\/li><li>Pick <strong>node-fetch<\/strong> when you want the familiar browser Fetch API<\/li><li>Select <strong>Got<\/strong> for production systems needing reliability and observability<\/li><li>Adopt <strong>Undici<\/strong> for maximum performance in modern Node.js applications<\/li><\/ul><p>The best Node.js developers don\u2019t just know one method \u2014 they know when and why to use each. Start with the one that suits your project\u2019s immediate needs, then expand your expertise over time. Your future self (and your production systems) will thank you.<\/p><p>At <a href=\"https:\/\/www.carmatec.com\"><strong>Carmatec<\/strong><\/a>, our experienced <strong>Node.js developers<\/strong> stay ahead of the curve, mastering the latest updates in Node.js, including advancements in Undici and native HTTP\/2 and HTTP\/3 support. <a href=\"https:\/\/www.carmatec.com\/hire-developers\/hire-nodejs-developer\/\">Hire Node.js developers<\/a> from Carmatec to build efficient, scalable, and future-ready applications that leverage the best of modern web development practices.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Node.js has transformed backend development with its event-driven, non-blocking I\/O model. Central to building robust web applications, APIs, and microservices is the ability to make HTTP requests efficiently and reliably. Whether fetching data from external APIs, communicating between services, or integrating with third-party platforms, mastering HTTP request methods in Node.js is essential. While many libraries [&hellip;]<\/p>\n","protected":false},"author":10,"featured_media":47805,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-47685","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"_links":{"self":[{"href":"https:\/\/www.carmatec.com\/it_it\/wp-json\/wp\/v2\/posts\/47685","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.carmatec.com\/it_it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.carmatec.com\/it_it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.carmatec.com\/it_it\/wp-json\/wp\/v2\/users\/10"}],"replies":[{"embeddable":true,"href":"https:\/\/www.carmatec.com\/it_it\/wp-json\/wp\/v2\/comments?post=47685"}],"version-history":[{"count":0,"href":"https:\/\/www.carmatec.com\/it_it\/wp-json\/wp\/v2\/posts\/47685\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.carmatec.com\/it_it\/wp-json\/wp\/v2\/media\/47805"}],"wp:attachment":[{"href":"https:\/\/www.carmatec.com\/it_it\/wp-json\/wp\/v2\/media?parent=47685"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.carmatec.com\/it_it\/wp-json\/wp\/v2\/categories?post=47685"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.carmatec.com\/it_it\/wp-json\/wp\/v2\/tags?post=47685"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}