Create a Basic Node App (CommonJS)
A single resource answering GET /, written with require()
Steps
Folder Structure End State
- app.js
Install Node
Install Node (v20+).
Set Up the Project
Create a folder for the project and move into it.
mkdir my-project
cd my-projectCreate a package.json file. The -y flag skips the questions npm init would otherwise ask and accepts the default answer for each one.
npm init -ynpm init -y does not add a start script, so add one that runs the app. The command in “Run the Drash App”, under Verification, runs this script.
npm pkg set scripts.start="node app.js"Install the dependencies.
npm install @drashland/drashCreate the Following File
const {
Application,
Resource,
} = require("@drashland/drash/modules/http.polyfill");
const { createServer } = require("node:http");
class Home extends Resource { // Create a resource.
paths = ["/"]; // Tell it which path(s) it answers to.
GET(context) { // Node hands you the context object, not a Request.
console.log(`Received request: ${context.request.url}`);
context.response.end( // Write straight to Node's ServerResponse.
`Oh so easy (written at ${new Date()})`,
);
}
}
const app = Application
.builder() // Get the app's builder so we can build the app easily.
.resources(Home) // Add the `Home` resource to the app.
.build(); // Build the app.
const hostname = "localhost"; // Define server variables for reuse below.
const port = 1447;
const server = createServer((request, response) => {
// Node's `node:http` gives you `IncomingMessage` and `ServerResponse`, not
// a Web `Request`. Drash does not convert them for you — you hand the application
// a context object carrying whatever your resources need. The app's request
// chain only requires `url` and `method`.
const context = {
url: `http://${hostname}:${port}${request.url}`,
method: request.method,
request,
response,
};
return app // Let the app
.handle(context) // handle the context object, and
.catch((error) => { // catch anything it throws.
if (context.url.includes("favicon")) {
return response.end(); // Browsers ask for this; ignore it.
}
console.log(`Request URL hit an error: ${context.url}:\n`);
console.log({ error });
response.statusCode = 500; // Everything else gets a 500.
response.statusMessage = "Internal Server Error";
response.end("Sorry, but we hit an error!");
});
});
// Start the server.
server.listen(port, hostname, () => {
console.log(`\nDrash running at http://${hostname}:${port}`);
});The only differences from the ESM example are the require() calls, and that the polyfill specifier drops its .js extension.
Verification
Run the Drash App
npm startNote: npm start is defined in the package.json file.
Open It
Go to http://localhost:1447 . You should see something like the following:
Oh so easy (written at Wed Nov 01 2023 22:04:56 GMT-0400 (Eastern Daylight Time))Notes
Resources only recognize absolute URLs. Node’s request.url returns only a path, so it must be converted to a full URL first. For example:
/users/1 —> http://localhost:1447/users/1
Node uses the polyfill entry point, and its node:http server does not give you a Web Request — so the resource receives a context object that you build. The chain requires two fields on its input: a readable url and a readable method. Everything else on that object is yours.
The finished app is in the repository at examples/runtimes/node/basic-app-cjs.