{"slug": "mastering-node-js-http-module-build-servers-rest-apis-and-handle-requests", "title": "Mastering Node.js HTTP Module: Build Servers, REST APIs, and Handle Requests", "summary": "The article explains that Node.js includes a built-in HTTP module enabling developers to create servers, handle requests and responses, and manage routing without external packages. It provides practical examples of creating a basic server, setting response headers, accessing request headers, and parsing URLs and query strings. The guide emphasizes that mastering this module is a foundational skill for backend developers building REST APIs or serving web content.", "body_md": "## Introduction to the HTTP Module\n\nModern web applications rely heavily on communication between clients and servers. Whether you are building a REST API, handling browser requests, or serving files, understanding the HTTP module in Node.js is a foundational skill every backend developer should master.\n\nNode.js provides a built-in HTTP module that allows developers to create servers, manage requests and responses, handle routing, and even stream large amounts of data efficiently — all without installing external packages.\n\nIn this article, we’ll explore the Node.js HTTP module in depth with practical examples, explanations, best practices, and real-world usage scenarios.\n\n## What is HTTP?\n\nHTTP stands for:\n\nHyperText Transfer Protocol\n\n**It is the protocol used for communication between:**\n\n- Browsers and web servers\n- Frontend and backend applications\n- APIs and clients\n\n**When you visit a website:**\n\n- Your browser sends an HTTP request\n- The server processes it\n- The server sends back an HTTP response\n\n**Key Features:**\n\n- Create HTTP servers to handle requests and send responses\n- Make HTTP requests to other servers\n- Handle different HTTP methods (GET, POST, PUT, DELETE, etc.)\n- Work with request and response headers\n- Handle streaming data for large payloads\n\n## Importing the HTTP Module\n\nNode.js uses the require() function to import modules.\n\n``` js\nconst http = require('http');\n```\n\nIf you are using ES Modules:\n\n``` python\nimport http from 'http';\n```\n\n## Creating Your First HTTP Server\n\nLet’s build a simple Node.js server.\n\n``` js\nconst http = require('http');\n\nconst server = http.createServer((req, res) => {\n\n  res.writeHead(200, {\n    'Content-Type': 'text/plain'\n  });\n\n  res.end('Hello, World!');\n});\n\nserver.listen(3000, () => {\n  console.log('Server running on port 3000');\n});\n```\n\n## Understanding the Server Code\n\n`http.createServer()`\n\n**Creates an HTTP server.**\n\nParameters\n\n- req → Request object\n- res → Response object\n\n`res.writeHead()`\n\nUsed to set:\n\n- Status code\n- Headers\n\n```\nres.writeHead(200, {\n  'Content-Type': 'text/plain'\n});\n```\n\n`res.end()`\n\nSends the response and closes the connection.\n\n```\nres.end('Hello World');\n```\n\n`server.listen()`\n\nStarts the server.\n\n```\nserver.listen(3000);\n```\n\n## Running the Server\n\nSave the code in a file named server.js\n\nRun the server using Node.js:\n\n```\nnode server.js\n```\n\nVisit [http://localhost:3000](http://localhost:3000) in your browser to see the response.\n\n## Working with HTTP Headers\n\nHTTP headers let you send additional information with your response.\n\nThe `res.writeHead()`\n\nmethod is used to set the status code and response headers.\n\n### Setting Response Headers\n\n``` js\nconst http = require('http');\n\nconst server = http.createServer((req, res) => {\n  // Set status code and multiple headers\n  res.writeHead(200, {\n    'Content-Type': 'text/html',\n    'X-Powered-By': 'Node.js',\n    'Cache-Control': 'no-cache, no-store, must-revalidate',\n    'Set-Cookie': 'sessionid=abc123; HttpOnly'\n  });\n\n  res.end('<h1>Hello, World!</h1>');\n});\n\nserver.listen(3000, () => {\n  console.log('Server running at http://localhost:3000/');\n});\n```\n\n### Common HTTP Status Codes\n\n| Code | Message | Description |\n|---|---|---|\n| 200 | OK | Standard response for successful HTTP requests |\n| 201 | Created | Request has been fulfilled and new resource created |\n| 301 | Moved Permanently | Resource has been moved to a new URL |\n| 400 | Bad Request | Server cannot process the request due to client error |\n| 401 | Unauthorized | Authentication is required |\n| 403 | Forbidden | Server refuses to authorize the request |\n| 404 | Not Found | Requested resource could not be found |\n| 500 | Internal Server Error | Unexpected condition was encountered |\n\n### Common Response Headers\n\n-\n**Content-Type**: Specifies the media type of the content (e.g., text/html, application/json) -\n**Content-Length**: The length of the response body in bytes -\n**Location**: Used in redirects (with 3xx status codes) -\n**Set-Cookie**: Sets HTTP cookies on the client -\n**Cache-Control**: Directives for caching mechanisms -\n**Access-Control-Allow-Origin**: For CORS support\n\n### Reading Request Headers\n\nYou can access request headers using the req.headers object:\n\n``` js\nconst http = require('http');\n\nconst server = http.createServer((req, res) => {\n  // Log all request headers\n  console.log('Request Headers:', req.headers);\n\n  // Get specific headers (case-insensitive)\n  const userAgent = req.headers['user-agent'];\n  const acceptLanguage = req.headers['accept-language'];\n\n  res.writeHead(200, { 'Content-Type': 'text/plain' });\n  res.end(`User-Agent: ${userAgent}\\nAccept-Language: ${acceptLanguage}`);\n});\n\nserver.listen(3000);\n\n// User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36\n// Accept-Language: en-US,en;q=0.9,nb;q=0.8,da;q=0.7,no;q=0.6\n```\n\n## Working with URLs and Query Strings\n\nNode.js provides built-in modules for working with URLs and query strings, making it easy to parse URL components and query parameters.\n\n### Accessing the Request URL\n\nThe req.url property contains the URL string that was requested, including any query parameters.\n\nThis is part of the http.IncomingMessage object.\n\n``` js\nconst http = require('http');\n\nconst server = http.createServer((req, res) => {\n  // Get the URL and HTTP method\n  const { url, method } = req;\n\n  res.writeHead(200, { 'Content-Type': 'text/plain' });\n  res.end(`You made a ${method} request to ${url}`);\n});\n\nserver.listen(3000, () => {\n  console.log('Server running at http://localhost:3000/');\n});\n\n// You made a GET request to /\n```\n\n### Parsing URLs with the URL Module\n\nThe url module provides utilities for URL resolution and parsing.\n\nIt can parse a URL string into a URL object with properties for each part of the URL.\n\n``` js\nconst http = require('http');\nconst url = require('url');\n\nconst server = http.createServer((req, res) => {\n  // Parse the URL\n  const parsedUrl = url.parse(req.url, true);\n\n  // Get different parts of the URL\n  const pathname = parsedUrl.pathname; // The path without query string\n  const query = parsedUrl.query; // The query string as an object\n\n  res.writeHead(200, { 'Content-Type': 'application/json' });\n  res.end(JSON.stringify({\n    pathname,\n    query,\n    fullUrl: req.url\n  }, null, 2));\n});\n\nserver.listen(3000);\n```\n\n### Example Requests and Responses\n\nFor the following request:\n\nGET /products?category=electronics&sort=price&page=2 HTTP/1.1\n\nThe server would respond with:\n\n{\n\n\"pathname\": \"/products\",\n\n\"query\": {\n\n\"category\": \"electronics\",\n\n\"sort\": \"price\",\n\n\"page\": \"2\"\n\n},\n\n\"fullUrl\": \"/products?category=electronics&sort=price&page=2\"\n\n}\n\n### Working with Query Strings\n\nFor more advanced query string handling, you can use the querystring module:\n\n``` js\nconst http = require('http');\nconst { URL } = require('url');\nconst querystring = require('querystring');\n\nconst server = http.createServer((req, res) => {\n  // Using the newer URL API (Node.js 10+)\n  const baseURL = 'http://' + req.headers.host + '/';   const parsedUrl = new URL(req.url, baseURL);\n\n  // Get query parameters\n  const params = Object.fromEntries(parsedUrl.searchParams);\n\n  // Example of building a query string\n  const queryObj = {\n    name: 'John Doe',\n    age: 30,\n    interests: ['programming', 'music']\n  };\n  const queryStr = querystring.stringify(queryObj);\n\n  res.writeHead(200, { 'Content-Type': 'application/json' });\n  res.end(JSON.stringify({\n    path: parsedUrl.pathname,\n    params,\n    exampleQueryString: queryStr\n  }, null, 2));\n});\n\nserver.listen(3000);\n{\n  \"path\": \"/\",\n  \"params\": {},\n  \"exampleQueryString\": \"name=John%20Doe&age=30&interests=programming&interests=music\"\n}\n```\n\n#### Common URL Parsing Methods\n\n-\n`url.parse(urlString, [parseQueryString], [slashesDenoteHost])`\n\n: Parse a URL string into an object -\n`url.format(urlObject)`\n\n: Format a URL object into a URL string -\n`url.resolve(from, to)`\n\n: Resolve a target URL relative to a base URL -\n`new URL(input, [base])`\n\n: The WHATWG URL API (recommended for new code) -\n`querystring.parse(str, [sep], [eq], [options])`\n\n: Parse a query string into an object -\n`querystring.stringify(obj, [sep], [eq], [options])`\n\n: Stringify an object into a query string\n\n## Handling Different HTTP Methods\n\nRESTful APIs commonly use different HTTP methods (GET, POST, PUT, DELETE, etc.) to perform different operations on resources.\n\nHere's how to handle different HTTP methods in a Node.js HTTP server:\n\n#### Example: Handling Multiple HTTP Methods\n\n``` js\nconst http = require('http');\nconst { URL } = require('url');\n\n// In-memory data store (for demonstration)\nlet todos = [\n  { id: 1, task: 'Learn Node.js', completed: false },\n  { id: 2, task: 'Build an API', completed: false }\n];\n\nconst server = http.createServer((req, res) => {\n  const { method, url } = req;\n  const parsedUrl = new URL(url, `http://${req.headers.host}`);\n  const pathname = parsedUrl.pathname;\n\n  // Set CORS headers (for development)\n  res.setHeader('Access-Control-Allow-Origin', '*');\n  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');\n  res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n  // Handle preflight requests\n  if (method === 'OPTIONS') {\n    res.writeHead(204);\n    res.end();\n    return;\n  }\n\n  // Route: GET /todos\n  if (method === 'GET' && pathname === '/todos') {\n    res.writeHead(200, { 'Content-Type': 'application/json' });\n    res.end(JSON.stringify(todos));\n  }\n  // Route: POST /todos\n  else if (method === 'POST' && pathname === '/todos') {\n    let body = '';\n    req.on('data', chunk => {\n      body += chunk.toString();\n    });\n\n    req.on('end', () => {\n      try {\n        const newTodo = JSON.parse(body);\n        newTodo.id = todos.length > 0 ? Math.max(...todos.map(t => t.id)) + 1 : 1;\n        todos.push(newTodo);\n        res.writeHead(201, { 'Content-Type': 'application/json' });\n        res.end(JSON.stringify(newTodo));\n      } catch (error) {\n        res.writeHead(400, { 'Content-Type': 'application/json' });\n        res.end(JSON.stringify({ error: 'Invalid JSON' }));\n      }\n    });\n  }\n\n  // Route: PUT /todos/:id\n  else if (method === 'PUT' && pathname.startsWith('/todos/')) {\n    const id = parseInt(pathname.split('/')[2]);\n    let body = '';\n\n    req.on('data', chunk => {\n      body += chunk.toString();\n    });\n\n    req.on('end', () => {\n      try {\n        const updatedTodo = JSON.parse(body);\n        const index = todos.findIndex(t => t.id === id);\n\n        if (index === -1) {\n          res.writeHead(404, { 'Content-Type': 'application/json' });\n          res.end(JSON.stringify({ error: 'Todo not found' }));\n        } else {\n          todos[index] = { ...todos[index], ...updatedTodo };\n          res.writeHead(200, { 'Content-Type': 'application/json' });\n          res.end(JSON.stringify(todos[index]));\n        }\n      } catch (error) {\n        res.writeHead(400, { 'Content-Type': 'application/json' });\n        res.end(JSON.stringify({ error: 'Invalid JSON' }));\n      }\n    });\n  }\n\n  // Route: DELETE /todos/:id\n  else if (method === 'DELETE' && pathname.startsWith('/todos/')) {\n    const id = parseInt(pathname.split('/')[2]);\n    const index = todos.findIndex(t => t.id === id);\n\n    if (index === -1) {\n      res.writeHead(404, { 'Content-Type': 'application/json' });\n      res.end(JSON.stringify({ error: 'Todo not found' }));\n    } else {\n      todos = todos.filter(t => t.id !== id);\n      res.writeHead(204);\n      res.end();\n    }\n  }\n\n  // 404 Not Found\n  else {\n    res.writeHead(404, { 'Content-Type': 'application/json' });\n    res.end(JSON.stringify({ error: 'Not Found' }));\n  }\n});\n\nconst PORT = 3000;\nserver.listen(PORT, () => {\n  console.log(`Server running at http://localhost:${PORT}/`);\n});\n```\n\n#### Testing the API with cURL\n\nYou can test this API using cURL commands:\n\n```\n# 1. Get all todos\ncurl http://localhost:3000/todos\n\n# 2. Create a new todo\ncurl -X POST http://localhost:3000/todos \\\n-H \"Content-Type: application/json\" \\\n-d '{\"task\":\"New Task\",\"completed\":false}'\n\n# 3. Update a todo\ncurl -X PUT http://localhost:3000/todos/1 \\\n-H \"Content-Type: application/json\" \\\n-d '{\"completed\":true}'\n\n# 4. Delete a todo\ncurl -X DELETE http://localhost:3000/todos/1\n```\n\n### Best Practices for HTTP Methods\n\n- GET: Retrieve a resource or collection of resources (should be idempotent)\n- POST: Create a new resource (not idempotent)\n- PUT: Update an existing resource or create it if it doesn't exist (idempotent)\n- PATCH: Partially update a resource\n- DELETE: Remove a resource (idempotent)\n- HEAD: Same as GET but without the response body\n- OPTIONS: Describe the communication options for the target resource\n\n### Error Handling\n\nAlways include proper error handling and appropriate HTTP status codes:\n\n-\n`200 OK`\n\n- Successful GET/PUT/PATCH -\n`201 Created`\n\n- Successful resource creation -\n`204 No Content`\n\n- Successful DELETE -\n`400 Bad Request`\n\n- Invalid request data -\n`401 Unauthorized`\n\n- Authentication required -\n`403 Forbidden`\n\n- Not enough permissions -\n`404 Not Found`\n\n- Resource doesn't exist -\n`500 Internal Server Error`\n\n- Server-side error\n\n## Streaming Responses\n\nNode.js streams are powerful for handling large amounts of data efficiently. The HTTP module works well with streams for both reading request bodies and writing responses.\n\n``` js\nconst http = require('http');\nconst fs = require('fs');\nconst path = require('path');\n\nconst server = http.createServer((req, res) => {\n  // Get the file path from the URL\n  const filePath = path.join(__dirname, req.url);\n\n  // Check if file exists\n  fs.access(filePath, fs.constants.F_OK, (err) => {\n    if (err) {\n      res.statusCode = 404;\n      res.end('File not found');\n      return;\n    }\n\n    // Get file stats\n    fs.stat(filePath, (err, stats) => {\n      if (err) {\n        res.statusCode = 500;\n        res.end('Server error');\n        return;\n      }\n\n      // Set appropriate headers\n      res.setHeader('Content-Length', stats.size);\n      res.setHeader('Content-Type', 'application/octet-stream');\n\n      // Create read stream and pipe to response\n      const stream = fs.createReadStream(filePath);\n\n      // Handle errors\n      stream.on('error', (err) => {\n        console.error('Error reading file:', err);\n        if (!res.headersSent) {\n          res.statusCode = 500;\n          res.end('Error reading file');\n        }\n      });\n\n      // Pipe the file to the response\n      stream.pipe(res);\n    });\n  });\n});\n\nconst PORT = 3000;\nserver.listen(PORT, () => {\n  console.log(`File server running at http://localhost:${PORT}/`);\n});\n```\n\n### Benefits of Streaming\n\n-\n**Memory Efficiency**: Processes data in chunks instead of loading everything into memory -\n**Faster Time to First Byte**: Starts sending data as soon as it's available -\n**Backpressure Handling**: Automatically handles slow clients by pausing the read stream\n\n### Common Use Cases for Streaming\n\n- File uploads/downloads\n- Real-time data processing\n- Proxying requests\n- Video/audio streaming\n- Log processing\n\n## Final Thoughts\n\nThe Node.js HTTP module is one of the most important building blocks in backend development. While frameworks like Express simplify development, understanding the core HTTP module gives you deeper insight into how web servers, APIs, and request-response cycles actually work.\n\nMastering this module will help you:\n\n- Build scalable backend systems\n- Understand REST APIs deeply\n- Improve debugging skills\n- Handle streams efficiently\n- Become a stronger Node.js developer\n\nIf you're serious about backend engineering, learning the HTTP module thoroughly is absolutely worth your time. 🚀", "url": "https://wpnews.pro/news/mastering-node-js-http-module-build-servers-rest-apis-and-handle-requests", "canonical_source": "https://dev.to/coding_sprint_e9acaaa6d35/mastering-nodejs-http-module-build-servers-rest-apis-and-handle-requests-953", "published_at": "2026-05-23 01:07:52+00:00", "updated_at": "2026-05-23 01:32:05.508881+00:00", "lang": "en", "topics": ["developer-tools"], "entities": ["Node.js"], "alternates": {"html": "https://wpnews.pro/news/mastering-node-js-http-module-build-servers-rest-apis-and-handle-requests", "markdown": "https://wpnews.pro/news/mastering-node-js-http-module-build-servers-rest-apis-and-handle-requests.md", "text": "https://wpnews.pro/news/mastering-node-js-http-module-build-servers-rest-apis-and-handle-requests.txt", "jsonld": "https://wpnews.pro/news/mastering-node-js-http-module-build-servers-rest-apis-and-handle-requests.jsonld"}}