express
brief introduction
Express is based on node JS platform, a fast, open and minimalist web development framework. Build web server
The essence of Express: it is a third-party package on npm, which provides a convenient way to quickly create a Web server.
Using the Express development framework, you can easily and quickly create a Web site server or an API interface server
Official website: https://www.expressjs.com.cn/
Simple use
Download and install:
npm init -y npm i express -S
Use steps:
- Import package
- Create server
- Processing requests
- Listening port
const express = require('express') const app = express() app.get(route,Callback) // get is the request method app.listen(Port number)
Routing method
The request method also supports:
get - query request - condition in address bar
post - add request - data in the request body
put - modify request - condition in address bar - data in request body
Delete - delete request - condition in address bar
Each verb method is used to process the corresponding request. Except for one method:
app.all() // Can be used to handle any request
Although the all method can handle any request, it should be used as little or even as little as possible.
Debugging with postman
Routing path
perfect match
// Requests that match the root path app.get('/', function (req, res) { res.send('root'); }); // Requests matching the / about path app.get('/about', function (req, res) { res.send('about'); }); // Match / random Textrequest for path app.get('/random.text', function (req, res) { res.send('random.text'); });
Incomplete match
// Match acd and abcd app.get('/ab?cd', function(req, res) { res.send('ab?cd'); }); // Match abcd, abbcd, abbbcd, etc app.get('/ab+cd', function(req, res) { res.send('ab+cd'); }); // Match abcd, abxcd, abRABDOMcd, ab123cd, etc app.get('/ab*cd', function(req, res) { res.send('ab*cd'); }); // Match / abe and / abcde app.get('/ab(cd)?e', function(req, res) { res.send('ab(cd)?e'); });
Characters?, +* And () are subsets of regular expressions, - and Interpreted at literal value in a string based path.
Regular matching:
// Match any path that contains a: app.get(/a/, function(req, res) { res.send('/a/'); }); // Matches butterfly, dragonfly, does not match butterflyman, dragonfly man, etc app.get(/.*fly$/, function(req, res) { res.send('/.*fly$/'); });
Route multiple processing
Use a callback function to handle Routing:
app.get('/example/a', function (req, res) { res.send('Hello from A!'); });
Multiple processing:
app.get('/example/b', function (req, res, next) { console.log('After this processing, it will be handed over to the next function'); next(); }, function (req, res) { res.send('Hello from B!'); });
Process routes using an array of callback functions:
var cb0 = function (req, res, next) { console.log('CB0') next() } var cb1 = function (req, res, next) { console.log('CB1') next() } var cb2 = function (req, res) { res.send('Hello from C!') } app.get('/example/c', [cb0, cb1, cb2])
Mix functions and function arrays to handle Routing:
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('response will be sent by the next function ...') next() }, function (req, res) { res.send('Hello from D!') })
Response method
res.download() // Prompt to download the file. res.end() // Terminate the response processing flow. res.json() // Send a response in JSON format. res.jsonp() // Send a response in JSON format that supports JSONP. res.redirect() // Redirect request. res.render() // Render the view template. res.send() // Send various types of responses. res.sendFile() // Send the file as an octet stream. res.sendStatus() // Set the response status code and send it as a string as part of the response body.
download example:
// Response download - res.download (downloaded source file, downloaded file name, callback function) res.download("./test.html",'b.html',err=>{ if(err){ console.log("Download failed"); }else{ console.log("Download succeeded"); } })
json example:
// Response json data to client // Res.json (data in JSON format) let obj = { name:"Zhang San", age:12, wife:"Emerald flower", children:['A da','Ah er','Xiao Ming'] } res.json(obj)
jsonp example:
// Respond to the json request initiated by the client, and the response is json data // Res.jsonp (data in JSON format) let obj = { name:"Zhang San", age:12, wife:"Emerald flower", children:['A da','Ah er','Xiao Ming'] } res.jsonp(obj)
redirect example:
// res.redirect() is used to jump the route - / a route. In fact, the route / b can handle it. In the route processing of / A, you can hand over the request to the route / b for processing res.redirect('/index') app.get('/index',(req,res)=>{ let data = fs.readFileSync('./test.html') res.end(data) })
render example:
send example:
// res.send() - used to give the client a response string - if the string is a tag, it can be parsed into html - automatically set the data type and encoding let html = ` <h2>This is a h2 label</h2> ` // res.end does not automatically set the data type or code // res.end(html) res.send(html)
sendFile example:
// res.sendFile() is used to respond to a file to the client res.sendFile(__dirname + '/test.html')
sendStatus example:
// sendStatus automatically sets the response status code and describes the corresponding response status to the client res.sendStatus(404) // Response not found res.sendStatus(200) // Response ok
Properties of the request object
req.url // Requested path - if any? Pass parameters, and this path will also contain parameters req.method // Request method req.path // Request path - if any? Pass parameters. This path does not contain parameters req.protocol // agreement req.params // Get the parameters of the get request - pass parameters for dynamic routing - restful style parameters - finally get the object, and the key of the object is the name specified by the path req.query // Get the parameters of the get request - for traditional parameter passing - use? Parameter - the object is finally obtained
Static resource hosting
Express provides a very easy-to-use method called express Static (), through this method, you can easily create a static web resource server:
app.use(express.static('public')) // app.use() means using (Middleware) // You can now access all the files in the public directory // Such as public / AA JPG file, you can: http://xxxx/images/aa.jpg
Express also supports creating a virtual file prefix for static resource files (in fact, it does not exist in the file system). You can use express The static function specifies a virtual static directory, as follows:
Meaning of prefix:
- It can confuse others and prevent others from guessing the directory structure of our server to a certain extent
- It can help us better organize and manage static resources
app.use('/static', express.static('public'))
The "/" in front of the prefix must be added, otherwise it will be wrong. [404]
Now you can use / static as the prefix to load the files in the public folder:
http://localhost:3000/static/images/kitten.jpg http://localhost:3000/static/css/style.css http://localhost:3000/static/js/app.js http://localhost:3000/static/images/bg.png http://localhost:3000/static/hello.html
Use app The use () method is usually written before the specific route listening.
Each application can have multiple static directories.
app.use(express.static('public')) app.use(express.static('uploads')) app.use(express.static('files'))
route
introduce
Routing in life, such as when making a service call, what kind of processing can be handled according to the number? It is similar to the mapping relationship between keys and services. In Express, routing refers to the mapping relationship between the request (address) initiated by the client and the server-side processing method (function).
The route in express consists of three parts: request type (method), request uri (address) and corresponding processing function.
When a client request arrives at the server, it first passes through the routing rule matching. Only after the matching is successful will the corresponding processing function be called. When matching, it will be matched according to the routing order. If the request type and the requested URL are matched successfully at the same time, Express will transfer the request to the corresponding function for processing.
app.<get/post/put/delete/use>(uri,(req,res)=>{}) // The use method is not a request type method, but it is placed in the same position as the request method
Routing modularization
Meaning: split the routing rules that may have been written in one file into several routing files (js file, a js file is a module).
As the name suggests, routes are modularized and managed in modules (js files). Birds of a feather flock together.
Core idea: dismantle it if you can (decouple it until you can't, high cohesion, low coupling).
When developing a project, if all routing rules are mounted in the entry file, it becomes more difficult to write and maintain the program. Therefore, for the modular management function of routing, express The router () method creates a routing modular handler, which can separate different business requirements into different modules, so as to facilitate code maintenance and project expansion.
Steps:
-
Specify the request at the beginning of that path, using app Use (beginning of path, processing module)
app.use('/admin',adminRouter) // /The request path starting with admin is handed over to the adminRouter module for processing app.use('/front',frontRouter) // /The request path starting with front is handed over to the frontRouter module for processing
-
This module is not defined. Please define this module
let {adminRouter} = require('./admin/admin') let {frontRouter} = require('./front/front')
-
The imported file has not been defined. Create a file
const express = require('express') const adminRouter = express.Router() // Create routing object // Process the remaining requests through the routing object adminRouter.get('/goods',(req,res)=>{ res.send('This is admin Modular goods page') }) // Export module module.exports = {adminRouter}
At this time, we have two schemes to process the request:
- app.get/post/use ...
- express.Router().get/post ...
- app. Route get/post()
Abbreviation for multiple requests using different request methods for the same request path:
app.route('/book') .get(function(req, res) { res.send('Get a random book'); }) .post(function(req, res) { res.send('Add a book'); }) .put(function(req, res) { res.send('Update the book'); });
middleware
middleware can be understood as the intermediate processing link of business process and intermediate filter.
Classification of Middleware
Middleware can be classified into the following categories:
-
Built in middleware, that is, express itself comes with no npm installation
- express.static()
-
Third party Middleware
Middleware, which is not officially built in but developed by a third party, is called third-party middleware. In the project, the third-party middleware can be installed and configured through npm, so as to improve the development efficiency of the project. For example, the middleware body parser (which parses post data) can easily help us obtain the data submitted by post.
-
Custom middleware, written by developers themselves (the essence of middleware is actually a function)
Considering from the use level, middleware can be divided into:
- Application level middleware (middleware bound to app instance through app.get/post/use and other methods)
- Global use of Middleware (all routes take effect)
- app. Use (Middleware)
- Partial use of Middleware (the current route takes effect)
- app. Request method (address, [middleware...,] callback function)
- app. Request method (address, middleware 1, intermediate 2, intermediate 3...,] callback function)
- Global use of Middleware (all routes take effect)
- Routing level middleware (middleware bound to express.Router())
- Its usage is no different from that of application level middleware, except that one is bound to the app instance and the other is bound to the router
- router. Use (Middleware)
- router. Request method (address, [middleware...,] callback function)
- Its usage is no different from that of application level middleware, except that one is bound to the app instance and the other is bound to the router
Built in middleware
express provides easy-to-use built-in middleware, such as a middleware for static resource management, which can help us quickly build a static resource server:
app.use('prefix',express.static('Managed directory address'))
In express, in addition to the built-in express Static () middleware is also built with two other commonly used middleware:
-
express.json()
- Function: receive data submitted in json format
- Compatibility issue: Express > = 4.16.0
- app.use(express.json())
- After receiving the data, it will mount the object form of the data to the body attribute of the req request object
Use example:
// With this middleware, we can send json data from the client to the server, and the json data will be placed on the body attribute of the req request object app.use(express.json()) app.post('/p1',(req,res)=>{ // express.json middleware can make data hang on the body attribute of req console.log(req.body); res.send('this p1 request is ended') })
First, it must be a post request, and then there must be data, but the data cannot be the previous x-www-form-urlencoded data, but must be raw data
Then the content type of the request header must be application/json
-
express.urlencoded()
- Function: process post form data
- Compatibility issue: Express > = 4.16.0
- app.use(express.urlencoded({extended: false}))
- After receiving the data, it will mount the object form of the data to the body attribute of the req request object
be careful,
- The two commonly used built-in middleware mentioned later have compatibility problems.
- Both of the two middleware mentioned above said that after data processing, it was linked to req Body, but in fact, there will be no coverage problem we want.
Case: json and urlencoded middleware are used to receive json data and form post data, which can be sent through postman
Custom Middleware
The essence of user-defined middleware is to define a function to process requests. However, in addition to the request and response parameters, this function must also contain a next parameter. This parameter is used to enable the middleware to make the process execute downward until the response is sent to the client in the matched route. You can also add attributes to the request object to transfer middleware data downward
function mfn(req,res,next){ //. the logical process you need to define // The middleware must execute this function at last, otherwise the program cannot be executed downward next() }
Note: in the whole request link, all middleware and the final route share a req and res
Case: customize a middleware to receive the form data submitted by post according to the above common characteristics (meaning: does the built-in middleware have compatibility problems)
Third party Middleware
In express, it allows us to use third-party middleware to process data. Typically, for example, a third-party middleware can be used to receive post data.
Taking the use of body parser middleware to receive post data as an example, the steps are as follows:
- Install the third-party middleware body parser
- npm i -S body-parser
- Import body parser from application file
- Call app through middleware use(body.urlencoded({extended: false}))
- Pass req. In the matching route Body gets data in post
- Express built-in express Urlencoded middleware is further encapsulated based on the third-party middleware body parser. However, the built-in version is incompatible, so the general project chooses to install and use the third-party middleware
When using, the syntax of the body parser library is the same as the built-in express The syntax of urlencoded middleware is very similar because the built-in middleware is implemented based on body parser.
Other third-party middleware: http proxy Middleware / CORS / cookie session
exception middleware
**Function: * * it is specially used to catch the abnormal errors of the whole project, so as to prevent the abnormal collapse of the project (friendly display of exceptions).
**Format: * * in the function parameters of the error level middleware, there must be four formal parameters, namely (err,req,res,next)
Q: what is the role of the extra err parameters?
A: it contains the wrong information, err The message attribute contains the error text information, which can be output to the user in the middleware.
app.get('/',(req,res) => { throw new Error('A fatal error has occurred inside the server!') res.send('Welcome to my homepage') }) app.use((err,req,res,next) => { console.log('An error occurred:' + err.message) res.send('Error!' + err.message) })
**Case: * * it is required to specify a path (the file corresponding to the route may not exist), read the file content and output it to the user
Note: if the error level middleware wants to play its role, it must be written behind all routes. Is it app Listen didn't matter before.
404 Middleware
**Function: * * used to process 404 request response
// Suppose this route is defined, but the actual request is / 12345, and 404 will be generated at this time app.post("/1234", (req, res, next) => { res.send('Your request succeeded') }); // 404 output // The middleware also needs to be written at the end (it doesn't matter the order of exception middleware, just make sure it is after all routing methods) app.use((req,res,next) => { // Output 404 error res.status(404).send('<h1>404</h1>') // Specify 404 status code first, and then output error information })
404 error middleware also requires to declare the use after all normal request routes, and do not put it in front of the route, otherwise the subsequent routes will be 404 errors.
**Note: * * error level middleware must be registered after all routes. As for 404 middleware and exception middleware, it doesn't matter who comes first.
Template page: https://404.life/
Other modules
cookie
The principle of cookie is to open a in the browser to store the data in the http request. After the first save, the next request can access the data in the browser as long as the current browser is still used.
The cookie is carried between the response header and the request header as a key value pair.
cookie features:
- Domain name restrictions. Cookies set under the current domain name can only be used under the current domain name
- Timeliness. Cookies will not be permanently stored in the browser and have a certain period of validity
- Quantity limit. Under normal circumstances, each domain name can not exceed 50 cookie s
- Due to space constraints, cookie s can only be stored in 4kb
- Data type restrictions. Only strings can be stored in cookie s
npm i cookie-parser -S
use:
// Import const cookieParser = require('cookie-parser') // middleware app.use(cookieParser()); // Request header acquisition req.headers.cookie // Get all cookie s // Response header settings res.cookie(key,value,{maxAge: term of validity-millisecond}) // Set cookie s
session
Cookies are stored in the browser, so the security is not high, so some important data cannot be stored in cookies, and the storage space of cookies is limited, so there is a session.
The session is stored on the server side. The session needs to rely on a cookie. The session data store will store a sessionid in the cookie. This sessionid will have a mapping relationship with the server side. If the sessionid is tampered with, it will not be implicit with the server side, so the security factor is higher. And the validity period of session is relatively short. It usually takes about 20 minutes. If the browser does not interact with the server within 20 minutes, the server will delete the session data.
npm i cookie-session -S
use:
// Import: const session = require('cookie-session') // session configuration session({ name:"sessionId", secret:"asdfasdfqwer", // The secret key used to encrypt sessioinId. Fill it in casually maxAge:20*60*1000 // 20 minutes }) // Set session req.session[key] = value // Get session req.session[key]
encryption
npm i bcryptjs -S
use:
var bcrypt = require('bcryptjs'); // encryption ciphertext = bcryptjs.hashSync(Plaintext[,number]); // Number, the specified number of rounds will be used to generate salt and use it. Recommendation 10 // verification bcryptjs.compareSync(Plaintext,ciphertext); // By returning true, false is returned in case of failure
jwt
npm install jsonwebtoken
use:
// Generate token by encryption var jwt = require('jsonwebtoken'); var token = jwt.sign(Encrypted object, salt); // verification jwt.verify(token, salt, function(err, decoded) { // decoded is the decrypted object });
File upload
npm i multer -S
use:
var multer = require('multer') var upload = multer({ dest: path.join(__dirname,'public','image') }) // Specify the path of the uploaded file app.post('/profile', upload.single('Upload Forms name value'), function (req, res, next) { // req.file is the uploaded file information from which the file name, path and suffix can be obtained and the splicing path can be stored in mongodb })
mysql
npm i mysql -S
use:
// Import const mysql = require("mysql"); // Create connection object const db = mysql.createConnection({ host:"localhost", user:"root", password:"root", database:"test" }); // connect db.connect(err=>{ if(err){ console.log("Connection failed with error:"+err); return; } console.log("Connection successful"); }); // Execute statement db.query("",(err,result)=>{ if(err){ console.log("Failed, error:"+err); return; } console.log("success"); console.log(result); });
Verification Code
npm i svg-captcha -S
use:
const svgCaptcha = require('svg-captcha') // Create verification code let captcha = svgCaptcha.create(); // captcha is an object, which contains the data key and the text key. Text is the character on the verification code, and data is an svg tag, which can be directly displayed as a picture
Mail sending
npm install nodemailer --save
use:
const nodemailer = require('nodemailer') // 1. Create transmitter const transport = nodemailer.createTransport({ // You need to send the stmp domain name and password of the mailbox and some other information // You need to copy it and find the downloaded nodemailer third-party package // nodemailer -> lib -> well-known -> services.json "host": "smtp.qq.com", "port": 465, "secure": true, // Prove your identity auth: { // User name of sender mailbox user: 'Mailbox number', // stmp allow password pass: 'Authorization code' } }) // 2. Send mail transport.sendMail({ // Send from that mailbox from: 'Sender email', // Where to send, you can write a string, write mailboxes, or write an array, write many mailboxes to: ['Recipient mailbox', 'Recipient mailbox'], // Mail title subject: 'title', // Hypertext content of this email html: ` Hello!: The verification code this time is <h1 style="color: red;"> 2345 </h1> Please use it within 3 minutes <br> ------------------------<br> Future Co., Ltd `, // Text content of this email // text: '' }, function (err, data) { if (err) return console.log(err) console.log('Mail sent successfully') console.log(data) })
template engine
introduce
In a web application, if only the server-side code is used to write the client-side HTML code, and the front and back ends are not separated, it will cause a lot of workload, and the written code will be difficult to read and maintain. If you only use the static HTML file of the client, the back-end logic will be difficult to integrate into the HTML code of the client. In order to facilitate maintenance, integrate the back-end logic into the front-end HTML code, and facilitate maintenance, many third-party developers have developed various Nodejs template engines, of which the more commonly used are Jade/Pug, Ejs, art template and other template engines.
Objective: to make the back-end logic better integrated into the front-end HTML code and easy to maintain
website:
- http://aui.github.io/art-template/zh-cn/
- http://aui.github.io/art-template/express/
Art template is a simple and super fast template engine.
Development mode:
Traditional development mode:
Front end code and back-end code are written together
Mixed together, but this kind of file has requirements. The file is usually written in the back-end language file to write the back-end logic - in this case, it is particularly unfriendly to our front-end siege lion, because our front-end siege lion is responsible for html pages, but we can't write the back-end logic in html pages. If you put html pages in the back-end file, We also need to learn the back-end language
At this point, the template engine appears - the template engine actually allows us to write back-end logic - loop / judgment in html pages
There are many kinds of template engines: Jade / EJS / Art template
The template engine can finally write logic in html, which is equivalent to a syntax mixed with the front and back of our code. Why can it be recognized by the browser in the end? Because our template engine needs to compile html code before the browser recognizes it
Front and rear end separated development mode:
Write html alone;
The backend interface is written by another person;
Interface documents shall be used for docking between the two parties
All data on html is requested back through ajax and displayed in the page through dom operation
Template engine rendering speed test:
characteristic
- Performance close to the limit of JavaScript rendering (DOM operation) (fast)
- Debugging friendly: syntax and runtime error log are accurate to the line of the template; Support breaking points on template files (Webpack Loader)
- Support Express, Koa and Webpack
- Support template inheritance (layout) and sub template (import and include)
- The browser version is only 6KB in size
use
Download and install:
# install npm i -S art-template express-art-template
to configure:
// Template engine configuration // Specify the art template template and the module suffix as html app.engine('html', require('express-art-template')); // Specify template view path app.set('views', path.join(__dirname, 'views')); // Omit the name after specifying the module file suffix (optional suffix that can be omitted during rendering) app.set('view engine', 'html')
Usage:
Art template supports * * standard syntax and original syntax * *. The standard syntax can make the template easy to read and write, while the original syntax has strong logical expression ability. The standard syntax supports basic template syntax and basic JavaScript expressions; The original syntax supports arbitrary JavaScript statements, just like Ejs.
-
Use art template to display a view (html file)
-
Put the view into the views directory (subdirectories are allowed)
-
Write code and display the view by ` res.redner (file path)
app.get('/', (req, res) => { // Output view res.render('404.html') })
-
-
The control layer returns data (assign variables to the view in the js control layer)
app.get(uri,(req,res)=>{ res.render(Template,{ username: 'Zhang San', age: 25, gender: 'female', hobby: ['Basketball','Table Tennis','badminton'] }) })
Template syntax
Variable output:
<!-- Standard grammar --> {{ username }} <!-- perhaps --> <!-- Primitive grammar --> <%= username %>
By default, the above output method cannot allow the browser to parse the content with HTML tags, but only output it as it is. If you need to make HTML tags available to the browser, output the data as follows:
<!-- Standard grammar --> {{@ username}} <!-- Primitive grammar --> <%- username %>
Condition judgment:
{{if condition}} ... {{else if condition}} ... {{/if}} <%if (condition){%> ... <%}else if (condition){%> ... <%}%>
Cycle:
<!-- Supports the iteration of arrays and objects. The default element variable is $value Subscript is $index Can customize {{each target val key}}--> {{each Cyclic data}} {{$index}} {{$value}} {{/each}} {{each Cyclic data val key}} {{key}} {{val}} {{/each}} <% for(var i = 0; i < target.length; i++){ %> <%= i %> <%= target[i] %> <% } %>
If you use the default key and value name (index,value), the $in front of it must be written! Be sure to write!!!
If the user-defined key and value name are used, the preceding $must not be written!! Can't write!!
Template import:
{{include 'Imported file path'}} <% include('Imported file path') %>
- If it is under the current path, be sure to write. / and, If you don't write, look under the disk root
- The file suffix of include defaults to art, if not, do not omit
- It's better not to have html, head and body tags in the sub template (otherwise, it's easy to have style errors)
Template inheritance:
Inherited template:
<html> <head> <meta charset="utf-8"> <!-- be similar to vue Slot for --> <title>{{block 'title'}}My Site{{/block}}</title> </head> <body> <!-- block placeholder content Name of this placeholder --> {{block 'content'}}{{/block}} </body> </html>
Sub templates to inherit:
<!--extend inherit --> {{extend './layout.html'}} {{block 'title'}}home page{{/block}} {{block 'content'}} <p>This is just an awesome page.</p> {{/block}}
Bootcss online Builder: https://www.bootcss.com/p/layoutit/