这是我参与8月更文挑战的第2天,活动详情查看:8月更文挑战
基本概念——域名、IP、端口、URL
- 平时上网的时候,是将域名转换为
ip才能访问到指定的网站服务器(比如本地域名就是localhost,其对应的IP就是127.0.0.1)。 - 而端口是计算机与外界通讯交流的出口,用来区分服务器提供的不同服务。
- 而我们平时所说的网页地址就是URL(组成:
传输协议://服务器IP或域名:端口/资源所在位置标识)。http就是一种超文本传输协议,提供了一种发布和接收HTML页面的方法。
创建web服务器
基础结构:
// 引用系统模块
const http = require('http');
// 创建web服务器
const app = http.createServer();
// 监听客户端发送请求
app.on('request', (req, res) => {
res.end('<h1>hello</h1>'); // 响应内容
})
// 监听3000端口
app.listen(3000);
console.log('服务器启动成功,监听3000端口');
此时用nodemon app.js开启服务器,再打开localhost:3000就可以看到一级标题hello了。
如果要渲染的是一个文件的话,可以就要用到fs模块;当请求地址对应某个url时,用fs.readFile将文件渲染出来;设置请求头,将文件内容写入页面中,对浏览器做出响应。
let path = req.url;
let newPath = path.split('.');
if (newPath == "html") {
fs.readFile(`01_First/src/${newPath}`, "utf-8", function (err, data) {
res.writeHead(200, { "content-type": "text/html;charset=utf-8" })
res.write(data);
res.end();
})
}
对不同请求的url,设置不同的请求头,向浏览器返回对应的文件;
1. HTTP协议
超文本传输协议,基于客户端服务器架构工作,是客户端和服务器端请求和应答的标准。
-
请求方式(Request Method)
- GET 请求数据
- POST 发送数据
-
请求地址(Request URL)
- 可以通过请求地址的不同返回不同的信息(可以看看控制台的
network)
- 可以通过请求地址的不同返回不同的信息(可以看看控制台的
app.on('request', (req, res) => {
req.headers //获取请求报文
req.url //获取请求地址
req.method //获取请求方法
})
http状态码返回200表示请求成功,404表示没找到资源,500表示服务器端错误,400表示客户端请求有语法错误。
内容类型:(1)text/html;(2)text/css;(3)application/javascript;(4)image/jpeg;(5)application/json;服务器端可以通过res.writeHead(400, {'content-type': 'text/html'; charset=utf8})来写入状态码和返回类型。(响应:res.end())
2. 请求参数
Get请求参数:参数被放置在浏览器地址栏中,例如:http://localhost:3000/?name=mannqo.用get请求参数的话,在res.url也可以看到请求参数。这里提供两个方法。
第一,字符串截取的方式,以及node.js的内置模块querystring来处理,先用字符串截取的方式取出参数,再将其转换为对象。说明:spilt的意思用?把原来的字符串切成一个有2个元素的数组,取出[1](即参数对应的数组元素)。
第二,用node.js的另一个内置模块url取出参数值
// 方法一:
const querystring = require('querystring');
console.log(querystring.parse(req.url.split('?')[1])); // key=value的形式
// 方法二:
const url = require('url');
let params = url.parse(req.url, true).query;
console.log(params.name); // 取出参数值
Post请求参数:post参数是通过事件的方式接收的,当请求参数传递的时候触发data事件,当参数传递完成的时候触发end事件。在接收完参数之后给客户端做出响应就是用res.end()。获取到传递的参数是通过&分割开的,此时我们就可以用querystring就可以把参数处理成对象的形式了。
app.on('request', (req, res) => {
let postParams = ''; // 接收参数
req.on('data', (params) => {
postParams += params;
})
req.on('end', () => {
console.log(postParams);
})
res.end('ok');
})
通过下面这种方式,用post去提交参数之后,在控制台的network中就可以看到所提交的参数了。
<form method="POST" action="http://localhost:3000">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit">
</form>
3. 静态和动态资源
- 静态资源:服务器不需要处理就可以直接响应给客户端的资源就是静态资源,例如
css、JavaScript、image文件。即浏览器可以直接运行的文件。 - 动态资源:相同的请求地址获得不同的响应参数,这种就是动态资源,比如
http://localhost/index?id=1和http://localhost/index?id=2,请求地址是相同的,但是从服务器端得到的响应是不同的。
获取动态资源
- 可以创建一个
public的文件夹里面放我们想要通过localhost在浏览器在浏览器访问的页面 - 获取用户的请求路径
- 将用户的请求路径转换为实际的服务器硬盘路径(
__dirname:获取当前文件的绝对路径) - 读取文件,将所读取的文件内容呈现到页面中
app.on('request', (req, res) => {
let pathname = url.parse(req.url).pathname;
pathname = pathname == '/' ? '/canvas.html' : pathname;
let realPath = path.join(__dirname + '/public/' + pathname);
fs.readFile(realPath, (err, result) => {
if(err != null) {
res.writeHead(404, {'content-type': 'text.html'})
console.log('文件读取失败'); // 中文会乱码,因此要指定utf
return;
}
res.end(result);
})
}
文件层级关系
这样子处理之后,在public文件夹存放的文件都可以通过文件名的后缀在服务器中找到了。这里还有一个要注意的事情,有时候content-type会影响页面呈现的结果,比如响应信息中包含中文的时候会乱码,那么我们就要用'content-type': 'text.html'来设置响应类型。这里有一个给我们提供方便的模块就是mime,引入mine模块之后它可以帮我们把content-type改为对应的文件类型。
let type = mime.getType(realPath);
res.writeHead(200, {
'content-type': type
})