Node.js: HTTP Module

Last updated: 2026-08-26

Bob needed to quickly validate an API idea but didn’t want to set up an entire Express project, so he used the native HTTP module to get an API server up and running in just 20 lines of code. From handling request methods and parsing URL paths to returning JSON data and setting status codes, Bob found that once he understood the underlying principles, using a framework actually became much easier.

1. What You'll Learn



2. Creating Your First HTTP Server

http.createServer Accepts a callback function that is triggered every time a request is received. The callback takes two parameters: request (the request object) and response (the response object). server.listen specifies the listening port.

▶ Example: Minimizing an HTTP Server

JAVASCRIPT
const http = require('http');

const server = http.createServer((req, res) => {
  res.end('Hello, World!');
});

server.listen(3000, () => {
  console.log('Server running at http://localhost:3000/');
});
▶ Try it Yourself
BASH
node server.js
TEXT 📖 Display only
Server running at http://localhost:3000/

Simply visit http://localhost:3000/ in your browser to view Hello, World!.



3. The HTTP Request-Response Lifecycle

Every HTTP interaction follows the process of Request → Routing → Processing → Response; understanding this lifecycle is the foundation for building web services.

100%
flowchart LR
    A["Client"] -->|"Send Request"| B["request Object<br/>method / url / headers"]
    B --> C["Routing Resolution<br/>pathname + searchParams"]
    C --> D{"Request Method?"}
    D -->|GET| E["Read Query Parameters"]
    D -->|POST / PUT| F["Collect the request body"]
    E --> G["Business Processing"]
    F --> G
    G --> H["response Object<br/>statusCode / headers / body"]
    H -->|"Return Response"| A


4. Core Properties of the request Object

request The object contains all the request information sent by the client; the three most commonly used properties are method, url, and headers.

Property / Method Type Description Example Value
req.method string Request method 'GET', 'POST'
req.url string Request path (including query string) '/api/users?id=1'
req.headers object Request header object { 'content-type': 'application/json' }
req.httpVersion string HTTP protocol version '1.1'
req.socket object underlying socket object

▶ Example: Printing Request Information

JAVASCRIPT
const http = require('http');

const server = http.createServer((req, res) => {
  console.log(`Method: ${req.method}`);
  console.log(`URL: ${req.url}`);
  console.log(`Content-Type: ${req.headers['content-type'] || 'N/A'}`);
  res.end('Check your terminal for request info.');
});

server.listen(3000);
▶ Try it Yourself

Send a test request using curl:

BASH
curl -X POST http://localhost:3000/api/data -H "Content-Type: application/json"
TEXT 📖 Display only
Method: POST
URL: /api/data
Content-Type: application/json


5. Core Methods of the response Object

response This object is used to send response data to the client, including the status code, response headers, and response body.

Method / Property Description Example
res.writeHead(statusCode, headers) Writing status codes and multiple response headers in a single operation res.writeHead(200, { 'Content-Type': 'text/plain' })
res.statusCode = n Set status code individually res.statusCode = 404
res.setHeader(name, value) Set a single response header res.setHeader('Content-Type', 'application/json')
res.write(data) Write response body data (can be called multiple times) res.write('partial')
res.end(data) Send the response body and end the response res.end('done')
res.writeHead After being called, then res.end() Send buffered data

▶ Example: Return a JSON response

JAVASCRIPT
const http = require('http');

const server = http.createServer((req, res) => {
  const data = { message: 'Success', timestamp: Date.now() };

  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify(data));
});

server.listen(3000);
▶ Try it Yourself
BASH
curl http://localhost:3000/
TEXT 📖 Display only
{"message":"Success","timestamp":1719792000000}


6. URL Routing Resolution

req.url contains the complete request path and query string. Using new URL() makes it easy to split the pathname and searchParams, enabling path-based routing.

▶ Example: Path-Based Routing

JAVASCRIPT
const http = require('http');

const server = http.createServer((req, res) => {
  const url = new URL(req.url, `http://${req.headers.host}`);
  const pathname = url.pathname;

  res.writeHead(200, { 'Content-Type': 'text/plain' });

  if (pathname === '/') {
    res.end('Home Page');
  } else if (pathname === '/about') {
    res.end('About Page');
  } else if (pathname === '/api/status') {
    res.end('OK');
  } else {
    res.writeHead(404, { 'Content-Type': 'text/plain' });
    res.end('Not Found');
  }
});

server.listen(3000);
▶ Try it Yourself

7. GET Requests and Query Parameters

The parameters for a GET request are included in the URL's query string, and you can retrieve the key-value pairs directly using url.searchParams.

▶ Example: Parsing Query Parameters

JAVASCRIPT
const http = require('http');

const server = http.createServer((req, res) => {
  if (req.method !== 'GET') {
    res.writeHead(405, { 'Content-Type': 'text/plain' });
    res.end('Method Not Allowed');
    return;
  }

  const url = new URL(req.url, `http://${req.headers.host}`);
  const name = url.searchParams.get('name') || 'Guest';
  const page = url.searchParams.get('page') || '1';

  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({ name, page }));
});

