当前位置:网站首页>01. Project introduction of blog development project
01. Project introduction of blog development project
2022-07-06 05:22:00 【John is orange】
The preliminary development of the blog project
1. Project introduction
1.1 The goal is
- Develop a blog system , It has the basic function of blog
- Only develop server End , Don't care about the front end
1.2 demand
- home page , Author URI , Blog details page
- The login page
- Management Center , new page , Edit page
1.3 Technical solution
data storage
Blog

user

The password needs to be encrypted
How to connect with the front end , Interface design

About logging in
There are unified solutions in the industry , Generally, there is no need to redesign
It's more complicated to implement
2. Development interface
2.1 http Request overview
- DNS analysis , resume TCP Connect , send out http request (http Default port 80,https Default port 443)
- server Received http request , Handle , And back to
- The client receives the returned data , Processing data ( Such as rendering the page , perform js)
2.2 Handle get request
- get request , That is, the client wants to server End access data , Such as querying the blog list
- adopt querystring To transfer data , Such as a.html?a=100&b=200
- Browser direct access , Is sent get request
Sample code
const http = require("http");
const {
emitWarning } = require("process");
const qs = require("qs");
const server = http.createServer((req, res) => {
console.log(req.method); // GET
const url = req.url; // Get the complete of the request url
console.log(url);
req.query = qs.parse(url.split("?")[1]); // qs analysis query by JS object
res.end(JSON.stringify(req.query)); // Message sending completed
});
server.listen(8000, () => {
console.log("listen on 8000");
});
Run input http://localhost:8000/?a=100&b=erere after , Background output :
listen on 8000
GET
/?a=100&b=erere
GET
/favicon.ico
/favicon.ico The browser will send it automatically GET request .
Browser display results :

2.3 Handle post request
- post request , That is, the client should transfer data to the server , Such as creating a new blog
- adopt post data To transfer data
- Browsers cannot directly simulate , Handwriting required js, Or use postman
Sample code
const http = require("http");
const server = http.createServer((req, res) => {
if (req.method === "POST") {
// The requested data format
console.log("content-type", req.headers["content-type"]);
// receive data
let postData = "";
// Receiving data streams ,req Triggered when sending data
req.on("data", (chunk) => {
postData += chunk.toString();
});
// req Triggered when transmission is complete
req.on("end", () => {
console.log(postData);
res.end("hello world"); // Back here , Because it's asynchronous
});
}
});
server.listen(8000, () => {
console.log("listen on port 8000");
});
use postman Send request results :
Client received hello world

The backend receives the data sent by the client , And we know that the data type sent by the server is JSON

2.4 Comprehensive case
const http = require("http");
const qs = require("qs");
const server = http.createServer((req, res) => {
const method = req.method;
const url = req.url;
const path = url.split("?")[0];
const query = qs.parse(url.split("?")[1]);
// Set the return format to JSON
res.setHeader("content-type", "application/json");
// Returned data
const resData = {
method,
url,
path,
query,
};
// return
if (method === "GET") {
// return JSON Format string
res.end(JSON.stringify(resData));
}
if (method === "POST") {
let postData = "";
req.on("data", (chunk) => {
postData += chunk.toString();
});
req.on("end", () => {
resData.postData = postData;
res.end(JSON.stringify(resData));
});
}
});
server.listen(8000, () => {
console.log("listen on port 8000");
});
GET Return results :

POST Return results :

