Building REST API with Pure Node.js
Now that you know how to serve HTML and static files, let's take it a step further and build a real **REST API** using only Node.js built-in modules. This will give you a deep understanding of how APIs work before you start using frameworks like Express.
What is a REST API?
A REST API is a way for different software applications to communicate over HTTP. It uses standard HTTP methods (GET, POST, PUT, DELETE) to perform CRUD operations on resources.
| HTTP Method | CRUD Operation | Example Endpoint |
|---|---|---|
| GET | Read | `/api/users` – get all users |
| GET | Read | `/api/users/1` – get user with id 1 |
| POST | Create | `/api/users` – create a new user |
| PUT | Update | `/api/users/1` – update user with id 1 |
| DELETE | Delete | `/api/users/1` – delete user with id 1 |
Think of a REST API as a restaurant menu. You look at the menu (GET), order food (POST), ask for a change (PUT), or cancel your order (DELETE).
Our Project: Simple User API
We'll build an API that manages a list of users. We'll store users in memory (an array) for simplicity. In a real application, you'd use a database.
Step 1: Setting Up the Server
const http = require('http');const url = require('url');
let users = [ { id: 1, name: 'John Doe', email: 'john@example.com' }, { id: 2, name: 'Jane Smith', email: 'jane@example.com' }];
const server = http.createServer((req, res) => { <!-- Set JSON as default content type --> res.setHeader('Content-Type', 'application/json'); const parsedUrl = url.parse(req.url, true); const pathname = parsedUrl.pathname; const method = req.method; <!-- Handle routes --> <!-- We'll fill this in next steps -->});
server.listen(3000, () => { console.log('API server running on port 3000');});Step 2: GET All Users
if (pathname === '/api/users' && method === 'GET') { res.writeHead(200); res.end(JSON.stringify(users));}Step 3: GET Single User by ID
if (pathname.match(/^/api/users/d+$/) && method === 'GET') { const id = parseInt(pathname.split('/')[3]); const user = users.find(u => u.id === id); if (user) { res.writeHead(200); res.end(JSON.stringify(user)); } else { res.writeHead(404); res.end(JSON.stringify({ error: 'User not found' })); }}Step 4: POST – Create New User
For POST requests, we need to read the request body. This is done by listening to `data` and `end` events.
if (pathname === '/api/users' && method === 'POST') { let body = ''; req.on('data', chunk => { body += chunk.toString(); }); req.on('end', () => { try { const newUser = JSON.parse(body); <!-- Generate new ID --> const id = users.length ? Math.max(...users.map(u => u.id)) + 1 : 1; const user = { id, ...newUser }; users.push(user); res.writeHead(201); <!-- Created --> res.end(JSON.stringify(user)); } catch (err) { res.writeHead(400); res.end(JSON.stringify({ error: 'Invalid JSON' })); } });}Step 5: PUT – Update User
if (pathname.match(/^/api/users/d+$/) && method === 'PUT') { const id = parseInt(pathname.split('/')[3]); let body = ''; req.on('data', chunk => { body += chunk.toString(); }); req.on('end', () => { try { const updatedData = JSON.parse(body); const index = users.findIndex(u => u.id === id); if (index !== -1) { users[index] = { ...users[index], ...updatedData }; res.writeHead(200); res.end(JSON.stringify(users[index])); } else { res.writeHead(404); res.end(JSON.stringify({ error: 'User not found' })); } } catch (err) { res.writeHead(400); res.end(JSON.stringify({ error: 'Invalid JSON' })); } });}Step 6: DELETE – Remove User
if (pathname.match(/^/api/users/d+$/) && method === 'DELETE') { const id = parseInt(pathname.split('/')[3]); const index = users.findIndex(u => u.id === id); if (index !== -1) { users.splice(index, 1); res.writeHead(204); <!-- No content --> res.end(); } else { res.writeHead(404); res.end(JSON.stringify({ error: 'User not found' })); }}Step 7: 404 for unknown routes
res.writeHead(404);res.end(JSON.stringify({ error: 'Route not found' }));Two Minute Drill
- REST APIs use HTTP methods to perform CRUD operations.
- Use `req.method` and `req.url` to route requests.
- For POST/PUT, collect the request body by listening to `data` and `end` events.
- Always parse JSON body with `JSON.parse()` and handle errors.
- Send appropriate status codes (200, 201, 204, 400, 404).
- This is how Express and other frameworks work under the hood.
Need more clarification?
Drop us an email at career@quipoinfotech.com
