πŸ“Ÿ Express.js πŸ“Ÿ

Express can be used to create websites or APIs.

$ cd xxx # go to your project folder
$ npx --yes --package express-generator express --force --no-view
$ npm install
$ npm audit fix --force

➑️ Don't forget to add a .gitignore, and maybe a linter too.

Understand your generated project

  • ✨ Your server file is created inside /bin/www. You will most likely never have to edit this file.
  • 🍹 It will load the application "routes" from /app.js. You will add "routes" and "middlewares" here.
  • πŸ”₯ The associated routes files are stored inside /routes.
  • πŸ’ Your publicly URL accessible files are stored inside /public.

If you are not familiar with routes, HTTP methods/response codes... Then you should learn that first. Refer to the HTTP protocol.


Middlewares

In app.js you should see a lot of app.use(xxx). These are called middleware. A middleware is a function that will prepare the request (req) or the response (res) for usage in routes later.

app.use(function (req, res, next) {
    // ... do something ...
    next()
});

➑️ It's useful to know if there is some code you want to execute for every or only some requests.

  • ✨ Example: cookie parser

For instance, app.use(cookieParser()) is a middleware that will parse cookies in the request, and store them in req.cookies.

  • ✨ Example: adding headers
CORS headers

See also Express.js/cors middleware.

const cors = require('cors');
app.use(
    cors({
        origin: 'http://localhost', // ex: allow localhost
        methods: ["GET", "POST", "PATCH", "PUT", "OPTIONS", "HEAD"],
        allowedHeaders: ['X-Requested-With', 'content-type']
    })
);

Allowing browsers to fetch cookies

methods: [...],
+ credentials: true,

If you want to use origin: '*' (any) with credentials

- origin: '*',
+ origin: [ /.*/ ],
...
credentials: true,

Allowing multiple origins (you can use regexes...)

- origin: 'URL',
+ origin: ['http://localhost', 'http://127.0.0.1' ],
Custom headers
app.use(function (req, res, next) {
    res.setHeader('Access-Control-Expose-Headers', 'Custom-header');
    res.setHeader('Custom-header', 'value');
    next()
});

Routers

In app.js, you will also define routes. To make things cleaner, we are moving routes to "local" routers in ./routes. In app.js, we are importing (require) local routers, and associating them with an API endpoint.

const usersRouter = require('./routes/users');
app.use('/users', usersRouter);

In the scenario above, any requests to the endpoint /users will be handled by usersRouter.

⚠️It's important to note that inside a "local" router, routes will be declared relatively to this endpoint. For instance, / would be /users/.

Routing should be done AFTER every calling every middleware.

A "local" router is something like this.

// ./routes/users
const express = require('express');
const router = express.Router();

// router.get => GET
// / => /users/
// req => the request
// res => the response
router.get('/', (req, res) => {
    // ... code ...
    // send a response
});
// add more routes

module.exports = router;

Routing

You can use every HTTP method

router.get('/', (req, res) => {});
router.post('/', (req, res) => {});
router.put('/', (req, res) => {});
router.patch('/', (req, res) => {});
router.delete('/', (req, res) => {});

You can also declare "dynamic" routes. For instance, a route /:id will take any value after the / and store it inside id.

router.delete('/:id', (req, res) => {
    const id = req.params.id
    // ...
})
// extracting params
router.delete('/:x1/:x2', (req, res) => {
  const {x1, x2} = req.params;
  // or use req.params.x1 / req.params.x2
})

You can use regexes inside your dynamic routes! See Route Paths.

Useful methods on req.

// get headers
req.get('header-name')
req.headers['header-name']

// get GET/POST params
req.query.key // GET param named "key"
req.body.key // POST param named "key"

Useful methods on res.

// send something to the requester
res.send(something); // HTML, JSON, XML...
res.status(404).send(something); // ex: 404 HTTP code
res.render('index', { title: 'Title' }); // public/index.html

// redirect
res.redirect('URL');

Express handle login

You may want to use cookies to store some data, such as the logged user. We use a special cookie called session for this purpose. A session is a file on the server in which we can store data.

The client will store and return us in every request the session-id, which will allow us to load the matching session data.

See GitHub or session.

$ npm i express-session
const session = require('express-session');
/* ... */
app.use(session({
    resave: false,
    saveUninitialized: false,
    secret: 'something-random-and-secret'
}));
  • Create a session
await req.session.regenerate(() => {}); // generate session
  • Store data inside the session
req.session.key = 'value'; // store a value
  • Read data inside the session
const value = req.session.key
  • Delete a session
await req.session.destroy(() => {}) // destroy session

πŸ‘» To-do πŸ‘»

Stuff that I found, but never read/used yet.