3. Build development environment
- from 0 Begin to build , Don't use any framework
- Use nodemon Monitoring file changes , Automatic restart node
- Use cross-env Set the environment variable
3.1 build
yarn init -ynode Project initializationgit initinitialization Git WarehouseInstall the required third-party libraries
yarn add nodemon cross-env --devstay
package.jsonWritten in scripts, Simplify input command line instructions"scripts": { "dev": "cross-env NODE_ENV=dev nodemon ./bin/www.js" },After writing like this , In the command line
yarn devperhapsnpm run devYou can execute the above command instead .cross-env NODE_ENV=devThe current environment is the development environment , And one variable is NODE_ENV The value is dev.js Documents can be passed throughprocess.env.NODE_ENVTo get to the dev.nodemon ./bin/www.jsnodemon monitor www.js The change of , Each change is automatically executed again .( Because I have customized the main entry as www.js)
3.2 Code test build effect
stay ./bin/www.js Write the following code in :
const http = require("http"); const { serverHandle } = require("../app"); const PORT = 8000; // The callback after creating the server is placed in app.js In the document const server = http.createServer(serverHandle); // stay 8000 Listening on the port server.listen(PORT);stay app.js The file contains the callback to create the server ,app.js Focus on business code .
const serverHandle = (req, res) => { // Set the return format JSON res.setHeader("Content-type", "application/json"); const resData = { name: "sjh", site: "ssjjhh.com", env: process.env.NODE_ENV, }; res.end(JSON.stringify(resData)); }; module.exports = { serverHandle, };perform
yarn dev, Visit the local 8000 port , You can get the... Returned by the server JSON data .
4. Initialize route
4.1 Development interface
- Initialize route : According to the design of the previous counting scheme , Make a route
- Return false data : Separate routing and data processing , It has complied with the design principles

By viewing the route , It can be found that interfaces are divided into two categories :blog and user. Six interfaces can be implemented through two files .
blog route
Getting through first is the most important , Write each interface first , The returned content is ignored .
const handleBlogRouter = (req, res) => {
const method = req.method;
// Get a list of blogs
if (method === "GET" && req.path === "/api/blog/list") {
return {
msg: " This is the interface to get the blog list ",
};
}
// Get blog details
if (method === "GET" && req.path === "/api/blog/detail") {
return {
msg: " This is the interface to get blog details ",
};
}
// Create a new blog
if (method === "POST" && req.path === "/api/blog/new") {
return {
msg: " This is the interface for creating a new blog ",
};
}
// Update a blog
if (method === "POST" && req.path === "/api/blog/update") {
return {
msg: " This is the interface for updating blog ",
};
}
// Delete a blog
if (method === "POST" && req.path === "/api/blog/del") {
return {
msg: " This is the interface for deleting blogs ",
};
}
};
module.exports = {
handleBlogRouter,
};
user route
user Routing is the same
const handleUserRouter = (req, res) => {
const method = req.method;
// Sign in
if (method === "POST" && req.path === "/api/user/login") {
return {
msg: " This is the user login interface ",
};
}
};
module.exports = {
handleUserRouter,
};
app.js Incoming routing
Introduce two routes app.js, And after analysis path and query after , Pass to routing . If the requested path and route can match , Will return data , Otherwise do not return .
Significance lies in , Separate business functions , Improve maintainability .
According to this principle , If the routes do not match , Namely 404 Not found . stay serverHandle At the end 404 To deal with .
const qs = require("qs");
const {
handleBlogRouter } = require("./src/router/blog");
const {
handleUserRouter } = require("./src/router/user");
const serverHandle = (req, res) => {
// Set the return format JSON
res.setHeader("Content-type", "application/json");
// obtain path
const url = req.url;
req.path = url.split("?")[0];
// analysis query
req.query = qs.parse(req.path)
// Handle blog route
const blogData = handleBlogRouter(req, res);
if (blogData) {
res.end(JSON.stringify(blogData));
// Need to be return, Otherwise, it will continue to execute
return;
}
// Handle user route
const userData = handleUserRouter(req, res);
if (userData) {
res.end(JSON.stringify(userData));
return;
}
// Missed route : Plain text returns 404 Information
res.writeHead(404, {
"content-type": "text/plain" });
res.write("404 not found");
res.end();
};
module.exports = {
serverHandle,
};
Unify the return information of success and failure
establish model Folder , Create success and failure models :
// src/model/resModel.js
class BaseModel {
constructor(data, message) {
// data It can be the object , It could be a string
if (typeof data === "string") {
this.message = data;
data = null;
message = null;
}
if (data) {
this.data = data;
}
if (message) {
this.message = message;
}
}
}
/** * The model of successful information */
class SuccessModel extends BaseModel {
constructor(data, message) {
super(data, message);
this.errno = 0;
}
}
/** * Model of failure information */
class ErrorModel extends BaseModel {
constructor(data, message) {
super(data, message);
this.errno = -1;
}
}
module.exports = {
SuccessModel,
ErrorModel,
};
Return information later , After the processing of the model , Back to json The structure is expected to be as follows :
{
"errno": 0,
"data": {
...},
"message": "xxx"
}
4.2 Blog list routing development

Now build one controller layer , Write relevant business inside . Because the database is not connected yet , So first return the data you made . The following is the relevant code for obtaining blog list data :
// src/controller/blog.js
const getList = (author, keyword) => {
// return Mock data ( The format is correct )
return [
{
id: 1,
title: " title A",
content: " Content A",
createTime: 1654087871762,
author: "zhangsan",
},
{
id: 2,
title: " title B",
content: " Content B",
createTime: 1654087879762,
author: "lisi",
},
];
};
controller Split the data ,router Only focus on data . The following is the related code of blog list routing :
// src/router/blog.js
// Get a list of blogs
if (method === "GET" && req.path === "/api/blog/list") {
const author = req.query.author || "";
const keyword = req.query.keyword || "";
const listData = getList(author, keyword);
return new SuccessModel(listData);
}
Return results :

4.3 Blog details routing development
// src/router/blog.js
// Get blog details
if (method === "GET" && req.path === "/api/blog/detail") {
const id = req.query.id;
const data = getDetail(id);
return new SuccessModel(data);
}
controller And the return result is slightly .
4.4 Processing of route development POST data
app.js Now there is only parsing path and query,POST data did not .POST Data transmission is asynchronous , Wait deliberately POST After data transmission , The relevant code of the route can run , Make sure you get it POST data.
Because of convenience , Create a single Handle POST data Function of . Asynchronous method returns promise after , have access to then/catch Monogram or await Syntax sugar to handle asynchronous requests , Just run the following code .
// app.js
const getPostData = (req) => {
return new Promise((resolve, reject) => {
// Not POST The request does not exist POST data The problem of
if (req.method !== "POST") {
resolve({
});
return;
}
// If POST data No JSON Formatted data , Direct to ignore ( This project POST data All are JSON Format )
if (req.headers["content-type"] !== "application/json") {
resolve({
});
return;
}
let postData = "";
req.on("data", (chunk) => {
postData += chunk.toString();
});
req.on("end", () => {
if (!postData) {
resolve({
});
return;
}
resolve(JSON.parse(postData));
});
});
};
const serverHandle = async (req, res) => {
// Set the return format JSON
res.setHeader("Content-type", "application/json");
// obtain path
const url = req.url;
req.path = url.split("?")[0];
// analysis query
req.query = qs.parse(req.path);
// analysis POST data Put it after req.body Inside
const postData = await getPostData(req);
req.body = postData;
// Handle blog route
const blogData = handleBlogRouter(req, res);
if (blogData) {
res.end(JSON.stringify(blogData));
// Need to be return, Otherwise, it will continue to execute
return;
}
// Handle user route
const userData = handleUserRouter(req, res);
if (userData) {
res.end(JSON.stringify(userData));
return;
}
// Missed route : Plain text returns 404 Information
res.writeHead(404, {
"content-type": "text/plain" });
res.write("404 not found");
res.end();
};
4.5 New blog route development
With the top postData After processing , The route can go through req.body Get post The transmitted data .
// router/blog.js
// Create a new blog
if (method === "POST" && req.path === "/api/blog/new") {
const data = newBlog(req.body);
return new SuccessModel(data);
}
// controller/blog.js
const newBlog = (blogData = {
}) => {
// blogData Is a blog object , contain title、content attribute
return {
...blogData, // Just a demonstration. POST data Succeeded in getting
id: 3, // Indicates a new blog , Inserted into the data table id
};
};
stay postman send out post Request and response results :

4.6 Update blog routing development
Update route is also used post Method , But what is different from the new blog is , When updating a blog, you need to bring id Parameters can be modified .
// controller/blog.js
/** * Updates the specified id The blog content of * @param {number} id To update the corresponding blog id * @param {object} blogData Blog object , contain title、content attribute */
const updateBlog = (id, blogData = {
}) => {
console.log("update blog", blogData);
return true;
};
// router/blog.js
// Update a blog
if (method === "POST" && req.path === "/api/blog/update") {
const result = updateBlog(id, req.body);
if (result) {
return new SuccessModel();
} else {
return new ErrorModel(" Update failed ");
}
}
4.7 Delete blog route
// controller/blog.js
const delBlog = (id) => {
return true;
};
// router/blog.js
// Delete a blog
if (method === "POST" && req.path === "/api/blog/del") {
const result = delBlog(id);
if (result) {
return new SuccessModel();
} else {
return new ErrorModel(" Failed to delete blog ");
}
}
4.8 Login routing completed
// controller/user.js
const loginCheck = (username, password) => {
// Use fake data first
if (username === "admin" && password === "123456") {
return true;
}
return false;
};
module.exports = {
loginCheck
};
// router/user.js
const {
loginCheck } = require("../controller/user");
const {
SuccessModel, ErrorModel } = require("../model/resModel");
const handleUserRouter = (req, res) => {
const method = req.method;
// Sign in
if (method === "POST" && req.path === "/api/user/login") {
const {
username, password } = req.body;
const result = loginCheck(username, password);
if (result) {
return new SuccessModel();
}
return new ErrorModel(" Login failed ");
}
};
module.exports = {
handleUserRouter,
};
4.9 Routing and API The difference between
- API: Front end and backing , A term for docking between different ends
- url ( route ), Input , Output
- route :
- API Part of , Address of the interface
- A definition inside the backend system
边栏推荐
- Promotion hung up! The leader said it wasn't my poor skills
- Select knowledge points of structure
- Modbus protocol communication exception
- 【LeetCode】18、四数之和
- Can the feelings of Xi'an version of "Coca Cola" and Bingfeng beverage rush for IPO continue?
- Vulhub vulnerability recurrence 67_ Supervisor
- [leetcode] 18. Sum of four numbers
- 04. 项目博客之日志
- Knowledge points of circular structure
- Codeforces Round #804 (Div. 2) Editorial(A-B)
猜你喜欢

Questions d'examen écrit classiques du pointeur

Vulhub vulnerability recurrence 71_ Unomi

Fluent implements a loadingbutton with loading animation

Huawei equipment is configured with OSPF and BFD linkage

注释、接续、转义等符号

无代码六月大事件|2022无代码探索者大会即将召开;AI增强型无代码工具推出...

Postman assertion

Please wait while Jenkins is getting ready to work

C Advanced - data storage (Part 1)

The ECU of 21 Audi q5l 45tfsi brushes is upgraded to master special adjustment, and the horsepower is safely and stably increased to 305 horsepower
随机推荐
Sliding window problem review
【云原生】3.1 Kubernetes平台安装KubeSpher
JDBC calls the stored procedure with call and reports an error
Notes, continuation, escape and other symbols
Three. JS learning - light and shadow (understanding)
Oracle deletes duplicate data, leaving only one
浅谈镜头滤镜的类型及作用
指针经典笔试题
01. 开发博客项目之项目介绍
MySQL time processing
Summary of deep learning tuning tricks
Implementing fuzzy query with dataframe
[leetcode16] the sum of the nearest three numbers (double pointer)
用StopWatch 统计代码耗时
Cve-2019-11043 (PHP Remote Code Execution Vulnerability)
js Array 列表 实战使用总结
pix2pix:使用条件对抗网络的图像到图像转换
Fluent implements a loadingbutton with loading animation
Promotion hung up! The leader said it wasn't my poor skills
Review of double pointer problems