Basic use of express, using postman to simulate back-end routing

Introduction

Node.js enables JavaScript\TypeScript scripts to run on the server (backend) without the browser environment (actually encapsulating the Chrome V8 engine), providing an option for us to develop the backend. Unlike the front-end, which has a unified browser standard, if you don't follow it, the browser will not be able to display properly; the development of the back-end is relatively free, and there are many options for development languages, such as Java, PHP, python, C, Go, etc. Our technology The Xie website uses the TypeScript language, and knowledge about TypeScript has been introduced in previous courses.

If you want to build a simple backend yourself, in theory you can receive and send http requests by simply calling a library such as http-server. Although these libraries have helped us deal with many low-level problems, it is still quite troublesome to implement more complex functions. Express is an open source framework based on Node.js, which encapsulates receiving and sending http requests at a higher level and more user-friendly. The official website calls it "fast, open, and minimalist", which shows that while Express ensures performance, it is very easy to write code and is open source. It enables the creation of powerful APIs quickly and easily using a variety of http utilities and middleware of the developer's choice.

Configuration Environment

Install express

Use yarn to install, as follows

yarn init#取号名字,一路默认
yarn add express

Preparation

In the working directory where Express is installed just created, we create a new folder src to save the source code, and create a new entry file app.ts in it. Then import the Express package and create an instance of the Express class in it:

import express from "express"; // 导入Express包
const app = express(); // 创建Express类的实例

The Express package imported in this way is written in JavaScript and lacks the type declaration file required by TypeScript syntax, so a reminder will appear on the import line. We can install type declarations using the following command:

yarn add @types/express --dev

After the installation is complete, we see that the reminder has been dismissed.

Then we let the program listen to port 3000, so that requests sent to http://localhost:3000 can be captured by us.

const port = 3000
app.listen(port, () => {
    
    
    // 开始监听
    console.log(`listening on port ${
      
      port}`);
});

The question is, how can we run the backend? We can use babel

First install the tools

yarn add @babel/core @babel/cli @babel/preset-env @babel/preset-typescript @babel/node nodemon --dev

Second, we configure Babel. Create a new babel.config.json file in the working directory and write it (remove comments):

{
    
    
  "presets": [
    // 指定要使用的工具集。更多配置详见官方文档:https://www.babeljs.cn/docs/
    "@babel/preset-env",
    "@babel/preset-typescript"
  ]
}

Then, we configure nodemon. Open the package.json file in the working directory and create a new field as follows (remove the comments):

"nodemonConfig": {
    
          // 更多配置详见官方文档:https://www.npmjs.com/package/nodemon
    "watch": [          // 监听的文件目录
      "src"
    ],
    "ext": "ts, json",  // 监听的文件后缀
    "exec": "babel-node --extensions \".ts\" src/app.ts"    // 当运行nodemon命令时执行
    // babel-node与node的区别在于应用了babel.config.json中配置的工具,src/app.ts是你的入口文件
  }

Finally, we set up yarn's execution script to simply run the programs in node_modules. Create a new field in the package.json file as follows (remove comments):

"scripts": {
    
    
    "start": "nodemon"  // 等价于./node_modules/nodemon/bin/nodemon.js
  }

In this way, as long as we enter yarn start in the terminal, we will see that nodemon starts and uses Babel to generate and run JavaScript code. At this time, entering rs and pressing Enter will cause the backend to restart; pressing Ctrl+C will cause the backend to stop.

Postman

Install

Postman is an API debugging tool that can simulate the front-end sending requests to the back-end, which is very useful when we develop the back-end. You can go to its official website to register an account (the advantage is that your HTTP requests will be backed up and synchronized on different devices) https://www.postman.com/, and then click on the download desktop app related options or directly link to https://www .postman.com/downloads/, download the installer and install it.

