What is a Web server?
When an application (client) needs a resource, it can request the resource from a server through Http. The server that provides the server is a Web server;
There are many open source Web servers out there: Nginx, Apache (static), Apache Tomcat (static, dynamic), Node.js
Http template basic use
1.1. How do I create a service
1.1.1. Initial experience of Web server
A first look at creating a Web server:
const http = require('http');
const HTTP_PORT = 8000;
const server = http.createServer((req, res) = > {
res.end("Hello World");
});
server.listen(8000.() = > {
console.log('🚀 server is in${HTTP_PORT}Start ~ `)})Copy the code
1.1.2. Create a server
To create the server object, we do this using createServer
http.createServer
An object that returns to the server;- The underlying layer actually uses a direct New Server object.
function createServer(opts, requestListener) {
return new Server(opts, requestListener);
}
Copy the code
So, of course, we can also create this object ourselves:
const server2 = new http.Server((req, res) = > {
res.end("Hello Server2");
});
server2.listen(9000.() = > {
console.log("Server started successfully ~");
})
Copy the code
As we have seen above, a callback function is passed when the Server is created. This callback function is called with two arguments:
- Req: request Request object, which contains information about the request.
- Res: Response The response object that contains the information we want to send to the client;
1.1.3. Listen on ports and hosts
The Server uses the Listen method to start the Server and listen for network requests on a host or port:
- That is, when we pass
ip:port
Is sent to the Web server we are listening to; - We can do something about it;
The listen function takes three arguments:
- Port: it can not be transmitted, the system will assign the end by default, we will write it into the environment variable in the subsequent project;
- Host: you can usually pass localhost, IP address 127.0.0.1, or IP address 0.0.0.0. The default is 0.0.0.0.
- Localhost: is essentially a domain name that is normally resolved to 127.0.0.1;
- 127.0.0.1: Loop Back Address (127.0.0.1) : Loop Back Address (127.0.0.1)
- Normal database packages often application layer – transport layer – network layer – data link layer – physical layer;
- However, the loopback address is directly obtained at the network layer and is not often at the data link layer and physical layer.
- Like we listen in
127.0.0.1
The IP addresses of hosts on the same network segment cannot be accessed.
- 0.0.0.0:
- Listen to all addresses on IPV4 and find different applications by port;
- Like we listen in
0.0.0.0
Hosts on the same network segment can be accessed using IP addresses.
- Callback function: the callback function when the server is successfully started;
server.listen(() = > {
console.log("Server start ~🚀");
})
Copy the code
1.2. Request Request object
When sending a request to the server, we carry a lot of information, such as:
- This request URL, the server needs to conduct different processing according to different URL;
- The request methods, such as GET and POST, are different.
- Headers also carries some information, such as the client information, the format of the data received, and the supported encoding format.
- And so on…
Node will help us encapsulate this information into a request object that we can process directly:
const server = http.createServer((req, res) = > {
/ / request object
console.log(req.url);
console.log(req.method);
console.log(req.headers);
res.end("Hello World");
});
Copy the code
1.2.1. Processing of URL
When the client sends a request, it will request different data, so it will pass a different request address:
- Such as
http://localhost:8000/login
; - Such as
http://localhost:8000/products
;
The server needs to make different responses according to different request addresses:
const server = http.createServer((req, res) = > {
const url = req.url;
console.log(url);
if (url === '/login') {
res.end("welcome Back~");
} else if (url === '/products') {
res.end("products");
} else {
res.end("error message"); }});Copy the code
What if the user sends the address with some extra parameters?
-
http://localhost:8000/login?name=why&password=123
; -
At this point, the url is /login, right? Name = why&password = 123;
How do we parse it?
- Use the built-in module URL;
const url = require('url');
// Parse the request
const parseInfo = url.parse(req.url);
console.log(parseInfo);
Copy the code
Analysis results:
Url {
protocol: null.slashes: null.auth: null.host: null.port: null.hostname: null.hash: null.search: '? name=why&password=123'.query: 'name=why&password=123'.pathname: '/login'.path: '/login? name=why&password=123'.href: '/login? name=why&password=123'
}
Copy the code
We will find that the PathName is the result we want.
But how can query information be retrieved?
- Method 1: Intercept a string;
- Method 2: Use the QueryString built-in module;
const { pathname, query } = url.parse(req.url);
const queryObj = qs.parse(query);
console.log(queryObj.name);
console.log(queryObj.password);
Copy the code
1.2.2. Method processing
In a Restful specification (design style), we should add, delete, modify, and review data through different requests:
- GET: Queries data.
- POST: Creates data.
- PATCH: updates data.
- DELETE: deletes data.
Therefore, we can do different processing by judging different request modes.
For example, create a user:
- The request interface is
/users
; - Request mode:
POST
Requests; - Carry data
username
andpassword
;
How to judge and obtain the corresponding data in our program?
- So we need to figure out what the interface is
/users
And the request method is the POST method to get the incoming data; - To get the data carried by the body, we need to listen on the REQ
data
Event to get;
if (req.url.indexOf('/users')! = = -1) {
if (req.method === 'POST') {
// You can set the encoding, or you can get the string format from data.toString() below
req.setEncoding('utf-8');
req.on('data'.(data) = > {
const {username, password} = JSON.parse(data);
console.log(username, password);
});
res.end("create user success");
} else {
res.end("users list"); }}else {
res.end("error message");
}
Copy the code
Parse converts the JSON string format to an object type using the json.parse method.
1.2.3. Header properties
The header of the Request object also contains a lot of useful information:
const server = http.createServer((req, res) = > {
console.log(req.headers);
res.end("Hello Header");
});
Copy the code
By default, the browser passes some information:
{
'content-type': 'application/json'.'user-agent': 'PostmanRuntime / 7.26.5'.accept: '* / *'.'postman-token': 'afe4b8fe-67e3-49cc-bd6f-f61c95c4367b'.host: 'localhost:8000'.'accept-encoding': 'gzip, deflate, br'.connection: 'keep-alive'.'content-length': ', 48 '
}
Copy the code
Content-type is the type of data carried in this request:
application/json
Represents a JSON type;text/plain
Representation is a text type;application/xml
The representation is of type XML;multipart/form-data
Indicates that the file is uploaded.
The content – length:
- The size and length of the file
Keep alive: –
-
HTTP is based on TCP, but usually interrupts immediately after a request and response.
-
In HTTP1.0, if you want to remain connected:
- The browser needs to add in the request header
connection: keep-alive
; - The server needs to add in the response header
connection:keey-alive
; - When the client releases the request again, it will use the same connection, and directly one party breaks the connection;
- The browser needs to add in the request header
-
In HTTP1.1, all connections are connection: keep-alive by default;
- Different Web servers have different holds
keep-alive
The time. - In Node, 5s is the default;
- Different Web servers have different holds
The accept – encoding:
- Inform the server that the file compression format supported by the client, such as JS files can use GZIP encoding, corresponding
.gz
File;
Accept:
- Inform the server of the format types of files that are acceptable to the client;
The user-agent:
- Client related information;
1.3. Response object Response
1.3.1. Return the response result
If we want to give the client the result data of the response, we can do it in two ways:
- Write method: This method writes out data directly, but does not close the stream;
- End method: This method writes out the last data and closes the stream.
const http = require('http');
const server = http.createServer((req, res) = > {
// There are two ways to respond to data:
res.write("Hello World");
res.write("Hello Response");
res.end("message end");
});
server.listen(8000.() = > {
console.log("Server start 🚀~")});Copy the code
If we hadn’t called end and close, the client would have been waiting for the result, so the client would have set a timeout when sending network requests.
1.3.2. Return the status code
An Http Status Code is a numeric Code used to indicate the Status of an Http response:
- Http status code is very many, according to different situations, to the client to return different status code;
- Common status codes are the following (and will be used in future projects);
There are two common ways to set the status code:
res.statusCode = 400;
res.writeHead(200);
Copy the code
1.3.3. Response header files
There are two main ways to return header information:
res.setHeader
: Writes one header at a time.res.writeHead
: Write both header and status;
res.setHeader("Content-Type"."application/json; charset=utf8");
res.writeHead(200, {
"Content-Type": "application/json; charset=utf8"
})
Copy the code
So what does Header set content-type do?
- By default, the client receives a string, and the client processes it in its default way.
For example, we return a piece of HTML, but do not specify the format:
res.end('<h2>Hello World</h2>')
Copy the code
However, if we specify the format:
res.setHeader("Content-Type"."text/html; charset=utf8");
res.end('<h2>Hello World</h2>')
Copy the code
What if we want to return a piece of JSON data?
res.writeHead(200, {
"Content-Type": "application/json; charset=utf8"
})
const data = {
name: "Wang Hongyuan".age: 18.height: 1.88
};
res.end(JSON.stringify(data));
Copy the code
Other Web supplements
2.1. Use of file upload
If it is a large file that needs to be uploaded to the server, how should the server save it?
const server = http.createServer((req, res) = > {
if (req.url === '/upload') {
if (req.method === 'POST') {
const fileWriter = fs.createWriteStream('./foo.png');
req.pipe(fileWriter);
const fileSize = req.headers['content-length'];
let curSize = 0;
console.log(fileSize);
req.on("data".(data) = > {
curSize += data.length;
console.log(curSize);
res.write('File upload progress:${curSize/fileSize * 100}%\n`);
});
req.on('end'.() = > {
res.end("File upload completed ~"); }}})else {
res.end("error message"); }});Copy the code
The file was uploaded successfully, but the file could not be opened:
- That’s because the data that we write, it contains some special information;
- The software that opens up this information doesn’t parse very well;
const server = http.createServer((req, res) = > {
if (req.url === '/upload') {
if (req.method === 'POST') {
// Image files must be set to binary
req.setEncoding('binary');
// Get the value of boundary in content-type
var boundary = req.headers['content-type'].split('; ') [1].replace('boundary='.' ');
// Record the current data
const fileSize = req.headers['content-length'];
let curSize = 0;
let body = ' ';
// Listen for current data
req.on("data".(data) = > {
curSize += data.length;
res.write('File upload progress:${curSize/fileSize * 100}%\n`);
body += data;
});
// Data structure
req.on('end'.() = > {
// Cut the data
const payload = qs.parse(body, "\r\n".":");
// Get the last type (image/ PNG)
const fileType = payload["Content-Type"].substring(1);
// Get the length to intercept
const fileTypePosition = body.indexOf(fileType) + fileType.length;
let binaryData = body.substring(fileTypePosition);
binaryData = binaryData.replace(/^\s\s*/.' ');
// binaryData = binaryData.replaceAll('\r\n', '');
const finalData = binaryData.substring(0, binaryData.indexOf(The '-'+boundary+The '-'));
fs.writeFile('./boo.png', finalData, 'binary'.(err) = > {
console.log(err);
res.end("File upload completed ~"); }}})})else {
res.end("error message"); }});Copy the code
2.2. HTTP sends network requests
The AXIos library can be used in a browser as well as in Node:
- In browsers, Axios uses wrapped XHR;
- In Node, the HTTP built-in module is used;
So HTTP modules can send network requests directly from Node.
Send a GET request:
http.get("http://localhost:8000".(res) = > {
res.on('data'.data= > {
console.log(data.toString());
console.log(JSON.parse(data.toString())); })});Copy the code
Send a POST request:
const req = http.request({
method: 'POST'.hostname: "localhost".port: 8000
}, (res) = > {
res.on('data'.data= > {
console.log(data.toString());
console.log(JSON.parse(data.toString()));
})
})
req.on('error'.err= > {
console.log(err);
})
req.end();
Copy the code
Note: All of this content will be published on our official website. We will update our tutorials on Flutter, TypeScript, React, Node, Uniapp, MPvue, data structures and algorithms, etc. We will also update some of our own learning experiences