Note
This documentation reflects the beta version of NodePlace. The current alpha version is a pre-release, aimed at gathering feedback from the community to shape the final product and address key developer pain points.
Typescript support is only available in es modules. however, that does not mean that the code will break in commonjs modules, only that you will have to turn of noImplicitAny in tsConfig and also other fields that may cause the ts compiler to complain.
This alpha version is not intended for serious projects but to try out and explore. Please report any issues or bugs you encounter on our Discord server. Your feedback is invaluable. Thank you in advance for helping make NodePlace better!
API Documentation
nodeplace()
The nodeplace() function initializes and returns a new NodePlace application instance.
import nodeplace from 'nodeplace'
const app = nodeplace()
Description
- Purpose: Initializes the core application instance for defining routes, mounting middleware, and configuring the framework.
- Return Value: Returns an application object with methods for handling requests, managing middleware, and starting the server.
Methods
nodeplace.json([options])
nodeplace.json is a built-in middleware function that parses incoming requests with JSON payloads. It populates the req.body property with the parsed data.
Features
- Content-Type Matching: Only processes requests where the Content-Type header matches application/json.
- Unicode Support: Accepts any Unicode encoding of the body.
- Error Handling: Automatically handles malformed JSON or empty bodies.
app.use(nodeplace.json(options))
Options
Option | Description | Type | Default |
---|---|---|---|
limit | Maximum size of the incoming JSON payload. | String or Number | 100kb |
strict | Ensures only objects and arrays are parsed (if set to true). | Boolean | true |
reviver | A function passed to JSON.parse to transform the parsed JSON. | Function | undefined |
Behavior
- Successful Parsing: Populates req.body with the parsed JSON object.
- Invalid JSON: Responds with:
- Status: 400
- Content-Type: Application/Json
- Body:{"message": "Unexpected token <input> is not valid JSON" }
- Empty Body: Responds with:
- Status: 400
- Content-Type: Application/Json
- Body:{ "message": "Failed to process empty body" }
- Internal Errors: Responds with:
- Status: 500
- Content-Type: Application/Json
- Body:{ "message": some server error }
Example
import nodeplace from 'nodeplace'
const app = nodeplace()
// Middleware to parse JSON payloads
app.use(nodeplace.json())
app.post('/data', (req, res) => {
console.log(req.body)
res.json({ message: 'Data received', data: req.body })
})
app.listen(3000, () => {
console.log('Server running on http://localhost:3000')
})
As req.bodyβs shape is based on user-controlled input, all properties and values in this object are untrusted and should be validated before trusting. For example, req.body.foo.toString() may fail in multiple ways, for example foo may not be there or may not be a string, and toString may not be a function and instead a string or other user-input.
nodeplace.static(root, [options])
nodeplace.static is a built-in middleware function for serving static files. It maps incoming requests to file paths within a specified root directory.
For best results, use a reverse proxy cache to improve performance of serving static assets.
Features
- File Serving:Serves static files such as HTML, png, and pdf.
- Cache Control:Supports options like maxAge and immutable for optimized client-side caching.
- Extension Fallbacks:Automatically serves files with specified extensions if the requested file is not found.
- Custom Headers:Allows setting custom HTTP headers for responses.
app.use(nodeplace.static(root, options))
Arguments
- root: (Optional) The directory from which to serve static assets. Defaults to 'public'.
- options: (Optional) An object specifying configuration options for serving static files.
Options (Optional)
Option | Description | Type | Default |
---|---|---|---|
dotfiles | Determines how dotfiles (files starting with .) are treated ('allow' or 'ignore'). | String | ignore |
etag | Enables or disables ETag generation for caching. | Boolean | true |
extensions | File extensions to try when the requested file is not found. | Array<String> | [] |
maxAge | Sets the max-age directive in the Cache-Control header (in milliseconds). | Number | 0 |
lastModified | Sets the Last-Modified header to the fileβs modification time. | Boolean | true |
immutable | Adds the immutable directive to Cache-Control for long-lived caching. Requires maxAge. | Boolean | false |
setHeaders | A custom function for setting headers on the response. | Function(res, path, stat) | undefined |
Behavior
- If a file is found:
- Responds with the file contents.
- Automatically sets headers like Content-Type, ETag, and Last-Modified if enabled.
- If a file is not found:
- If extensions are specified, attempts to resolve the file by appending each extension in the list.
- If still not found, invokes next() to pass control to the next middleware.
Example with Options
import nodeplace from 'nodeplace'
const options = {
dotfiles: 'ignore',
etag: true,
extensions: ['html', 'htm'],
maxAge: 86400000, // 1 day in milliseconds
immutable: true,
setHeaders: (res, path, stat) => {
res.setHeader('X-Custom-Header', 'NodePlace-Static')
}
}
const app = nodeplace()
app.use(nodeplace.static('assets', options))
app.listen(3000, () => {
console.log('Static file server running on http://localhost:3000')
})
nodeplace.urlencoded([options])
nodeplace.urlencoded is a built-in middleware function for parsing incoming requests with URL-encoded payloads. It is commonly used to parse form submissions.
Features
- Form Data Parsing:application/x-www-form-urlencoded payloads into a JavaScript object.
- Customizable Parsing:Supports configuration options to adjust how payloads are handled.
- Unicode Support:Fully compatible with Unicode-encoded bodies.
app.use(nodeplace.urlencoded(options))
Arguments (Optional)
Option | Description | Type | Default |
---|---|---|---|
parameterLimit | Limits the number of parameters parsed to prevent potential denial-of-service attacks. | Number | 1000 |
limit | Maximum size of the incoming JSON payload. | String or Number | 100kb |
Behavior
- Parses the request body and populates req.body with a key-value object.
- If the Content-Type does not match application/x-www-form-urlencoded, the middleware skips parsing.
- Validates the structure of the payload to ensure compatibility with the specified options.
Example
Basic Form Parsing
import nodeplace from 'nodeplace'
const app = nodeplace()
app.use(nodeplace.urlencoded({}))
app.post('/submit', (req, res) => {
console.log(req.body)
res.send('Form submitted!')
})
app.listen(3000, () => {
console.log('Server running on http://localhost:3000')
})
As req.bodyβs shape is based on user-controlled input, all properties and values in this object are untrusted and should be validated before trusting. For example, req.body.foo.toString() may fail in multiple ways, for example foo may not be there or may not be a string, and toString may not be a function and instead a string or other user-input.
Application()
The app object in NodePlace serves as the foundation of your application. It is created by calling the nodeplace() function and provides methods for defining routes, managing middleware, and controlling how your app handles HTTP requests.
Creating an Application
import nodeplace from 'nodeplace'
const app = nodeplace()
This initializes a new NodePlace application.
The app object comes with several methods and properties for managing application behavior, including route handling, middleware mounting, and configuration.
Methods
Method | Description |
---|---|
app.listen(port[, callback]) | Starts the server, binding it to the specified port. |
app.use([path], callback) | Mounts middleware functions at the specified path (default is /). |
app.get(path, callback) | Handles HTTP GET requests to the specified path. |
app.post(path, callback) | Handles HTTP POST requests to the specified path. |
app.put(path, callback) | Handles HTTP PUT requests to the specified path. |
app.delete(path, callback) | Handles HTTP DELETE requests to the specified path. |
Examples
Starting a Server
import nodeplace from 'nodeplace'
const app = nodeplace()
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000')
})
Adding Routes
app.get('/', (req, res) => {
res.send('Hello, world!')
})
app.post('/submit', (req, res) => {
res.send('Form submitted!')
})
Mounting Middleware
app.use((req, res, next) => {
console.log('Time:', Date.now())
next()
})
Methods
app.all(path, callback [, callback ...])
The app.all() method routes all HTTP methods to the specified path. This is useful for applying middleware or handling requests regardless of the HTTP method.
app.all(path, callback [, callback ...])
Parameters
- path:The path to match for the route.
- callback:One or more callback functions that handle the request. These follow the standard (req, res, next) signature.
Example: Logging All HTTP Methods
app.all('/logs', (req, res) => {
console.log(`${req.method} request to ${req.path}`)
res.send('This route handles all HTTP methods')
})
In this example:
- A single route /logs is defined to handle any HTTP method (GET, POST, PUT, DELETE, etc.).
- The server logs the method used for each request.
Example: Middleware Application
app.all('/secure/*', (req, res, next) => {
if (!req.isAuthenticated) {
res.status(401).send('Unauthorized')
} else {
next()
}
})
In this example:
- Middleware ensures that all requests to paths under /secure/ are authenticated.
- If the user is authenticated, the next handler is called.
app.delete(path, callback [, callback ...])
The app.delete() method routes HTTP DELETE requests to the specified path and handles them with the provided callback(s). It is commonly used to remove resources on the server.
app.delete(path, callback [, callback ...])
Parameters
- path:The route path where the handler should apply.
- callback:The route path where the handler should apply.
Example: Deleting a Resource
app.delete('/users/:id', (req, res) => {
const userId = req.params.id
// Logic to delete user by ID
res.send(`User with ID ${userId} deleted`)
})
In this example:
- The route /users/:id accepts DELETE requests.
- The req.params.id retrieves the user ID from the URL, and a confirmation response is sent.
Example: Middleware with DELETE
app.delete('/resources/:id', authenticate, (req, res) => {
const resourceId = req.params.id
// Logic to delete the resource
res.status(200).json({ message: `Resource ${resourceId} removed` })
})
In this example:
- Middleware authenticate ensures only authorized users can delete resources.
- A JSON response confirms the deletion.
app.disable(setting)
The app.disable method disables a specific setting.
Parameters:
- setting (String): The name of the setting to disable.
Example:
app.disable('poweredBy')
This disables the poweredBy header.
app.enable(setting)
The app.enable method explicitly enables a specific setting.
Parameters:
- setting (String): The name of the setting to enable.
Example:
app.enable('poweredBy');
This enables the poweredBy header.
app.get(path, callback [, callback ...])
The app.get() method routes HTTP GET requests to the specified path and handles them with the provided callback(s). This method is typically used to retrieve and display data or serve static pages.
Syntax
app.get(path, callback [, callback ...])
Parameters
- path:The route path where the handler should apply.
- callback:One or more callback functions to handle the request, with the standard (req, res, next) signature.
Example: Basic GET Handler
app.get('/', (req, res) => {
res.send('Welcome to the Homepage')
})
In this example:
- The route / accepts GET requests.
- A simple text response is sent to the client.
Example: Dynamic Routes
app.get('/users/:id', (req, res) => {
const userId = req.params.id
res.send(`User ID: ${userId}`)
})
In this example:
- The route /users/:id dynamically handles GET requests for user IDs.
- The req.params.id retrieves the dynamic portion of the URL.
Example: Middleware with GET
app.get('/dashboard', authenticate, (req, res) => {
res.send('Welcome to your dashboard')
})
In this example:
- Middleware authenticate ensures only logged-in users can access the dashboard.
Example: JSON Response
app.get('/api/products', (req, res) => {
res.json([
{ id: 1, name: 'Laptop', price: 1200 },
{ id: 2, name: 'Phone', price: 800 }
])
})
In this example:
- The route /api/products serves a JSON array of products.
- Use this for API endpoints.
app.listen(path, [callback])
The app.listen() method binds and listens for connections on the specified port or path. It is typically the final step in starting your NodePlace application, making it ready to handle incoming requests.
Syntax
app.listen([port[, host[, backlog]]][, callback])
app.listen(path, [callback])
Parameters
- Port(optional): The port number for the server to listen on.
- host(optional): The hostname or IP address to bind the server to. Defaults to "0.0.0.0".
- backlog(optional): The maximum number of pending connections the server will allow.
- path(optional): A Unix domain socket path or Windows named pipe for server connections.
- callback(optional): A function that executes once the server starts successfully.
If port is omitted or is 0, the operating system will assign an arbitrary unused port, which is useful for cases like automated tasks (tests, etc.).
import nodeplace from 'nodeplace'
const app = nodeplace()
app.listen(3000)
Example: Listening on a Port
app.listen(3000, () => {
console.log('Server is running at http://localhost:3000')
})
In this example:
- The server listens on port 3000.
- A success message is logged to the console.
Example: Listening on a Unix Socket
app.listen('/tmp/app.sock', () => {
console.log('Server is listening on /tmp/app.sock')
})
In this example:
- The server listens on a Unix domain socket at /tmp/app.sock.
- Suitable for inter-process communication on Unix-like systems.
Example: Dynamic Port Assignment
app.listen('/tmp/app.sock', () => {
console.log('Server is listening on /tmp/app.sock')
})
In this example:
- The operating system assigns an unused port dynamically.
- Use this for scenarios like test automation.
Using HTTPS and HTTP Together
import http from 'http'
import https from 'https'
const app = nodeplace()
http.createServer(app).listen(80, () => {
console.log('HTTP server running on port 80')
})
https.createServer({ key: privateKey, cert: certificate }, app).listen(443, () => {
console.log('HTTPS server running on port 443')
})
In this example:
- The same app handles both HTTP and HTTPS requests using Node.js' http and https modules.
- Use this for scenarios like test automation.
app.patch(path, callback [, callback ...])
The app.patch() method routes HTTP PATCH requests to the specified path and handles them with the provided callback(s). This method is typically used for partially updating resources.
Syntax
app.patch(path, callback [, callback ...])
Parameters
- path:The route path where the handler should apply.
- callback:One or more callback functions to handle the request, with the standard (req, res, next) signature.
Example: Basic PATCH Handler
app.patch('/user', (req, res) => {
res.send('User updated')
})
In this example:
- The route /user accepts PATCH requests.
- A simple confirmation message is sent to the client.
Example: Dynamic Routes
app.patch('/users/:id', (req, res) => {
const userId = req.params.id
res.send(`User with ID ${userId} has been updated`)
})
In this example:
- The route /users/:id dynamically handles PATCH requests for specific user IDs.
- req.params.id retrieves the dynamic portion of the URL to identify the user.
Example: Middleware with PATCH
app.patch('/settings', verifyToken, (req, res) => {
res.send('Settings have been updated')
})
In this example:
- Middleware verifyToken ensures that only authorized users can access the /settings route.
- The response confirms the successful update of settings.
Example: JSON Payload
app.patch('/api/products/:id', (req, res) => {
const { id } = req.params
const { name, price } = req.body
res.json({ id, updated: { name, price } })
})
In this example:
- The route /api/products/:id accepts PATCH requests with a JSON payload.
- The response includes the updated product details.
Example: Chained Middleware
app.patch(
'/profile',
validateProfileUpdate,
saveChanges,
(req, res) => {
res.send('Profile updated successfully')
}
)
In this example:
- Multiple middleware functions are chained together:
- validateProfileUpdate ensures incoming data is valid.
- saveChanges persists updates to the database.
- The final callback sends a success message to the client.
app.put(path, callback [, callback ...])
The app.put() method routes HTTP PUT requests to the specified path and handles them with the provided callback(s). This method is generally used to update or replace existing resources on the server.
Syntax
app.put(path, callback [, callback ...])
Parameters
- path:The route path where the handler should apply.
- callback:One or more callback functions to handle the request, with the standard (req, res, next) signature.
Example: Basic PUT Handler
app.put('/profile', (req, res) => {
res.send('Profile updated successfully')
})
In this example:
- The route /profile accepts PUT requests.
- A success message is sent to the client.
Example: Updating Resource Data
app.put('/users/:id', (req, res) => {
const userId = req.params.id
const updatedData = req.body
res.json({ message: `User ${userId} updated`, updatedData })
})
In this example:
- The route /users/:id dynamically handles PUT requests for specific users.
- req.params.id retrieves the user ID from the URL.
- req.body contains the updated user data sent in the request payload.
Example: Middleware with PUT
app.put('/settings', authenticate, (req, res) => {
res.send('Settings updated successfully')
})
In this example:
- Middleware authenticate ensures only authorized users can update settings.
- The final callback confirms the update.
Example: Handling Partial Updates with PUT
app.put('/orders/:orderId', (req, res) => {
const orderId = req.params.orderId
const changes = req.body
res.json({ message: `Order ${orderId} updated`, changes })
})
In this example:
- The route /orders/:orderId accepts PUT requests for modifying order details.
- The server responds with the applied changes.
Example: Chained Middleware for Validation
app.put(
'/posts/:id',
validatePostData,
updatePostInDatabase,
(req, res) => {
res.send('Post updated successfully')
}
)
In this example:
- Middleware functions validatePostData and updatePostInDatabase are chained together:
- validatePostData ensures the submitted data is valid.
- updatePostInDatabase applies the updates in the database.
- The final callback sends a success response to the client.
app.settings(options)
The app.settings method allows you to configure application-level settings, enabling or disabling specific features.
Parameters:
- options (Object): An object containing key-value pairs for settings.
Example:
app.settings({poweredBy: false })
In this example, the poweredBy header is disabled.
app.use([path,] callback [, callback ...])
The app.use() method mounts middleware, error handlers, or routers onto your NodePlace application. It is a versatile method that allows you to enhance your applicationβs functionality by adding reusable components to the request-response cycle.
Syntax
app.use([path,] callback [, callback ...])
Parameters
- path(optional): The base path at which the middleware or router is mounted. Defaults to /, applying the middleware globally.
- callback:One or more middleware functions, error handlers, or routers to process requests.
Example: Global Middleware
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`)
next()
})
In this example:
- A middleware logs each incoming requestβs method and URL.
- It applies globally to all routes.
Example: Path-Specific Middleware
app.use('/admin', authenticate)
In this example:
- The authenticate middleware is applied to all routes under /admin.
- Only authenticated users can access these routes.
Example: Mounting a Router
const userRouter = nodeplace.Router()
userRouter.get('/', (req, res) => {
res.send('User Home')
})
userRouter.get('/:id', (req, res) => {
res.send(`User ID: {req.params.id}`)
})
app.use('/users', userRouter)
In this example:
- A userRouter handles requests to /users and its subpaths.
- The routes /users/ and /users/:id are defined within the router.
Example: Serving Static Files
app.use(nodeplace.static('public'))
In this example:
- The static middleware serves files from the public directory.
- Requests for files like /images/logo.png are automatically handled.
Example: Middleware Chain
app.use(
'/dashboard',
authenticate,
logActivity,
(req, res) => {
res.send('Welcome to the Dashboard')
}
)
In this example:
- Multiple middleware functions (authenticate and logActivity) process requests to /dashboard.
- The final callback sends a success response.
Example: Error Handling
app.use((err, req, res, next) => {
console.error(err.stack)
res.status(500).send('Something went wrong!')
})
In this example:
- An error-handling middleware catches unhandled errors in the application.
- It sends a 500 status code along with an error message.
Request
The req object in NodePlace represents the HTTP request made by a client. It provides details about the request, such as headers, body, query parameters, and URL. This object is an enhanced version of Node.js' native request object, with additional properties and methods provided by NodePlace.
Additional Properties
req.body
Contains data submitted in the request body. Typically populated by body-parsing middleware, such as nodeplace.json() or nodeplace.urlencoded().
As req.bodyβs shape is based on user-controlled input, all properties and values in this object are untrusted and should be validated before trusting. For example, req.body.foo.toString() may fail in multiple ways, for example foo may not be there or may not be a string, and toString may not be a function and instead a string or other user-input.
Example: Accessing req.body
app.post('/profile', (req, res) => {
res.send(`Name: ${req.body.name}`)
})
In this example:
- Data sent in the body (e.g., {"name": "John"}) is accessible via req.body.
req.params
An object containing properties mapped to route parameters. For example, if the route defines /users/:id, the id parameter is available as req.params.id.
As req.paramsβs shape is based on user-controlled input, all properties and values in this object are untrusted and should be validated before trusting. For example, req.params.foo.toString() may fail in multiple ways, for example foo may not be there or may not be a string, and toString may not be a function and instead a string or other user-input.
Example: Accessing Route Parameters
app.get('/users/:id', (req, res) => {
res.send(`User ID: ${req.params.id}`)
})
In this example:
- A request to /users/123 will respond with User ID: 123.
req.query
An object containing the query string parameters from the URL.
As req.queryβs shape is based on user-controlled input, all properties and values in this object are untrusted and should be validated before trusting. For example, req.query.foo.toString() may fail in multiple ways, for example foo may not be there or may not be a string, and toString may not be a function and instead a string or other user-input.
Example: Accessing Query Parameters
app.get('/search', (req, res) => {
res.send(`Search term: ${req.query.q}`)
})
In this example:
- A request to /search?q=NodePlace will respond with Search term: NodePlace.
req.res
This property holds a reference to the response object. The response is the extended version of the NodePlace response, which means it also have the extended properties and methods
Response
The res object in NodePlace represents the HTTP response that your application sends to a client. It provides methods for sending data, setting headers, and controlling the HTTP status of the response. This object extends Node.js' native response object with additional methods and properties provided by NodePlace.
res.clearCookie(name [, options])
Clears the cookie specified by name. For the cookie to be cleared properly, the options provided to res.clearCookie must match those used when setting the cookie with res.cookie(), excluding expires and maxAge.
Example: Clearing a Cookie
app.get('/clear-cookie', (req, res) => {
res.cookie('username', 'john_doe', { path: '/user', httpOnly: true })
res.clearCookie('username', { path: '/user', httpOnly: true })
res.send('Cookie cleared')
})
Parameters
- name:(string, required) The name of the cookie to clear.
- options (optional):(optional) An object specifying attributes of the cookie to match when clearing it. See res.cookie() for the available options.
Behavior:
If options like path, domain, or secure were specified when the cookie was set using res.cookie(), they must be included in res.clearCookie() to match the original cookie. For example:
res.cookie('key', 'value', { path: '/api' })
res.clearCookie('key', { path: '/api' }) // Matches and clears the cookie.
res.json([body])
Sends a JSON response. This method sets the Content-Type header to application/json automatically.
Example: Sending JSON
app.get('/users', (req, res) => {
res.json([{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }])
})
res.redirect([status,] path)
Redirects the client to a specified path or URL. Optionally accepts an HTTP status code (default is 302).
Example: Redirecting to a URL
app.get('/old-page', (req, res) => {
res.redirect('/new-page')
})
Example: Redirecting with a Custom Status Code
app.get('/moved-permanently', (req, res) => {
res.redirect(301, '/new-page')
})
res.send([body])
Sends a response to the client. The body parameter can be a string, buffer, array, or object.
Example: Sending Text Response
app.get('/welcome', (req, res) => {
res.send('Welcome to NodePlace!')
})
Example: Sending JSON Response
app.get('/api/data', (req, res) => {
res.send({ id: 1, name: 'NodePlace' })
})
res.sendFile(path [, options] [, callback])
Transfers the file at the given path to the client. Sets the Content-Type response HTTP header field based on the fileβs extension. If the root option is set, the path argument can be a relative path; otherwise, it must be an absolute path.
The method supports caching, range requests, and additional headers to fine-tune the response. Use it to serve static files or dynamically generated paths.
Example: Serving a Static File
app.get('/download', (req, res) => {
res.sendFile('/absolute/path/to/file.zip', {
cacheControl: true,
maxAge: 3600, // 1 hour
})
})
Example: Serving with Options
app.get('/file/:name', (req, res, next) => {
const options = {
root: path.join(__dirname, 'public'),
dotfiles: 'deny',
maxAge: '1d',
cacheControl: true,
immutable: true,
headers: {
'x-timestamp': Date.now(),
'x-sent': true,
},
}
const fileName = req.params.name
res.sendFile(fileName, options, (err) => {
if (err) {
next(err) // Pass control to error handling middleware
} else {
console.log('File sent:', fileName)
}
})
})
Options
Option | Description | Type | Default |
---|---|---|---|
maxAge | Specifies the Cache-Control max-age in milliseconds. | number | 0 |
root | The root directory for resolving the relative file path. | string | null |
headers | Allows you to set additional HTTP headers. This can be useful for security or metadata requirements. | Object | null |
dotfiles | Determines how dotfiles (hidden files starting with .) are handled. Can be one of "allow", "deny", or "ignore". | string | "ignore" |
acceptRanges | Enables or disables support for range requests. | Boolean | true |
cacheControl | Enables or disables the Cache-Control header in the response. When enabled, use maxAge to specify the cache duration. | Boolean | true |
immutable | Adds the immutable directive to the Cache-Control header. This is useful for static files that will never change. If enabled, maxAge should also be set to allow caching. | Boolean | false |
lastModified | Automatically sets the Last-Modified header based on the fileβs last modified timestamp on the file system. Setting this to false disables the header. | Boolean | true |
disposition | Controls the Content-Disposition header for the file. Can be "inline" (display in-browser) or "attachment" (download file). If unspecified, it defaults to "inline" for most files and "attachment" for certain MIME types like archives. | String | "inline" / "attachment" based on file type |
res.set(field [, value])
Sets the HTTP header field to a specific value.
Example: Setting a Header
app.get('/custom-header', (req, res) => {
res.set('X-Custom-Header', 'NodePlace')
res.send('Header set')
})
res.status(code)
Sets the HTTP status code for the response. Returns the res object for chaining.
Example: Setting Status Code
app.get('/not-found', (req, res) => {
res.status(404).send('Page not found')
})
res.type(type)
Sets the Content-Type HTTP header to the specified MIME type.
Example: Setting Content Type
app.get('/text', (req, res) => {
res.type('text/plain')
res.send('This is plain text')
})
Example: Setting JSON Type
app.get('/json', (req, res) => {
res.type('application/json')
res.send({ message: 'This is JSON' })
})
Router
The Router object in NodePlace is an instance of middleware and routing functionality. It acts as a "mini-application" that can have its own middleware, routes, and error-handling logic. Routers are particularly useful for modularizing your application by separating concerns and grouping related routes.
Syntax
const router = nodeplace.Router()
Features of Router
- Modular and mountable, allowing for clean separation of application logic.
- Can handle its own middleware, routes, and error handlers.
Creating a Router
Example: Basic Router Setup
const router = nodeplace.Router()
router.get('/', (req, res) => {
res.send('Welcome to the Router!')
})
app.use('/router', router)
Features of Router
- A router is created using nodeplace.Router().
- The router handles requests to /router and responds to /router/ with a welcome message.
Handling Routes with Router
Dynamic Routes
You can define dynamic routes with parameters directly in the router.
router.get('/user/:id', (req, res) => {
res.send(`User ID: ${req.params.id}`)
})
Explanation:
- The router handles requests to /user/:id, where :id is a dynamic parameter.
- Use req.params.id to access the dynamic value.
Using Middleware in Routers
Routers can have middleware specific to their routes.
router.use((req, res, next) => {
console.log('Router-specific middleware')
next()
})
router.get('/dashboard', (req, res) => {
res.send('Router-specific Dashboard')
})
Explanation:
- Middleware added to the router applies only to routes defined within that router.
Combining Middleware and Routes
router.get(
'/example',
(req, res, next) => {
console.log('Middleware before response')
next()
},
(req, res) => {
res.send('Hello from Example!')
}
)
Explanation:
- Middleware added to the router applies only to routes defined within that router.
Mounting Routers
Routers can be mounted on specific paths in the main application.
Example: Mounting a Router
const adminRouter = nodeplace.Router()
adminRouter.get('/settings', (req, res) => {
res.send('Admin Settings')
})
app.use('/admin', adminRouter)
Explanation:
- The adminRouter handles routes prefixed with /admin.
- Requests to /admin/settings are served by the router.
Router-Level Middleware
Middleware specific to a router can be added using router.use().
Example: Router Middleware
const loggingMiddleware = (req, res, next) => {
console.log(`Request Method: ${req.method}, Path: ${req.path}`)
next()
}
router.use(loggingMiddleware)
router.get('/profile', (req, res) => {
res.send('Profile Page')
})
Explanation:
- The middleware logs each request method and path before the route handler is executed.
Method: router.route(path)
Defines multiple HTTP method handlers for a single route.
Example: Handling Multiple Methods
router.route('/items')
.get((req, res) => {
res.send('List of Items')
})
.post((req, res) => {
res.send('Create a New Item')
})
.put((req, res) => {
res.send('Update an Item')
})
.delete((req, res) => {
res.send('Delete an Item')
})
Explanation:
- Use router.route() to define GET, POST, PUT, and DELETE handlers for /items.
Nested Routers
NodePlace allows routers to be nested infinitely, providing a powerful way to organize complex applications into manageable modules. Nested routers inherit middleware and routing logic from their parent routers, enabling seamless composition of application features.
Example: Basic Nested Router Setup
const nodeplace = require('nodeplace')
const app = nodeplace()
// Main Router
const mainRouter = nodeplace.Router()
// Sub Router
const subRouter = nodeplace.Router()
subRouter.get('/info', (req, res) => {
res.send('This is nested inside the main router!')
})
// Mount Sub Router onto Main Router
mainRouter.use('/sub', subRouter)
// Mount Main Router onto the App
app.use('/main', mainRouter)
Explanation:
- The subRouter is mounted on the /sub path of mainRouter
- The mainRouter is mounted on the /main path of the app.
- A request to /main/sub/info will pass through both the mainRouter and subRouter.
Example: Middleware in Nested Routers
// Define middleware for subRouter
subRouter.use((req, res, next) => {
console.log('SubRouter Middleware Triggered')
next()
})
subRouter.get('/data', (req, res) => {
res.json({ message: 'Nested router data' })
})
// Main Router Middleware
mainRouter.use((req, res, next) => {
console.log('MainRouter Middleware Triggered')
next()
})
// Mount the Sub Router onto Main Router
mainRouter.use('/sub', subRouter)
Explanation:
- Middleware defined in mainRouter is executed before any middleware or routes in subRouter.
- Nested routers allow middleware at different levels of the hierarchy to work together.
Example: Deeply Nested Routers
// Level 3 Router
const level3Router = nodeplace.Router()
level3Router.get('/deep', (req, res) => {
res.send('Deeply nested route')
})
// Level 2 Router
const level2Router = nodeplace.Router()
level2Router.use('/level3', level3Router)
// Level 1 Router
const level1Router = nodeplace.Router()
level1Router.use('/level2', level2Router)
// Mount Level 1 Router onto the App
app.use('/level1', level1Router)
Explanation:
- The level3Router is nested within level2Router, which is nested within level1Router.
- A request to /level1/level2/level3/deep passes through all routers in the hierarchy.
Key Benefits of Nested Routers
- Modularization: Split application logic into smaller, reusable units.
- Hierarchy: Build complex applications with clear routing hierarchies.
- Isolation: Each router can have its own middleware and error-handling logic, ensuring clean separation of concerns.