nodejs核心模块 http模块 —静态资源
11.处理.html文件中的二次请求-枚举
11.1二次请求
从服务器获取html文件之后,如果这个html文件中还引用了其它的外部资源(图片,样式文件等),则浏览器会重新再发请求。
假设在index.html
中还引入了style.css
, 1.png
或者.js
文件,则:浏览器请求localhost:8000/index.html
之后,得到的从服务器反馈的内容,解析的过程中还发现有外部的资源,所以浏览器会再次发出第二次请求,再去请求相应的资源。
11.2思路
一个最朴素的想法是枚举不同的请求来返回不同的文件。
11.3代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
h1{
text-align: center;
}
</style>
+ <link rel="stylesheet" href="./style.css">
</head>
<body>
<h1>index.html</h1>
+ <img src="./1.png" alt="">
</body>
</html>
上面的+号只是表示这里的代码需要修改。
const http = require('http');
const fs = require('fs');
const path = require('path');
//创建服务器
const app = http.createServer((req, res) => {
if (req.url === '/index.html') {
let htmlString = fs.readFileSync(path.join(__dirname, 'index.html'));
res.end(htmlString);
}
else if (req.url === '/style.css') {
let cssString = fs.readFileSync(path.join(__dirname, 'style.css'));
res.setHeader('content-type', 'text/css');
res.end(cssString);
} else if (req.url === '/1.png') {
let pngString = fs.readFileSync(path.join(__dirname, '/1.png'));
res.end(pngString);
} else {
res.setHeader('content-type', 'text/html;charset=utf-8');
res.statusCode = 404;
res.end('<h2>可惜了, 找不到你要的资源' + req.url + '</h2>');
}
});
//启动服务器,监听8082端口
app.listen(8082, () => {
console.log('8082端口启动');
});
12.处理.html文件中的二次请求-批量处理请求
12.1问题分析
由于我们无法事先得知一个.html
文件中会引用多少个静态资源(.png, .css, .js....
),所以,我们不能像处理某个页面一样去处理它们。
我们的解决办法是:
- 把所有的静态资源(
.html,.png,.css,.js
)全放在一个指定的目录里; - 收到用户的请求之后,去指定的目录下去找对应的文件
- 找到,把内容读出来返回给用户。
- 找不到,报404。
目录如下:
|-public
|-public/index.html
|-public/stye.css
|-public/1.png
|-server.js
在上面的目录结构中,我们把所有的静态资源全放在public下面,然后使用server.js
来启动web服务器。
12.2参考代码
// 当收到用户的请求之后
// 在public下去读这个文件
// 读到:返回
// 读不到:返回404
const http = require('http')
const path = require('path')
const fs = require('fs')
// 放一个对象,其中保存所有的 后缀名与content-type的一一对应关系 策略模式
const mapExtToContentType = {
'.html': 'text/html;charset=utf8',
'.jpg': 'image/jpg',
'.css': 'text/css;charset=utf8',
'.js': 'application/javascript',
'.ico': 'image/ico'
}
const server = http.createServer((req, res) => {
const { url } = req
// 获取后缀名
const ext = path.extname(url)
console.log(url, ext)
// 1. 拼接地址
const filePath = path.join(__dirname, 'public', url)
// 2. 读资源文件
try{
const content = fs.readFileSync(filePath)
console.log(content)
// 根据不同的后缀名,补充不同的content-type
// .html ---> text/html;charset=utf8
// .jpg ---> image/jpg
if(mapExtToContentType[ext]) {
res.setHeader('content-type', mapExtToContentType[ext])
}
// mapExtToContentType[ext] && res.setHeader('content-type', mapExtToContentType[ext])
res.end(content)
} catch (err) {
console.log(err)
res.statusCode = 404
res.end('404')
}
})
server.listen(8001, () => {
console.log('你的服务器在8001就绪');
})