1 服务器端基础概念
1.1 网站的组成
1.2 node网站服务器
1.3 IP地址
1.4 域名
1.5 端口
用于区分是FTP服务、HTTP服务、收发邮件服务、web服务等。
1.6 URL
1.7 开发过程中客户端和服务器端说明
2 创建WEB服务器
在Node.js中如何创建网站服务器,网站服务器就是一台电脑,在这个电脑中我们要安装node.js服务器,现在要使用nodejs创建软件层面的网站服务器,也就是说要得到请求对象和相应对象
创建服务器具体步骤:
- 在lesson2文件夹下新建sever文件夹,在该文件夹下新建app.js文件
- 在app.js文件中创建服务器,代码如下:
//用于创建网站服务器模块
const http = require('http');
//返回值app就是网站服务器对象
const app = http.createServer();
//为网站服务器添加请求事件,
//on(参数1,参数2)参数1:request是请求的事件名称 参数2:事件处理函数
//当客户端有请求来的时候:
app.on('request', (req, res) => { //req是请求对象,保存了请求相关的信息,利用res下的方法对客户端进行相应
//服务器端的响应
res.end('<h2>hello user</h2>')
});
//上述网站服务器创建好之后,还要监听端口
app.listen(3000); //习惯性传端口号3000
console.log('网站服务器启动成功');
如何访问该服务器呢?
- 首先使用node命令执行文件app.js,只有这个文件被执行了,网站服务器才能启动成功
- 执行文件的时候为方便不使用node app.js不使用nodemon app.js,好处是只要重新修改了app.js文件并保存后,命令行中就会自动执行
- 此时打开浏览器就可以访问网站,由于这个服务器是在自己的电脑上启动的,那么我们就需要启动特殊的域名localhost找到自己的电脑,同时我们的电脑又有很多服务,我们就需要用端口来区分服务(找到app.js),告知电脑我们需要访问的是网站这个服务localhost:3000
- 疑问:h2怎么原封不动地输出了呢?我们将学习的http协议可以帮助解决这个问题。
3 HTTP协议
3.1 概念
HTTP协议是客户端和服务器端进行沟通的规范(超文本传输协议)
- 超文本:在文本中除了包含文字以外,还可以包含图片、视频、音频,实际上就是html文本
- 传输协议:规定了如何从网站服务器传输html文本到浏览器
3.2 报文
报文分请求报文和响应报文
对于开发人员报文可以在哪里被看到呢?答:浏览器
1 客户端对服务器的请求
2 服务器对客户端的响应
先了解response选项
切回到headers中
3.3 请求报文
请求方式分为get请求和post请求,用来告诉服务器端当前这个请求要做的事情的类型
- Get常用于获取数据的请求
- Post常用于添加数据的请求
- 若一个请求既不是获取数据也不是添加数据而就是网站中的一般逻辑(eg:登陆操作)也用Post,因为Post相对于Get来说要安全些
客户端如何向服务器端发送Post请求或Get请求呢?(req.method)
(1)常见的Get请求就是在地址栏中输入网址,如何证明?实际上在服务器端是可以获取客户端的请求方式的,举例如下:
- app.js
//用于创建网站服务器模块
const http = require('http');
//返回值app就是网站服务器对象
const app = http.createServer();
//为网站服务器添加请求事件,
//on(参数1,参数2)参数1:request是请求的事件名称 参数2:事件处理函数
//当客户端有请求来的时候:
app.on('request', (req, res) => { //req是请求对象,保存了请求相关的信息,利用res下的方法对客户端进行相应
//服务器端通过req来获取客户端请求的方式req.method
console.log(req.method);
//服务器端的响应
res.end('<h2>hello user</h2>')
});
//上述网站服务器创建好之后,还要监听端口
app.listen(3000); //习惯性传端口号3000
console.log('网站服务器启动成功');
- 运行
- 打开浏览器输入localhost:3000,此时再看一眼命令行窗口,出现了GET
上述过程说明了在浏览器地址栏中输入网址是GET方式,那么为什么有两个get呢?答案:一个是localhost请求一个是浏览器的图标请求
(2)如何发送post请求呢?可以通过表单的方式form标签,举例如下
- 在sever文件夹下新建form.html,内容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!--
表单中的属性
method:指定当前表单提交的方式,可以是GET也可以是POST,默认GET
action:指定当前表单提交的地址(服务器)
-->
<form action="http://localhost:3000" method="POST">
<input type="submit">
</form>
</body>
</html>
- 在浏览器中打开form.html,点击提交后(提交给服务器localhost:3000),跳转到localhost:3000返回的页面
表单的提交是post行为,提交后表单有一个默认的跳转行为是get方式
对于get请求和post请求,服务器拿到之后的用处是?
当前发送get请求和post请求是同一个网址。若请求的地址相同但是方式不同,那么服务器可以根据请求方式响应不同的内容(通过if...else语句)。在app.js做出判断如下:
(1)app.js
const http = require('http');
const app = http.createServer();
app.on('request', (req, res) => {
console.log(req.method);
if (req.method == 'POST') {
res.end('post');
} else if (req.method == 'GET') {
res.end('get');
}
});
app.listen(3000); //习惯性传端口号3000
console.log('网站服务器启动成功');
(2)命令行中打开服务器,打开浏览器输入localhost:3000
(3)切回到命令行工具
(4)打开服务器,在浏览器中打开form.html,提交表单后
res.end()这是协议尾,表示这个网页结束,如果没有会导致网页一直在加载
面临的问题:客户端无论访问什么样的请求地址返回的都是相同的内容,举例如下(req.url)
如何根据客户端访问的请求地址,来响应不同的内容呢?那么就需要服务器端可以获取到客户端的请求地址
(1)引子
- app.js
const http = require('http');
const app = http.createServer();
app.on('request', (req, res) => {
//获取请求地址req.url
console.log(req.url);
if (req.method == 'POST') {
res.end('post');
} else if (req.method == 'GET') {
res.end('get');
}
//服务器端的响应
// res.end('<h2>hello user</h2>')
});
app.listen(3000); //习惯性传端口号3000
console.log('网站服务器启动成功');
- 打开服务器,在浏览器中输入localhost:3000/index,切回到命令行中:
(2)解决方案
- app.js
const http = require('http');
const app = http.createServer();
app.on('request', (req, res) => {
if (req.url == '/index' || req.url == '/') {
res.end('welcome to homepage');
} else if (req.url == '/list') {
res.end('welcome to list page');
} else {
res.end('not found');
}
if (req.method == 'POST') {
res.end('post');
} else if (req.method == 'GET') {
res.end('get');
}
});
app.listen(3000); //习惯性传端口号3000
console.log('网站服务器启动成功');
- 打开服务器,在浏览器中输入localhost:3000/index,切回到命令行中:
- 输入localhost:3000,切回到命令行中:
如何获取请求信息呢?(req.headers)
req.headers这个对象里面存储的就是请求报文信息,举例如下
(1)app.js
const http = require('http');
const app = http.createServer();
app.on('request', (req, res) => {
//获取请求报文信息req.headers
console.log(req.headers);
if (req.url == '/index' || req.url == '/') {
res.end('welcome to homepage');
} else if (req.url == '/list') {
res.end('welcome to list page');
} else {
res.end('not found');
}
if (req.method == 'POST') {
res.end('post');
} else if (req.method == 'GET') {
res.end('get');
}
});
app.listen(3000);
console.log('网站服务器启动成功');
(2)打开服务器,在浏览器中输入localhost:3000,切回到命令行中:可以看到有两个对象的输出
(3)切回到命令行中:可以看到有两个对象的输出
(4)如果想获取具体的某一项,需要修改app.js如下(比如想获取accept)
//console.log(req.headers);
console.log(req.headers['accept']);
(5)打开服务器,在浏览器中输入localhost:3000,切回到命令行中可以拿到具体的信息
3.4 响应报文
1 HTTP状态码
对于客户端的每一次请求,服务器端都要给予相应,告诉客户端本次请求是成功还是失败。服务器主要通过HTTP状态码的方式来告知客户端,服务器通过给客户端返回不同的状态码来对客户端进行通知(若服务器端没有返回状态码,这个状态码默认是200)
(1)去服务器端尝试为客户端设置不同的状态码
- app.js
const http = require('http');
const app = http.createServer();
app.on('request', (req, res) => {
//要为服务器端提供一些相应要用到res对象
// res.writeHead(状态码默认200,)书写相应报文
res.writeHead(500);
if (req.url == '/index' || req.url == '/') {
res.end('welcome to homepage');
} else if (req.url == '/list') {
res.end('welcome to list page');
} else {
res.end('not found');
}
if (req.method == 'POST') {
res.end('post');
} else if (req.method == 'GET') {
res.end('get');
}
});
app.listen(3000);
console.log('网站服务器启动成功');
- 打开服务器,在浏览器中输入localhost:3000
http状态码就是一种标识,服务器在返回的时候要把状态码设置成多少完全取决于当前的情况
2 内容类型
在服务器端为客户端作出相应的时候,一定是有相应内容的类型。服务器需要告诉客户端当前返回的类型是什么,如果不告知,那么浏览器就不知道如何解析收到的类容。返回的是html文件就设置为text/html,返回的是css文件就设置为text/css.
(1)返回类型举例
- app.js
const http = require('http');
const app = http.createServer();
app.on('request', (req, res) => {
//要为服务器端提供一些相应要用到res对象
// res.writeHead(状态码默认200,对象)书写相应报文
//对象里面写的是相应头里面的信息
res.writeHead(200, {
'content-type': 'text/plain' //返回纯文本,若不指定这一项也是默认返回纯文本
});
if (req.url == '/index' || req.url == '/') {
res.end('welcome to homepage');
} else if (req.url == '/list') {
res.end('welcome to list page');
} else {
res.end('not found');
}
if (req.method == 'POST') {
res.end('post');
} else if (req.method == 'GET') {
res.end('get');
}
});
app.listen(3000);
console.log('网站服务器启动成功');
- 打开服务器,在浏览器中输入localhost:3000
(2)让浏览器解析html标签
- app.js
const http = require('http');
const app = http.createServer();
app.on('request', (req, res) => {
//要为服务器端提供一些相应要用到res对象
// res.writeHead(状态码默认200,对象)书写相应报文
//对象里面写的是相应头里面的信息
res.writeHead(200, {
'content-type': 'text/html' //返回html文本,若不指定这一项也是默认返回纯文本
});
if (req.url == '/index' || req.url == '/') {
res.end('<h2>welcome to homepage</h2>');
} else if (req.url == '/list') {
res.end('welcome to list page');
} else {
res.end('not found');
}
if (req.method == 'POST') {
res.end('post');
} else if (req.method == 'GET') {
res.end('get');
}
});
app.listen(3000);
console.log('网站服务器启动成功');
- 打开服务器,在浏览器中输入localhost:3000
- 问题:若将app.js中的welcome to homepage修改为中文:欢迎来到主页。重复上述过程会发现一堆乱码:
- 解决:服务器需要告知客户端当前返回文件的编码类型,在做网页开发的时候一般都是utf-8的编码,所以需要指定编码。只需要将
'content-type': 'text/html'
修改为
'content-type': 'text/html;charset=utf8'
之后刷新浏览器