Skip to content
Merged
20 changes: 3 additions & 17 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const express = require("express");
const path = require("path");
const cookieParser = require("cookie-parser");
const logger = require("morgan");
const RateLimit = require("express-rate-limit");

const indexRouter = require("./routes/index");
const usersRouter = require("./routes/users");
Expand All @@ -14,28 +15,13 @@ const helmet = require("helmet");
const app = express();

// Set up rate limiter: maximum of twenty requests per minute
const RateLimit = require("express-rate-limit");
const limiter = RateLimit({
windowMs: 1 * 10 * 1000, // 10 seconds
max: 10,
windowMs: 1 * 60 * 1000, // 10 seconds
max: 60,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the tests can hammer out 50+ route tests very quickly.

});
// Apply rate limiter to all requests
app.use(limiter);

// Set up mongoose connection
const mongoose = require("mongoose");

mongoose.set("strictQuery", false);

const dev_db_url =
"mongodb+srv://cooluser:coolpassword@cluster0.cojoign.mongodb.net/local_library?retryWrites=true&w=majority&appName=Cluster0";
const mongoDB = process.env.MONGODB_URI || dev_db_url;

main().catch((err) => console.log(err));
async function main() {
await mongoose.connect(mongoDB);
}

// view engine setup
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "pug");
Expand Down
94 changes: 55 additions & 39 deletions bin/www
Original file line number Diff line number Diff line change
Expand Up @@ -4,72 +4,70 @@
* Module dependencies.
*/

var app = require('../app');
var debug = require('debug')('express-locallibrary-tutorial:server');
var http = require('http');
var app = require("../app");
var debug = require("debug")("express-locallibrary-tutorial:server");
var http = require("http");

/**
* Get port from environment and store in Express.
*/

var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
let port = normalizePort(process.env.PORT || "3000");
app.set("port", port);

/**
* Create HTTP server.
* Set up mongoose connection
*/
const mongoose = require("mongoose");
mongoose.set("strictQuery", false);
const dev_db_url =
"mongodb+srv://cooluser:coolpassword@cluster0.cojoign.mongodb.net/local_library?retryWrites=true&w=majority&appName=Cluster0";
const mongoDB = process.env.MONGODB_URI || dev_db_url;

try {
connectMongoose();
} catch (err) {
console.error("Failed to connect to MongoDB:", err);
process.exit(1);
}

var server = http.createServer(app);
async function connectMongoose() {
await mongoose.connect(mongoDB);
}

/**
* Listen on provided port, on all network interfaces.
* Create HTTP server.
*/

server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
var server = http.createServer(app);

/**
* Normalize a port into a number, string, or false.
* Listen on provided port, on all network interfaces.
*/

function normalizePort(val) {
var port = parseInt(val, 10);

if (isNaN(port)) {
// named pipe
return val;
}

if (port >= 0) {
// port number
return port;
}

return false;
}
server.listen(port);
server.on("error", onError);
server.on("listening", onListening);

/**
* Event listener for HTTP server "error" event.
*/

function onError(error) {
if (error.syscall !== 'listen') {
if (error.syscall !== "listen") {
throw error;
}

var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
var bind = typeof port === "string" ? "Pipe " + port : "Port " + port;

// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
case "EACCES":
console.error(bind + " requires elevated privileges");
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
case "EADDRINUSE":
console.error(bind + " is already in use");
process.exit(1);
break;
default:
Expand All @@ -83,8 +81,26 @@ function onError(error) {

function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
var bind = typeof addr === "string" ? "pipe " + addr : "port " + addr.port;
debug("Listening on " + bind);
}

/**
* Normalize a port into a number, string, or false.
*/

function normalizePort(val) {
var port = parseInt(val, 10);

if (isNaN(port)) {
// named pipe
return val;
}

if (port >= 0) {
// port number
return port;
}

return false;
}
29 changes: 14 additions & 15 deletions controllers/authorController.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,18 @@ const Author = require("../models/author");
const Book = require("../models/book");

const { body, validationResult } = require("express-validator");
const asyncHandler = require("express-async-handler");

// Display list of all Authors.
exports.author_list = asyncHandler(async (req, res, next) => {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are the only substantial change - Express 5 does this automatically for you.

exports.author_list = async (req, res, next) => {
const allAuthors = await Author.find().sort({ family_name: 1 }).exec();
res.render("author_list", {
title: "Author List",
author_list: allAuthors,
});
});
};

// Display detail page for a specific Author.
exports.author_detail = asyncHandler(async (req, res, next) => {
exports.author_detail = async (req, res, next) => {
// Get details of author and all their books (in parallel)
const [author, allBooksByAuthor] = await Promise.all([
Author.findById(req.params.id).exec(),
Expand All @@ -33,7 +32,7 @@ exports.author_detail = asyncHandler(async (req, res, next) => {
author,
author_books: allBooksByAuthor,
});
});
};

// Display Author create form on GET.
exports.author_create_get = (req, res, next) => {
Expand Down Expand Up @@ -67,7 +66,7 @@ exports.author_create_post = [
.toDate(),

// Process request after validation and sanitization.
asyncHandler(async (req, res, next) => {
async (req, res, next) => {
// Extract the validation errors from a request.
const errors = validationResult(req);

Expand All @@ -93,11 +92,11 @@ exports.author_create_post = [
await author.save();
// Redirect to new author record.
res.redirect(author.url);
}),
},
];

// Display Author delete form on GET.
exports.author_delete_get = asyncHandler(async (req, res, next) => {
exports.author_delete_get = async (req, res, next) => {
// Get details of author and all their books (in parallel)
const [author, allBooksByAuthor] = await Promise.all([
Author.findById(req.params.id).exec(),
Expand All @@ -114,10 +113,10 @@ exports.author_delete_get = asyncHandler(async (req, res, next) => {
author,
author_books: allBooksByAuthor,
});
});
};

// Handle Author delete on POST.
exports.author_delete_post = asyncHandler(async (req, res, next) => {
exports.author_delete_post = async (req, res, next) => {
// Get details of author and all their books (in parallel)
const [author, allBooksByAuthor] = await Promise.all([
Author.findById(req.params.id).exec(),
Expand All @@ -137,10 +136,10 @@ exports.author_delete_post = asyncHandler(async (req, res, next) => {
// Author has no books. Delete object and redirect to the list of authors.
await Author.findByIdAndDelete(req.body.authorid);
res.redirect("/catalog/authors");
});
};

// Display Author update form on GET.
exports.author_update_get = asyncHandler(async (req, res, next) => {
exports.author_update_get = async (req, res, next) => {
const author = await Author.findById(req.params.id).exec();
if (author === null) {
// No results.
Expand All @@ -150,7 +149,7 @@ exports.author_update_get = asyncHandler(async (req, res, next) => {
}

res.render("author_form", { title: "Update Author", author });
});
};

// Handle Author update on POST.
exports.author_update_post = [
Expand Down Expand Up @@ -179,7 +178,7 @@ exports.author_update_post = [
.toDate(),

// Process request after validation and sanitization.
asyncHandler(async (req, res, next) => {
async (req, res, next) => {
// Extract the validation errors from a request.
const errors = validationResult(req);

Expand All @@ -205,5 +204,5 @@ exports.author_update_post = [
// Data from form is valid. Update the record.
await Author.findByIdAndUpdate(req.params.id, author);
res.redirect(author.url);
}),
},
];
Loading