ExpressJS 101
Published: 2023-01-28 10:52:55

npm init -y :
creates a package.json file

npm i --save-dev-nodemon:
package which re-runs the server when any changes are saved
```
  "scripts": {
    "devStart": "nodemon server.js"
  },
```


```
const express = require("express");
const app = express();
app.listen(3000);
```
the express package that has been installed will be called out as a function express()

ERROR CODES:


```
app.get("/", (req, res) => {
  console.log("HERE");
  //   res.send("HI");
  res.status(500).send("error from server 500");
});
```
The get() method takes two arguments: the first is the route or path, and the second is a callback function that is executed when a GET request is made to that route. The callback function typically takes two arguments: a request object and a response object, which are used to handle the incoming request and send a response back to the client.


```
  res.json({
    a: "HI",
    image: {
      b: "hello",
    },
  });
```

To send files to be downloaded from the server
```
res.download("server.js");
```

To render html component:
```
  res.render("index");
```
this just gives an error
```
Error: No default engine was specified and no extension was provided.
    at new View (/home/abhinav-pandey/Github/LearnExpress/node_modules/express/lib/view.js:61:11)
    at Function.render (/home/abhinav-pandey/Github/LearnExpress/node_modules/express/lib/application.js:587:12)
    at ServerResponse.render (/home/abhinav-pandey/Github/LearnExpress/node_modules/express/lib/response.js:1039:7)
    at /home/abhinav-pandey/Github/LearnExpress/server.js:17:7
    at Layer.handle [as handle_request] (/home/abhinav-pandey/Github/LearnExpress/node_modules/express/lib/router/layer.js:95:5)
    at next (/home/abhinav-pandey/Github/LearnExpress/node_modules/express/lib/router/route.js:144:13)
    at Route.dispatch (/home/abhinav-pandey/Github/LearnExpress/node_modules/express/lib/router/route.js:114:3)
    at Layer.handle [as handle_request] (/home/abhinav-pandey/Github/LearnExpress/node_modules/express/lib/router/layer.js:95:5)
    at /home/abhinav-pandey/Github/LearnExpress/node_modules/express/lib/router/index.js:284:15
    at Function.process_params (/home/abhinav-pandey/Github/LearnExpress/node_modules/express/lib/router/index.js:346:12)
```

Solution:
Setup view engine:
pug OR ejs
```
app.set("view engine", "ejs");
app.get("/", (req, res) => {
  res.render("index");
});
```
index.html should be named to index.ejs

```
    <h1>2+2=<%= 2+2 %></h1>
```
it will run on the server and return back the value between the tag

```
res.render("index", { text: "page" });
<p>HELLO IM IN INDEX <%=text%></p>
```

```
res.render("index", { text123: "page" });
<p>HELLO IM IN INDEX <%=locals.text || 'PAGES'%></p>
```

locals is always going to passed from the viewengine.
so even if text prop is not passed we can use an alternative.

Custom routes in express:

We can create custom files like routes/users.js
```
const express = require("express");
const router = express.Router();
router.get("/", (req, res) => {
  res.send("Users List");
});
router.get("/new", (req, res) => {
  res.send("New User Form");
});
module.exports = router;
```

Connect so that all the routes in the file will be a child of the parent route like /users

so it will be
/users/ 
/users/new
```
const userRouter = require("./routes/users");
app.use("/users", userRouter);
```

.route():
Instead of doing this:
```
router.get("/:id", (req, res) => {
  // req.params.id;
  res.send(`Get User with ID ${req.params.id}`);
});
router.put("/:id", (req, res) => {
  // req.params.id;
  res.send(`Get User with ID ${req.params.id}`);
});
router.delete("/:id", (req, res) => {
  // req.params.id;
  res.send(`Get User with ID ${req.params.id}`);
});
```

we can :
BETTER
```
router
  .route("/:id")
  .get((req, res) => {
    res.send(`Get User with ID ${req.params.id}`);
  })
  .put((req, res) => {
    res.send(`Get User with ID ${req.params.id}`);
  })
  .delete((req, res) => {
    res.send(`Get User with ID ${req.params.id}`);
  });
```

MIDDLEWARE:

Middleware in Express is a function that runs between the request and the response in the processing of an HTTP request. Middleware functions can perform various tasks such as logging, authentication, validation, and more. Express uses a series of middleware functions that are executed in the order that they are defined. Each middleware function can perform some logic, and then pass control to the next middleware function using the next() function. Middleware functions can also end the request/response cycle by sending a response to the client or redirecting to another route.

```
function logger(req, res, next) {
  console.log(req.originalUrl);
  next();
}
```

```
app.use(logger);
```
We have to use this above the get request functions if we want to run this on those urls /.

We can also run middleware to just a particular url like:
```
app.get("/", logger, (req, res) => {
  res.render("index", { text123: "page" });
});
```

.param():
```
router.param("id", (req, res, next, id) => {
  console.log(id);
  next();
});
```
if we dont use next() it will keep running forever.
.param() is running before request and response so if there is no next it wont be able to further proceed

Running static files from public:
```
app.use(express.static("public"));
```
Instead of putting a get request of ./ we can use this to create a path to connect the index file or even render other files through that same request.


We can navigate to http://localhost:3000/test/tt.html
to render this as well.

express.urlencoded({extended: true}):
Suppose we have a new.ejs:
```
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <form action="/users" method="POST">
      <input type="text" name="fname" />
      <button type="submit">Submit</button>
    </form>
  </body>
</html>
```

By default express doesnt allow us to access the body we need to use another middleware for that.

```
app.use(express.urlencoded({ extended: true }));
```

```
router.get("/new", (req, res) => {
  res.render("./users/new");
});

router.post("/", (req, res) => {
  console.log(req.body.fname);
  res.send("Create User");
});
```

req.body is coming from the form
it is an object whose parameters are the name properties of the input fileds inside that form.

res.redirect():
```
const users = [{ name: "Abhinav" }, { name: "Juan" }];
```

```
router.post("/", (req, res) => {
  const isValid = true;
  if (isValid) {
    users.push({ name: req.body.fname });
    res.redirect(`users/${users.length - 1}`);
  } else {
    console.log("ERROR");
    res.redirect("users/new");
  }
  console.log(req.body);
  res.send("Create User");
});
```

We can also get the query parameters directly coming to request:
```
console.log(req.query.name);
```
http://localhost:3000/users?name=Kyle

How to send json file to a get request from express:

```
app.get("/a", async (req, res) => {
  try {
    const data = await fs.promises.readFile(
      "./public/assets/users.json",
      "utf8"
    );
    res.json(JSON.parse(data));
  } catch (err) {
    console.log(err);
  }
});
```

fs in JS:
```
const fs = require("fs");
```


CORS ERROR IN EXPRESS:
allows any origin to post into the express server

```
const cors = require("cors");
app.use(function (req, res, next) {
  res.header("Access-Control-Allow-Headers", "content-type");
  next();
});
```

(IMPORTANT)
BODY-PARSER:
the response body will come empty if we don't use this.
we need to add a middleware for parsing the request body that is not being used. To fix this, you need to add a middleware function, such as "body-parser", to parse the request body and make it available on the req. body object.

```
const bodyParser = require("body-parser");
app.use(bodyParser.json());
```