After opening Postman and logging in, you can click the plus sign in Collections to create a new Collection, and then click the plus sign in the upper bar to create a new Request and save it to this Collection. This way you can edit, save and send the Request. Requests for the same type of API can be saved under the same Collection to facilitate management. It is recommended that you read the official Postman documentation (https://learning.postman.com/docs/getting-started/introduction/) to learn more practical knowledge about Postman.

use

Create a new request and fill in the local ip:port

http://localhost:3000/

Then you can send a get request and get an error, because we have not yet routed to process this request. The specific usage of routing will be introduced later.

HTTP

Basic structure of HTTP request

To understand how Express is routed, it is necessary to first understand the format and structure of HTTP requests. HTTP (Hypertext Transfer Protocol) is based on the TCP/IP protocol to transfer data and is designed for communication between clients and servers. The format of the client request is as follows:

Client request format

The format of the server response is as follows:

Server response format

Express routes based on the HTTP request method and URI/URL. The API written by the developer processes the request and sends the status code and other response content back to the client. Let’s first understand the HTTP request method:

serial number method describe
1 GET Make a request to the specified resource to obtain the resource, and the data is included in the URL
2 HEAD It is equivalent to sending a GET request to the server, but does not obtain the response body, only the response header.
3 POST Submit data to the specified resource to process the request (such as submitting a form or uploading a file), and the data is included in the request body
4 PUT Upload its latest content to the designated resource
5 DELETE Request the server to delete the resource identified by Request-URL
6 CONNECT The HTTP/1.1 protocol is reserved for proxy servers that can change connections to pipes.
7 OPTIONS Returns the server's support for a specific resource, allowing clients to view the server's performance
8 TRACE Echo requests received by the server, mainly used for testing or diagnostics
9 PATCH It is a supplement to the PUT method and is used to locally update known resources.

Generally, we commonly use GET, POST and PUT requests. Next, let’s take a look at the HTTP response status codes. The following table lists some status codes and descriptions that may be encountered:

status code English description Chinese description
200 OK Request successful
400 Bad Request The syntax of the client request is incorrect and the server cannot understand it.
401 Unauthorized The identity authentication requested by the client is missing or incorrect, and the authentication fails.
403 Forbidden The server understands the client's request, but refuses to execute it
404 Not Found The server cannot find the resource (webpage) based on the client's request
500 Internal Server Error Internal server error, unable to complete the request
501 Not Implemented The server does not support the requested feature and cannot complete the request
502 Bad Gateway A server working as a gateway or proxy received an invalid response from the remote server while trying to perform a request.

HTTP URL

URL = uniform resource locator, Uniform Resource Locator, is a method of identifying addresses on the network. Specifically in the application of HTTP protocol, the form is as follows:

http://[host]:[port]/[path]?[searchpart]

Among them, <port>the default is 80 (default is 443 for HTTPS protocol), <path>is an HTTP selector, <searchpart>and is the query string. For example:

https://baike.baidu.com/item/%E7%BB%9F%E4%B8%80%E8%B5%84%E6%BA%90%E5%AE%9A%E4%BD%8D%E7%B3%BB%E7%BB%9F/5937042?fromtitle=url&fromid=110640

The protocol is https, the host address is baike.baidu.com(will be resolved into an IP address by DNS), and the default 443port is used; the path is /item/%E7%BB%9F.../5937042, with path parameters /%E7%BB%9F.../5937042; the query string is fromtitle=url&fromid=110640.

routing

Introduction

The process of parsing URLs is routing. We implement the response to front-end requests through the process of matching URLs.

Basic usage

The basic format of a route is:

app.METHOD(PATH, HANDLER);

in:

  • appIs expressan instance of class.
  • METHODIs the HTTP request method.
  • PATHis the path on the server.
  • HANDLERIs a function executed when a route is matched.

Note that the number of parameters here is not fixed. There will be 3 parameters and 4 parameters in the subsequent usage.

For example:

// “/”路径接收到的GET方法匹配至该路由
app.get("/", (req, res) => {
    
    
  res.status(200).send("GET request");
});

// “/”路径接收到的POST方法匹配至该路由
app.post("/", (req, res) => {
    
    
  res.status(200).send("POST request");
});

// “/”路径接收到的所有方法匹配至该路由
app.all("/", (req, res) => {
    
    
  res.status(200).send("Any request");
});

For the Handler function, Express will call it when the route matches. There are three parameters passed in when calling (generally named req, res, next):

  • The req object represents "request", and commonly used attributes are body (requested package body), query (requested query string) and params (requested path parameters);
  • The res object represents "response", and the commonly used methods are status (setting the response status code) and send (setting the response content);
  • When the next function is called, it means handing over to the next middleware for processing.

match path

Matching paths can be ordinary strings, string templates, and regular expressions.

Ordinary strings such as:

app.get("/", (req, res) => {
    
    
  // 可匹配“/”
  res.send("root");
});
app.get("/about", (req, res) => {
    
    
  // 可匹配“/about”
  res.send("about");
});
app.get("/random.text", (req, res) => {
    
    
  // 可匹配“/random.text”
  res.send("random.text");
});

String template such as:

app.get("/ab?cd", (req, res) => {
    
    
  // 可匹配“acd”或“abcd”
  res.send("ab?cd");
});
app.get("/ab+cd", (req, res) => {
    
    
  // 可匹配“abcd”,“abbcd”,“abbbcd”等
  res.send("ab+cd");
});
app.get("/ab*cd", (req, res) => {
    
    
  // 可匹配“abcd”,“abxcd”,“abRANDOMcd”,“ab123cd”等
  res.send("ab*cd");
});
app.get("/ab(cd)?e", (req, res) => {
    
    
  // 可匹配“abe”或“abcde”
  res.send("ab(cd)?e");
});

Regular expressions such as:

app.get(/a/, (req, res) => {
    
    
  // 可匹配任何带有‘a’的路径
  res.send("/a/");
});
app.get(/.*fly$/, (req, res) => {
    
    
  // 可匹配“butterfly”,“dragonfly”
  res.send("/.*fly$/"); // 但不可匹配“butterflyman”,“dragonflyman”
}); // 相当于匹配以“fly”结尾的所有路径

query string

The parameter in the path (route parameter) refers to the method of passing parameters directly as part of the URL path, which is our previous path

The query string is the part of the URL that is separated by ? after the path. Although both of them pass parameters in the URL, their usage is different.

Still taking the example of the above URL: https://baike.baidu.com/item/%E7%BB%9F%E4%B8%80%E8%B5%84%E6%BA%90%E5%AE%9A% E4%BD%8D%E7%B3%BB%E7%BB%9F/5937042?fromtitle=url&fromid=110640. It can be resolved through the following routes:

app.get("/item/:param1/:param2", (req, res) => {
    
    
  console.log(req.params.param1); // 统一资源定位系统,中间那段%unicode编码的翻译
  console.log(req.params.param2); // 5937042
  console.log(req.query.fromtitle); // url
  console.log(req.query.fromid); // 110640
  res.status(200).send("ok");
});

-In addition, there are some advanced usages, such as inserting dashes ( ) and points ( ) in the path ., and even introducing regular expressions in the path:

// Request URL: http://localhost:3000/flights/LAX-SFO
app.get("/flights/:from-:to", (req, res) => {
    
    
  console.log(req.params.from); // LAX
  console.log(req.params.to); // SFO
  res.status(200).send("ok");
});

// Request URL: http://localhost:3000/date/2020.2.1
app.get("/date/:year.:month.:day", (req, res) => {
    
    
  console.log(req.params.year); // 2020
  console.log(req.params.month); // 2
  console.log(req.params.day); // 1
  res.status(200).send("ok");
});

Route processing function

Express's route handler functions are very flexible and can be passed multiple functions, arrays of functions, or a mixture of the two. When it is necessary to transition from the previous processing function to the next processing function, the passed in next function needs to be called.

var cb0 = function (req, res, next) {
    
    
  console.log("CB0");
  next();
};

var cb1 = function (req, res, next) {
    
    
  console.log("CB1");
  next();
};

app.get(
  "/example/d",
  [cb0, cb1],
  function (req, res, next) {
    
    
    console.log("the response will be sent by the next function ...");
    next();
  },
  (req, res) => {
    
    
    res.send("Hello from D!");
  }
);

Router

The express.Router class can be used to build modular routing processing functions (middleware)

We create a new route1.ts file under the src folder and write:

import express from "express";
const router = express.Router(); // 实例化express.Router类

router.get("/", (req, res) => {
    
    
  res.status(200).send("ok!");
});

export default router; // 导出后,这个Router就成为了一个中间件

Then modify the app.ts class:

import express from "express";
import route1 from "./route1"; // 导入route1中间件

const app = express();
const port = 3000;

app.use("/route1", route1); // 在route1路径下使用route1中间件

app.listen(port, () => {
    
    
  console.log(`Example app listening on port ${
      
      port}`);
});

middleware

Middleware is a modular route processing function. We have just seen the use of route-level middleware (create middleware through express.Router, and then import middleware through app.use). In addition, in a broad sense, all routing processing just mentioned Functions can also be regarded as the most common middleware. There are also the following considerations when creating and using middleware:

The middleware loaded with app.use will be called regardless of the HTTP request method. If you want to limit an HTTP request method, you need to use app.METHOD. At the same time, if no path parameter is given, the middleware will be called by default for requests with any path.

Middleware is loaded and executed in order. If a matching route has already appeared before, then even if the subsequent route matches, the corresponding middleware will not be called. The next function will transfer control to the next processing function of the current route by default. If you want to transfer control to the next route, you need to call next('route'). If non-"route" parameters are passed to the next function, Express will think that the middleware has an error and directly execute the exception handling function, bypassing other normal handling functions.

app.get(
  "/user/:id",
  (req, res, next) => {
    
    
    // if the user ID is 0, skip to the next route
    if (req.params.id === "0") next("route");
    // otherwise pass the control to the next middleware function in this stack
    else next();
  },
  (req, res, next) => {
    
    
    // send a regular response
    res.send("regular");
  }
);

// handler for the /user/:id path, which sends a special response
app.get("/user/:id", (req, res, next) => {
    
    
  res.send("special");
});

Exception handling

For synchronous programming middleware, when an exception is thrown and there is no self-built exception handling function, Express will handle the exception by itself. Express will set status codes, error messages, etc. based on the error err.status(or ). err.statusCodeWe can also create an exception handling function ourselves. If four parameters are passed to the Express middleware, usually named (err, req, res, next), Express will treat this middleware as an exception handling function.

app.get("/", (req, res) => {
    
    
  throw new Error("error occurs!"); // 异常由Express自建异常处理函数来处理
});
app.use((err, req, res, next) => {
    
    
  res.status(500).send("error occurs!"); // 或者可以自己编写异常处理函数
});

For asynchronous programming middleware, to handle exceptions, you need to call the next function and pass a value to it. If the middleware returns a Promise, next(value) will be called automatically. The following asynchronous function returns Promise. If an exception or reject is thrown in the middle, Express will call the next function by default and pass in the exception information.

app.get("/user/:id", async (req, res, next) => {
    
    
  var user = await getUserById(req.params.id);
  res.send(user);
});

More often, we handle exceptions inside middleware instead of passing them to Express:

app.get("/", async (req, res) => {
    
    
    try{
    
    
    ...
    return res.status(200).send("ok");
    } catch(err) {
    
    
    ...
    return res.status(500).send("Internal Server Error");
    }
})

Commonly used middleware

Express provides some built-in middleware for users to choose from. For example, the commonly used express.json will parse the request body in json format, and express.urlencoded will parse the request body in urlencoded format. There are also some third-party middleware that can be installed through the package manager, such as cookie-parser.

Guess you like

Origin blog.csdn.net/killsime/article/details/135314896