server.listen(3000);
▶ Try it Yourself
BASH
curl "http://localhost:3000/?name=Bob&page=3"
TEXT 📖 Display only
{"name":"Bob","page":"3"}

Note: searchParams.get() always returns a string, so you must manually convert it to a number or other type.



8. POST Requests and Request Body Collection

Data for POST requests is transmitted via the request body. The request object is a readable stream; you need to listen for the data event to collect data blocks and listen for the end event to process the complete data.

▶ Example: Collecting the POST request body

JAVASCRIPT
const http = require('http');

const server = http.createServer((req, res) => {
  if (req.method === 'POST' && req.url === '/api/users') {
    let body = '';

    req.on('data', (chunk) => {
      body += chunk.toString();
    });

    req.on('end', () => {
      try {
        const data = JSON.parse(body);
        res.writeHead(201, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ id: 1, ...data }));
      } catch (e) {
        res.writeHead(400, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ error: 'Invalid JSON' }));
      }
    });
  } else {
    res.writeHead(404, { 'Content-Type': 'text/plain' });
    res.end('Not Found');
  }
});

server.listen(3000);
▶ Try it Yourself
BASH
curl -X POST http://localhost:3000/api/users -H "Content-Type: application/json" -d "{\"name\":\"Bob\",\"age\":30}"
TEXT 📖 Display only
{"id":1,"name":"Bob","age":30}


9. Content-Type and Response Headers

Content-Type This is one of the most critical response headers in HTTP communication, as it specifies the data format of the response body to the client. Setting it incorrectly will prevent the client from parsing the data correctly.

Content-Type Purpose Description
text/plain Plain text The most basic text type, with no formatting
text/html HTML page The browser renders this as a web page
application/json JSON Data The Most Commonly Used Response Format for APIs
application/x-www-form-urlencoded Form Data Default Form Submission Format
multipart/form-data File Upload Form Submission with Files
application/xml XML Data SOAP API or Legacy Interface
text/css CSS Style Sheet Style Sheet
application/octet-stream Binary Stream File Download Scenarios

▶ Example: The Effect of Different Content-Types for the Same Data

JAVASCRIPT
const http = require('http');

const server = http.createServer((req, res) => {
  const url = new URL(req.url, `http://${req.headers.host}`);

  if (url.pathname === '/plain') {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('<h1>This is plain text</h1>');
  } else if (url.pathname === '/html') {
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.end('<h1>This is HTML</h1>');
  } else if (url.pathname === '/json') {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ message: 'This is JSON' }));
  }
});

server.listen(3000);
▶ Try it Yourself

When you visit /plain, the browser displays the source code tab; when you visit /html, the browser renders the main heading; and when you visit /json, the browser displays JSON data.



10. Quick Reference for HTTP Status Codes

A status code is a standardized representation of the server's response to a request; the client determines its next course of action based on the status code.

Status Code Category Meaning Common Scenarios
200 2xx Success OK GET request successfully returned data
201 2xx Success Created POST Resource created successfully
204 2xx Success No Content Deletion successful, no content returned
301 3xx Redirect Moved Permanently Permanent redirect to new URL
302 3xx Redirect Found Temporary Redirect
304 3xx Redirect Not Modified Cache hit; no need to retransmit
400 4xx Client Error Bad Request Invalid request parameter format
401 4xx Client Error Unauthorized Not authenticated; login required
403 4xx Client Error Forbidden Authenticated but no permissions
404 4xx Client Error Not Found Route or Resource Does Not Exist
405 4xx Client Error Method Not Allowed The request method is not allowed
500 5xx Server Error Internal Server Error Internal Server Error
502 5xx Server Error Bad Gateway The gateway/proxy received an invalid response
503 5xx Server Error Service Unavailable Service temporarily unavailable

▶ Example: Returning Different Status Codes Based on Conditions

JAVASCRIPT
const http = require('http');

const server = http.createServer((req, res) => {
  const url = new URL(req.url, `http://${req.headers.host}`);
  const id = url.searchParams.get('id');

  if (!id) {
    res.writeHead(400, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ error: 'Missing id parameter' }));
  } else if (id === '0') {
    res.writeHead(404, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ error: 'User not found' }));
  } else {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ id, name: 'Bob' }));
  }
});

server.listen(3000);
▶ Try it Yourself

11. Comprehensive Example: A Simple REST API Server

Combine all the concepts covered so far to build a REST API server that supports GET/POST routes, JSON responses, and query parameter parsing. Maintain a list of users in memory and support three operations: querying all users, querying a single user, and creating a user.

JAVASCRIPT
const http = require('http');

const users = [
  { id: 1, name: 'Bob', email: 'bob@example.com' },
  { id: 2, name: 'Alice', email: 'alice@example.com' },
];
let nextId = 3;

