
Research
Two Malicious Rust Crates Impersonate Popular Logger to Steal Wallet Keys
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
node-web-server-with-stuff
Advanced tools
It's just that - a vanilla web server with some of my modules with no thirdparty modules. Yet. It provides an uniform way of server development for serving files and API-endpoints both.
A simple and customizable Node.js web server built with the built-in http
module, enhanced with additional utilities for easier development and deployment.
http
module, no external web frameworks.up2require
.httpity
: Simplifies HTTP request and response handling.up2require
: Enhances require
for hot reloading.c4console
: Enhanced console.log
functionality.Install the package via npm:
npm install node-web-server-with-stuff
Create a simple server with default settings:
const { server } = require('node-web-server-with-stuff');
server.run();
This will:
3000
locally or use the PORT
environment variable (useful for deployment platforms)./public
directory in the project root.index.html
if a request is made to the root URL..html
files if a request is made to a path that doesn't have an extension./api
directory.You can customize the server by passing an options object to server.run()
:
const { server } = require('node-web-server-with-stuff');
const options = {
port: 5500,
publicPath: '/front',
dev: false, // Force production mode
secure: true, // Enable access control for APIs
accessors: '/checks', // Directory for access control functions
api: ['/data', '/secret_api'], // Directories for API handlers
given: { /* Custom objects to pass to handlers */ },
};
server.run(options);
port
(number): Port number to run the server on. Defaults to process.env.PORT
or 3000
.publicPath
(string): Path to the directory containing static files. Defaults to /public
.dev
(boolean): Set to true
for development mode or false
for production mode. Automatically determined if not set.secure
(boolean): Enable or disable access control for API endpoints. Defaults to false
.accessors
(string): Directory containing access control functions. Defaults to /access
.api
(string | string[]): Path(s) to directories containing API handlers. Defaults to /api
.given
(object): Custom objects or functions to pass to API handlers and access control functions.The server serves static files from the publicPath
directory and its subdirectories. When a request is made to a URL, the server looks for a corresponding file there.
For example, with publicPath
set to /public
, a request to /about/page
(without extension specified) will look for:
/public/about/page/index.html
.page
exists in /public/about/
, it will look for a file named page
in that directory, without an extension.page
exists in /public/about/
, it will look for page.html
.page.html
either, it will serve the 404 page.API handlers are modules that process incoming API requests. Place your API handler modules in one or more directories specified by the api
option (default is /api
).
/api/notes.js
or /api/notes.cjs
will handle requests to the /api/notes
endpoint.An API handler can be a JavaScript file exporting a function:
// /api/notes.js or /api/notes.cjs or similar
module.exports = async function ({ request, response, granted, conn, validateFn, rules, ...rest }) {
// Handle the request and return the response data
const data = await request.data; // Parsed request body and query parameters
// ... perform operations ...
return { success: true, data: /* ... */ };
// Returned data can be any JSON-serializable object
};
Note: Throughout this documentation, req
and resp
are available aliases for request
and response
respectively, so they can be destructured under those names if preferred.
request
: Enhanced HTTP request object provided by httpity
.response
: Enhanced HTTP response object provided by httpity
.granted
: Result from the access control function (if access control is enabled).conn
, validateFn
, rules
, etc.: Custom objects passed via the given
option....rest
: Any additional objects passed via the given
option.You can define handlers for specific HTTP methods. Instead of exporting a single function, export an object with sub-objects for each HTTP method, specifying the access level and the handler function:
// /api/notes.js or /api/notes.cjs or similar
module.exports = {
GET: {
access: 'guest', // Full access
handler: async function ({ request, response, ...rest }) {
// Handle GET requests
},
},
POST: {
access: 'user', // Requires the /access/user.js function
handler: async function ({ request, response, granted, ...rest }) {
// Handle POST requests with user access
},
},
DELETE: {
access: 'admin', // Requires the /access/admin.js function or the ADMIN_KEY
handler: async function ({ request, response, granted, ...rest }) {
// Handle DELETE requests with admin access
},
},
};
There's also a simpler way to define handlers for specific HTTP methods if you don't need access control:
// /api/notes.js or /api/notes.cjs or similar
module.exports = {
GET: ({ request, response, ...rest }) => {
// Handle GET requests
},
POST: ({ request, response, ...rest }) => {
// Handle POST requests
},
DELETE: ({ request, response, ...rest }) => {
// Handle DELETE requests
},
};
When the secure
option is set to true
, API endpoints require access checks before processing requests. Access control functions are placed in the directory specified by the accessors
option (default is /access
).
Without custom accessors, the server uses a simple cookie-based access control:
key
with the value matching the ADMIN_KEY
environment variable (customizable via an .env
file).guest
.access: 'guest'
are available without any access checks.unauthorized
.secure: true
and an API handler specifies an access level without a corresponding accessor function in the /access
directory, the endpoint will respond with unauthorized
.Each access level corresponds to a module exporting a function:
// /access/user.js or /access/user.cjs or similar
module.exports = async function ({ request, response, conn, ...rest }) {
const token = request.cookies.token;
const user = await conn.collection('users').findOne({ token });
if (user) {
return user; // Return user data to be available in `granted`
} else {
throw new Error('Unauthorized');
}
};
Specify the required access level in the handler definition:
// /api/notes.js
module.exports = {
POST: {
access: 'user', // Requires the `/access/user.js` function
handler: async function ({ request, response, granted, ...rest }) {
// `granted` contains the user data returned from the access control function
},
},
};
If secure: true
and an API handler specifies an access level without a corresponding accessor function, the server will respond with unauthorized
.
The package provides additional helper modules to simplify development:
up2require
An alias for upgradeToUpdate
from the up2require
module.
During development, modules loaded using the upgraded require
function from up2require
will hot reload. You can add, change, or remove them at any time without restarting the server. This is especially useful for rapid development and testing.
up2require
in Development ModeReplace Node.js's require
function with the upgraded one during development:
const { server, up2 } = require('node-web-server-with-stuff');
if (server.dev) {
require = up2(require);
}
To enable hot reloading for a specific module, pass true
as the second argument to the upgraded require
function:
const myModule = require('./myModule', true);
All API handlers are automatically hot-reloaded during development.
c4console
An enhanced version of console.log
from the c4console
module.
const { c } = require('node-web-server-with-stuff');
c('This is an enhanced console log message');
But c
can also be better used like this:
// No imports required to use as a method
[1, 2, 3].map(x => x * 2).c('doubled').map(x => x * 3).c('tripled');
/* Will log: */
// doubled: (3) [2, 4, 6]
// tripled: (3) [6, 12, 18]
Note that the c
method is inherited by any non-empty value from Object.prototype
, takes an optional label argument, and returns the value it was called on. This allows it to be inserted into a chain of property reads or function calls to see intermediate values without breaking the chain logic.
publicPath
Serve static files from a custom directory:
const { server } = require('node-web-server-with-stuff');
server.run({ publicPath: '/frontend' });
Provide a database connection and other utilities to API handlers:
const { server } = require('node-web-server-with-stuff');
const db = require('./db'); // Your database module
const validateFn = require('./validate');
const rules = require('./rules');
const conn = db.connect(/* credentials */);
server.run({
secure: true,
given: { conn, validateFn, rules },
});
// /api/data/notes.js
module.exports = {
GET: {
access: 'user',
handler: async function ({ request, response, granted, conn }) {
const notes = await conn.collection('notes').find({ userId: granted.id }).toArray();
return { notes };
},
},
};
// /access/user.js
module.exports = async function ({ request, response, conn }) {
const token = request.cookies.token;
const user = await conn.collection('users').findOne({ token });
if (user) {
return user;
} else {
throw new Error('Unauthorized');
}
};
FAQs
It's just that - a vanilla web server with some of my modules with no thirdparty modules. Yet. It provides an uniform way of server development for serving files and API-endpoints both.
We found that node-web-server-with-stuff demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
Research
A malicious package uses a QR code as steganography in an innovative technique.
Research
/Security News
Socket identified 80 fake candidates targeting engineering roles, including suspected North Korean operators, exposing the new reality of hiring as a security function.