Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
357 changes: 357 additions & 0 deletions assignments/02-events-http.md

Large diffs are not rendered by default.

341 changes: 341 additions & 0 deletions lessons/02-events-http.md

Large diffs are not rendered by default.

69 changes: 69 additions & 0 deletions mentor-guidebook/sample-answers/assignment2/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import express from "express";
import errorHandler from "../middleware/error-handler.js";
import notFound from "../middleware/not-found.js";

const app = express();

app.use((req, res, next) => {
console.log("Method:", req.method);
console.log("Path:", req.path);
console.log("Query:", req.query);
next();
})

app.get("/", (req, res) => {
res.send("Hello, World!");
});

app.post("/testpost", (req, res) => {
res.json({message: "Everything Worked."});
})

app.use(notFound);
app.use(errorHandler);


const port = process.env.PORT || 3000;
const server = app.listen(port, () =>
console.log(`Server is listening on port ${port}...`),
);

server.on('error', (err) => {
if (err.code === 'EADDRINUSE') {
console.error(`Port ${port} is already in use.`);
} else {
console.error('Server error:', err);
}
process.exit(1);
});

let isShuttingDown = false;
async function shutdown(code = 0) {
if (isShuttingDown) return;
isShuttingDown = true;
console.log('Shutting down gracefully...');
try {
await new Promise(resolve => server.close(resolve));
console.log('HTTP server closed.');
// If you have DB connections, close them here
} catch (err) {
console.error('Error during shutdown:', err);
code = 1;
} finally {
console.log('Exiting process...');
process.exit(code);
}
}

process.on('SIGINT', () => shutdown(0)); // ctrl+c
process.on('SIGTERM', () => shutdown(0)); // e.g. `docker stop`
process.on('uncaughtException', (err) => {
console.error('Uncaught exception:', err);
shutdown(1);
});
process.on('unhandledRejection', (reason) => {
console.error('Unhandled rejection:', reason);
shutdown(1);
});

export { server, app };
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import EventEmitter from "events";

const emitter = new EventEmitter();

emitter.on("tell", (message) => {
// this registers a listener
console.log("listener 1 got a tell message:", message);
});

emitter.on("tell", (message) => {
// listener 2. You don't want too many in the chain
console.log("listener 2 got a tell message:", message);
});

emitter.on("error", (error) => {
// a listener for errors. It's a good idea to have one per emitter
console.log("The emitter reported an error.", error.message);
});

emitter.emit("tell", "Hi there!");
emitter.emit("tell", "second message");
emitter.emit("tell", "all done");
17 changes: 17 additions & 0 deletions mentor-guidebook/sample-answers/assignment2/assignment2/events.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import EventEmitter from "events";

const emitter = new EventEmitter();

emitter.on("time", (message) => {
console.log("Time received: ", message);
});

const isMain = process.argv[1] && process.argv[1].endsWith("events.js");
if (isMain) {
setInterval(() => {
const currentTime = new Date().toString();
emitter.emit("time", currentTime);
}, 5000);
}

export default emitter;
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import http from "http";

const htmlString = `
<!DOCTYPE html>
<html>
<body>
<h1>Clock</h1>
<button id="getTimeBtn">Get the Time</button>
<p id="time"></p>
<script>
document.getElementById('getTimeBtn').addEventListener('click', async () => {
const res = await fetch('/time');
const timeObj = await res.json();
console.log(timeObj);
const timeP = document.getElementById('time');
timeP.textContent = timeObj.time;
});
</script>
</body>
</html>
`;

const server = http.createServer({ keepAliveTimeout: 60000 }, (req, res) => {
if (
req.method === "POST" &&
req.url === "/" &&
req.headers["content-type"] === "application/json"
) {
let body = "";
req.on("data", (chunk) => (body += chunk));
req.on("end", () => {
const parsedBody = JSON.parse(body);
res.writeHead(200, { "Content-Type": "application/json" });
res.end(
JSON.stringify({
weReceived: parsedBody,
}),
);
});
} else if (req.method != "GET") {
res.writeHead(404, { "Content-Type": "application/json" });
res.end(
JSON.stringify({
message: "That route is not available.",
}),
);
} else if (req.url === "/secret") {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(
JSON.stringify({
message: "The secret word is 'Swordfish'.",
}),
);
} else if (req.url === "/time") {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(
JSON.stringify({
time: new Date().toString(),
}),
);
} else if (req.url === "/timePage") {
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
res.end(htmlString);
} else {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(
JSON.stringify({
pathEntered: req.url,
}),
);
}
});

server.listen(8000);
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { StatusCodes } from "http-status-codes";

const errorHandlerMiddleware = (err, req, res, next) => {
console.error(
"Internal server error: ",
err.constructor.name,
JSON.stringify(err, ["name", "message", "stack"]),
);

if (!res.headersSent) {
return res
.status(StatusCodes.INTERNAL_SERVER_ERROR)
.send("An internal server error occurred.");
}
};

export default errorHandlerMiddleware;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { StatusCodes } from "http-status-codes";

const notFoundMiddleware = (req, res) => {
return res
.status(StatusCodes.NOT_FOUND)
.send(`You can't do a ${req.method} for ${req.url}`);
};

export default notFoundMiddleware;