REST API Demo

This demo showcases how to build RESTful APIs using StoneJS Framework's dhandler system. All endpoints below are fully functional and return JSON responses.

What is a Dhandler?

A dhandler is a special file that handles all requests for paths that don't have a specific file. It's perfect for building dynamic APIs with route parameters.

API Overview

The API is implemented in /pages/demo/api/dhandler and handles all requests to /demo/api/*.

Base URL: http://localhost:3000/demo/api

Available Endpoints

GET /demo/api

Description: API information and available endpoints

Response:

{ "message": "StoneJS Framework API Demo", "version": "1.0.0", "endpoints": { ... } }

Try it:

Open in new tab →

Users API

GET /demo/api/users

Description: List all users with pagination support

Query Parameters:

Parameter Type Description
page integer Page number (default: 1)
limit integer Items per page (default: 10)

Response:

{ "success": true, "data": [ { "id": 1, "name": "Alice Johnson", "email": "[email protected]", "role": "admin" }, ... ], "meta": { "page": 1, "limit": 10, "total": 4, "totalPages": 1 } }

Try it:

/demo/api/users → /demo/api/users?page=1&limit=2 →

GET /demo/api/users/:id

Description: Get a specific user by ID

Path Parameters:

Response (Success):

{ "success": true, "data": { "id": 1, "name": "Alice Johnson", "email": "[email protected]", "role": "admin" } }

Response (Not Found):

{ "success": false, "error": "User not found", "requestedId": 999 }

Try it:

/demo/api/users/1 → /demo/api/users/2 → /demo/api/users/999 (404) →

POST /demo/api/users

Description: Create a new user (demo only - not persisted)

Request Body:

{ "name": "John Doe", "email": "[email protected]", "role": "user" }

Response:

{ "success": true, "message": "User created (demo - not persisted)", "data": { "id": 5, "name": "John Doe", "email": "[email protected]", "role": "user", "created": "2024-01-15T10:30:00.000Z" } }

Try it with curl:

curl -X POST http://localhost:3000/demo/api/users \ -H "Content-Type: application/json" \ -d '{"name":"John Doe","email":"[email protected]","role":"user"}'

Products API

GET /demo/api/products

Description: List all products with optional price filtering

Query Parameters:

Parameter Type Description
minPrice float Minimum price filter
maxPrice float Maximum price filter

Response:

{ "success": true, "data": [ { "id": 1, "name": "Laptop", "price": 999.99, "stock": 15 }, ... ], "meta": { "total": 4, "filters": { "minPrice": 0, "maxPrice": Infinity } } }

Try it:

/demo/api/products → /demo/api/products?minPrice=50&maxPrice=200 →

GET /demo/api/products/:id

Description: Get a specific product by ID

Path Parameters:

Response:

{ "success": true, "data": { "id": 1, "name": "Laptop", "price": 999.99, "stock": 15 } }

Try it:

/demo/api/products/1 → /demo/api/products/3 →

Session API

GET /demo/api/session

Description: Get current session information

Response:

{ "success": true, "session": { "id": "abc123...", "visitCount": 5, "userName": "John Doe" } }

Try it:

/demo/api/session →

Cache Demo API

GET /demo/api/cache-demo

Description: Demonstrates caching with a 30-second TTL

Response:

{ "success": true, "message": "This data is cached for 30 seconds", "data": { "timestamp": "2024-01-15T10:30:00.000Z", "randomNumber": 0.123456 }, "note": "Make multiple requests within 30s to see the same data" }

Try it:

/demo/api/cache-demo →

Refresh the endpoint multiple times within 30 seconds - the timestamp and random number will stay the same!

Error Handling

Error Responses

404 Not Found:

{ "success": false, "error": "Endpoint not found", "requestedPath": "/invalid", "availableEndpoints": [...] }

405 Method Not Allowed:

{ "success": false, "error": "Method not allowed", "allowed": ["GET", "POST"] }

500 Internal Server Error:

{ "success": false, "error": "Internal server error", "message": "Error details..." }

Try it:

/demo/api/nonexistent (404) →

Implementation Guide

Creating the API Dhandler

The API is implemented in /pages/demo/api/dhandler:

<%%js> // Get the dynamic path after /api/ const path = $context.dhandlerPath; const parts = path.split('/').filter(p => p); const method = $req.method; // Set JSON response header $res.setHeader('Content-Type', 'application/json'); // Route handling if (parts[0] === 'users') { if (method === 'GET' && parts.length === 1) { // GET /api/users - List all users $res.send(JSON.stringify({ success: true, data: users })); } else if (method === 'GET' && parts.length === 2) { // GET /api/users/:id - Get specific user const userId = parseInt(parts[1]); const user = users.find(u => u.id === userId); if (user) { $res.send(JSON.stringify({ success: true, data: user })); } else { $res.status(404).send(JSON.stringify({ success: false, error: 'User not found' })); } } } </js%%>

Key Features

Accessing Request Data

// Query parameters const page = $req.query.page; // ?page=1 const limit = $req.query.limit; // &limit=10 // Route parameters (from path) const userId = parts[1]; // /users/123 // Request body (POST/PUT) const data = $req.body; // JSON body // HTTP method const method = $req.method; // GET, POST, etc. // Headers const auth = $req.headers.authorization;

Setting Response Headers

// JSON API $res.setHeader('Content-Type', 'application/json'); // CORS (if needed) $res.setHeader('Access-Control-Allow-Origin', '*'); // Custom headers $res.setHeader('X-Custom-Header', 'value');

Working with Sessions and Cache

// Session data in API const userId = $session.userId; $session.lastApiCall = new Date(); // Caching API responses const data = await $cache.remember('api-data', 300, async () => { // Expensive operation return await fetchDataFromDatabase(); }); $res.send(JSON.stringify({ success: true, data }));

Testing the API

Using curl

# GET request curl http://localhost:3000/demo/api/users # GET with query parameters curl "http://localhost:3000/demo/api/products?minPrice=50&maxPrice=200" # POST request with JSON curl -X POST http://localhost:3000/demo/api/users \ -H "Content-Type: application/json" \ -d '{"name":"Jane Doe","email":"[email protected]"}' # GET specific resource curl http://localhost:3000/demo/api/users/1

Using JavaScript fetch()

// GET request fetch('/demo/api/users') .then(res => res.json()) .then(data => console.log(data)); // POST request fetch('/demo/api/users', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'Jane Doe', email: '[email protected]', role: 'user' }) }) .then(res => res.json()) .then(data => console.log(data));

Best Practices

API Development Tips:

Try It Yourself

  1. Click the API links above to see live JSON responses
  2. Open your browser's Developer Tools (Network tab) to see requests
  3. Try the curl commands in your terminal
  4. Modify the dhandler to add your own endpoints
  5. Experiment with different query parameters