Express Basic Features

Let’s start with a simple example that gives you an overview of what Express needs to do.

const express = require('express') const app = express() const port = 3000 app.get('/', (req, res) => { res.send('Hello World! ') }) app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`) })Copy the code

Express provides an entry method, Express, that returns an instance that provides a listener for HTTP requests on the corresponding port, as well as routing listener methods like GET

Infrastructure implementation

Function createApplication(): any {// app = function (req: Request, res) {}; // @ts-ignore app.listen = function () { let server = http.createServer(app); // arguments (3000, 'localhost', function () {}) server.listen(... arguments); return server; }; return app; } const app = createApplication(); app.listen(3000, () => { console.log("listen 3000"); });Copy the code

The server is created using nodeJs’s native createServer method, which is exposed through listen.

Route listening method

The framework needs to provide the corresponding route listening METHODS of all HTTP request METHODS, which can be obtained through METHODS of HTTP module, traversed after obtaining, and then stored the corresponding route listening callback METHODS in the route array.

  app.routes = [];
  http.METHODS.forEach((method) => {
    method = method.toLocaleLowerCase();
    app[method] = function (path: string, handler) {
      app.routes.push({
        path,
        method,
        handler,
      });
    };
  });
Copy the code

The route listens for the callback function to execute

Finally, you can put the task of executing the route callback function in the app method, which is executed every time there is an HTTP request.

let app: App = function (req, res) { let method = req.method.toLocaleLowerCase(); let { pathname } = url.parse(req.url, true); app.routes.forEach((route) => { if (route.method === method && route.path === pathname) { route.handler(req, res); }}); };Copy the code

At present, the basic functions have been realized, and the complete code is as follows:

import * as http from "http"; import * as url from "url"; import { App } from "./config"; function createApplication(): App { // @ts-ignore let app: App = function (req, res) { let method = req.method.toLocaleLowerCase(); let { pathname } = url.parse(req.url, true); app.routes.forEach((route) => { if (route.method === method && route.path === pathname) { route.handler(req, res); }}); }; app.routes = []; app.listen = function () { // @ts-ignore let server = http.createServer(app); // arguments (3000, 'localhost', function () {}) server.listen(... arguments); return server; }; http.METHODS.forEach((method) => { method = method.toLocaleLowerCase(); app[method] = function (path: string, handler) { app.routes.push({ path, method, handler, }); }; }); return app; } const app = createApplication(); app.listen(3000, (req,res) => { console.log("listen 3000"); }); app.get("/gettest", (req, res) => { res.end('hello get test') });Copy the code

Middleware features

Implementing middleware functionality is actually quite simple, and middleware can be thought of as a special route listening event. Middleware is registered with the use method:

  app.use = function (path, handler) {
    app.routes.push({
      path,
      method: MIDDLE_WARE_METHOD,
      handler,
    });
  };
Copy the code

Middleware judgment is then added to the APP method

 const MIDDLE_WARE_METHOD = "middleware";

  let app: App = function (req, res) {
    let httpMethod = req.method.toLocaleLowerCase();
    let { pathname } = url.parse(req.url, true);
    let index = 0;
    function next() {
      if (index === app.routes.length) {
        return;
      }

      let { method, path, handler } = app.routes[index++];
      if (method === MIDDLE_WARE_METHOD) {
        if (path === pathname) {
          handler(req, res, next);
        } else {
          next();
        }
      } else {
        if (method === httpMethod && pathname === path) {
          handler(req, res);
        } else {
          next();
        }
      }
    }
    next();
  };
Copy the code

Add next method in APP method and judge whether it is middleware route monitor

The complete code

import * as http from "http"; import * as url from "url"; import { IncomingMessage, ServerResponse } from "http"; import { App } from "./interface"; const MIDDLE_WARE_METHOD = "middleware"; function createApplication(): App { let app = <App>function (req: IncomingMessage, res: ServerResponse) { let httpMethod = req.method.toLocaleLowerCase(); let { pathname } = url.parse(req.url, true); let index = 0; function next() { if (index === app.routes.length) { return; } let { method, path, handler } = app.routes[index++]; if (method === MIDDLE_WARE_METHOD) { if (path === pathname) { handler(req, res, next); } else { next(); } } else { if (method === httpMethod && pathname === path) { handler(req, res); } else { next(); } } } next(); }; app.use = function (path, handler) { app.routes.push({ path, method: MIDDLE_WARE_METHOD, handler, }); }; app.routes = []; app.listen = function (... arg) { let server = http.createServer(app); // arguments (3000, 'localhost', function () {}) server.listen(... arg); return server; }; http.METHODS.forEach((method) => { method = method.toLocaleLowerCase(); app[method] = function (path: string, handler) { app.routes.push({ path, method, handler, }); }; }); return app; } const app = createApplication(); app.listen(3000, () => { console.log("listen 3000"); }); app.get("/gettest", (req, res) => { res.end("hello get test"); }); app.use("/test", (req, res, next) => { next(); });Copy the code

conclusion

This is just a simple mock, and there are still many functions that are not perfect. You can read them selectively, and I will gradually improve them later.