function parseBody(req) {
  return new Promise((resolve, reject) => {
    let body = '';
    req.on('data', (chunk) => { body += chunk.toString(); });
    req.on('end', () => {
      try { resolve(JSON.parse(body)); }
      catch (e) { reject(e); }
    });
    req.on('error', reject);
  });
}

function sendJSON(res, statusCode, data) {
  res.writeHead(statusCode, {
    'Content-Type': 'application/json',
    'X-Powered-By': 'Node.js',
  });
  res.end(JSON.stringify(data));
}

const server = http.createServer(async (req, res) => {
  const url = new URL(req.url, `http://${req.headers.host}`);
  const pathname = url.pathname;

  // GET /api/users
  if (req.method === 'GET' && pathname === '/api/users') {
    const limit = parseInt(url.searchParams.get('limit')) || 10;
    sendJSON(res, 200, users.slice(0, limit));
    return;
  }

  // GET /api/users/:id
  if (req.method === 'GET' && pathname.startsWith('/api/users/')) {
    const id = parseInt(pathname.split('/').pop());
    const user = users.find((u) => u.id === id);
    if (!user) {
      sendJSON(res, 404, { error: 'User not found' });
    } else {
      sendJSON(res, 200, user);
    }
    return;
  }

  // POST /api/users
  if (req.method === 'POST' && pathname === '/api/users') {
    try {
      const data = await parseBody(req);
      if (!data.name || !data.email) {
        sendJSON(res, 400, { error: 'name and email are required' });
        return;
      }
      const newUser = { id: nextId++, name: data.name, email: data.email };
      users.push(newUser);
      sendJSON(res, 201, newUser);
    } catch (e) {
      sendJSON(res, 400, { error: 'Invalid JSON body' });
    }
    return;
  }

  // 404 fallback
  sendJSON(res, 404, { error: 'Route not found' });
});

server.listen(3000, () => {
  console.log('REST API server running at http://localhost:3000/');
});

Test all interfaces:

BASH
# Query All Users
curl http://localhost:3000/api/users

# Query a Single User
curl http://localhost:3000/api/users/1

# Create a New User
curl -X POST http://localhost:3000/api/users -H "Content-Type: application/json" -d "{\"name\":\"Charlie\",\"email\":\"charlie@example.com\"}"

# Accessing a Route That Does Not Exist
curl http://localhost:3000/unknown
TEXT 📖 Display only
[{"id":1,"name":"Bob","email":"bob@example.com"},{"id":2,"name":"Alice","email":"alice@example.com"}]

{"id":1,"name":"Bob","email":"bob@example.com"}

{"id":3,"name":"Charlie","email":"charlie@example.com"}

{"error":"Route not found"}

❓ FAQ

Q What is the difference between the http module and Express?
A http is a built-in, low-level module in Node.js that provides only the most basic request/response handling; Express is a framework built on top of the http module that includes advanced features such as routing, middleware, and a template engine, offering higher development efficiency but introducing additional dependencies.
Q How do I retrieve the request body of a POST request?
A The req object is a readable stream. You need to listen for the data event to collect buffer blocks and concatenate them, then listen for the end event to indicate that data reception is complete, and finally use JSON.parse() or Buffer.concat() to process the complete data.
Q What is the difference between res.end() and res.write()?
A res.end() Sends data and closes the response; it must be called once—and only once—for each request; res.write() only writes data but does not close the response; it can be called multiple times for streaming or chunked transmission, but res.end() must still be called at the end to close the response.
Q Why is it necessary to set the Content-Type when returning JSON?
A If the Content-Type is not set, the default is text/plain. Clients (browsers, fetch, curl) will not automatically parse the response as JSON, which may result in response.json() errors or the data not being displayed correctly. Setting it to application/json ensures that clients know how to parse the response body.
Q How do I handle query parameters in a URL?
A Use new URL(req.url, 'http://localhost') to create a URL object, then use url.searchParams.get('key') to retrieve parameter values, or use url.searchParams.entries() to iterate through all parameters.
Q What is the purpose of the second callback for server.listen?
A It is a callback that fires after the server has successfully started, and is often used to print startup logs. If you do not pass a callback, you can also listen for the server.on('listening', callback) event, which has the same effect.
Q Why does the second parameter of new URL need to include base?
A req.url contains only the path portion (e.g., /api?id=1) and is not a complete URL. new URL() requires a base parameter to complete the protocol and hostname; otherwise, a TypeError will be thrown. The value of base does not affect the parsing results of pathname and searchParams.

📖 Summary


📝 Exercises

  1. Complete all the code examples in this lesson and make sure each one runs correctly.
  2. Modify the comprehensive example and add your own extensions
  3. Review the official documentation, identify 1–2 APIs not covered in this lesson, and write test code for them.
  4. Reflection: How would you apply what you’ve learned in this lesson to a real-world project?
  5. Try to combine what you’ve learned in this lesson with material from previous lessons to build a small project.
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