REST API Example
Complete REST API implementation with CRUD operations.
Using the Router
The Router global provides clean, Express.js-style routing with path parameter support:
const router = new Router();
// In-memory storage (use KV store in production)
let items = [
{ id: 1, name: 'Item 1', description: 'First item' },
{ id: 2, name: 'Item 2', description: 'Second item' },
];
let nextId = 3;
// LIST: GET /
router.get('/', (req, res) => {
res.json({ items, count: items.length });
});
// GET: GET /:id
router.get('/:id', (req, res) => {
const id = parseInt(req.params.id);
const item = items.find(i => i.id === id);
if (!item) return res.status(404).json({ error: 'Item not found' });
res.json({ item });
});
// CREATE: POST /
router.post('/', (req, res) => {
const { name, description } = req.body;
if (!name) return res.status(400).json({ error: 'Name is required' });
const newItem = { id: nextId++, name, description: description || '' };
items.push(newItem);
res.status(201).json({ item: newItem });
});
// UPDATE: PUT /:id
router.put('/:id', (req, res) => {
const id = parseInt(req.params.id);
const item = items.find(i => i.id === id);
if (!item) return res.status(404).json({ error: 'Item not found' });
const { name, description } = req.body;
if (name) item.name = name;
if (description !== undefined) item.description = description;
res.json({ item });
});
// DELETE: DELETE /:id
router.delete('/:id', (req, res) => {
const id = parseInt(req.params.id);
const index = items.findIndex(i => i.id === id);
if (index === -1) return res.status(404).json({ error: 'Item not found' });
items.splice(index, 1);
res.status(204).end();
});
// 404 fallback
router.use((req, res) => {
res.status(404).json({ error: 'Endpoint not found' });
});
module.exports = router;
Testing the API
List Items
curl http://<your invoke-execution URL>/invoke/{functionId}
Get Single Item
curl http://<your invoke-execution URL>/invoke/{functionId}/1
Create Item
curl -X POST http://<your invoke-execution URL>/invoke/{functionId} \
-H "Content-Type: application/json" \
-d '{"name":"New Item","description":"A new item"}'
Update Item
curl -X PUT http://<your invoke-execution URL>/invoke/{functionId}/1 \
-H "Content-Type: application/json" \
-d '{"name":"Updated Item"}'
Delete Item
curl -X DELETE http://<your invoke-execution URL>/invoke/{functionId}/1
with KV Store Persistence
const router = new Router();
router.get('/', async (req, res) => {
const items = await kv.get('api:items') || [];
res.json({ items, count: items.length });
});
router.get('/:id', async (req, res) => {
const items = await kv.get('api:items') || [];
const item = items.find(i => i.id === parseInt(req.params.id));
if (!item) return res.status(404).json({ error: 'Item not found' });
res.json({ item });
});
router.post('/', async (req, res) => {
const { name, description } = req.body;
if (!name) return res.status(400).json({ error: 'Name is required' });
const items = await kv.get('api:items') || [];
const nextId = (await kv.get('api:nextId')) || 1;
const newItem = { id: nextId, name, description: description || '', createdAt: new Date().toISOString() };
items.push(newItem);
await kv.set('api:items', items);
await kv.set('api:nextId', nextId + 1);
res.status(201).json({ item: newItem });
});
router.put('/:id', async (req, res) => {
const items = await kv.get('api:items') || [];
const item = items.find(i => i.id === parseInt(req.params.id));
if (!item) return res.status(404).json({ error: 'Item not found' });
const { name, description } = req.body;
if (name) item.name = name;
if (description !== undefined) item.description = description;
item.updatedAt = new Date().toISOString();
await kv.set('api:items', items);
res.json({ item });
});
router.delete('/:id', async (req, res) => {
const items = await kv.get('api:items') || [];
const index = items.findIndex(i => i.id === parseInt(req.params.id));
if (index === -1) return res.status(404).json({ error: 'Item not found' });
items.splice(index, 1);
await kv.set('api:items', items);
res.status(204).end();
});
router.use((req, res) => res.status(404).json({ error: 'Endpoint not found' }));
module.exports = router;
With Pagination
const router = new Router();
router.get('/', async (req, res) => {
const items = await kv.get('api:items') || [];
// Filter
const search = req.query.search?.toLowerCase();
let filtered = search
? items.filter(i =>
i.name.toLowerCase().includes(search) ||
i.description.toLowerCase().includes(search)
)
: items;
// Sort
const sortBy = req.query.sortBy || 'id';
const sortOrder = req.query.order === 'desc' ? -1 : 1;
filtered.sort((a, b) => {
if (a[sortBy] < b[sortBy]) return -sortOrder;
if (a[sortBy] > b[sortBy]) return sortOrder;
return 0;
});
// Paginate
const page = parseInt(req.query.page) || 1;
const limit = parseInt(req.query.limit) || 10;
const offset = (page - 1) * limit;
const paginated = filtered.slice(offset, offset + limit);
res.json({
items: paginated,
pagination: {
page,
limit,
total: filtered.length,
pages: Math.ceil(filtered.length / limit),
hasNext: page * limit < filtered.length,
hasPrev: page > 1,
},
});
});
module.exports = router;
Next Steps
- KV Store Usage - Persistent storage
- Request Object - Handle requests
- Response Object - Send responses