一. 完成六个目标,开始完成目标一
- 以上就是一些前置的基础之后,接下来我们来完成六个目标,目标一根据url返回不同的文件
- 我们先要准备一些静态文件
- 新建public/index.html
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>网页1</title> </head> <body> <h1>这是一个 index.html</h1> </body> </html>- 新建public/style.css
h1 { color: red; }- 新建public/main.js
const h1 = document.querySelector('h1') h1.onclick = () => { alert('我是 js') } - 搞定三个静态文件之后,我们来处理服务端,先写返回index.html,这样子我们访问
http://127.0.0.1:8888/index.html就能得到一个html文件
import * as http from 'http';
import * as p from 'path';
import * as fs from 'fs';
const server = http.createServer();
const publicDir = p.resolve(__dirname, 'public')
server.on('request', (request, response) => {
const {method, url, headers} = request
console.log('url', url)
switch(url) {
case '/index.html':
fs.readFile(p.resolve(publicDir, 'index.html'), (error, data) => {
if(error) throw error;
response.end(data.toString())
});
break;
}
});
server.listen(8888);
- 依样画葫芦,返回style.css和main.js,需要注意这里要设置response的Header,告诉浏览器如何响应
server.on('request', (request, response) => {
const {method, url, headers} = request
console.log('url', url)
switch(url) {
case '/index.html':
response.setHeader('Content-Type', 'text/html; charset=utf-8');
fs.readFile(p.resolve(publicDir, 'index.html'), (error, data) => {
if(error) throw error;
response.end(data.toString())
});
break;
case '/style.css':
response.setHeader('Content-Type', 'text/css; charset=utf-8');
fs.readFile(p.resolve(publicDir, 'style.css'), (error, data) => {
if(error) throw error;
response.end(data.toString())
});
break;
case '/main.js':
response.setHeader('Content-Type', 'text/javascript; charset=utf-8');
fs.readFile(p.resolve(publicDir, 'main.js'), (error, data) => {
if(error) throw error;
response.end(data.toString())
});
break;
}
});
server.listen(8888);
- 给html加上css和js引用,这样就能看到样式和有js
<!doctype html>
<html lang="ch">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>网页1</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>这是一个 index.html</h1>
<script src="main.js"></script>
</body>
</html>
二. 完成任务二,处理查询参数
- 我们给链接加上?q=1,
curl -v -d "name=frank" http://localhost:8888/index.html?q=1 - 我们需要借助url模块来实现,查询参数不影响代码逻辑
server.on('request', (request, response) => {
const {method, url: path, headers} = request
const {pathname, search} = url.parse(path)
switch(pathname) {
case '/index.html':
...
}
}
三. 完成任务三:如何匹配任意文件
- 此时我再加一个js文件,比如jquery.js并在html中引用
server.on('request', (request, response) => {
const {method, url: path, headers} = request
const {pathname, search} = url.parse(path)
// response.setHeader('Content-Type', 'text/html; charset=utf-8');
const filename = pathname.substring(1);
fs.readFile(p.resolve(publicDir, filename), (error, data) => {
if(error) {
response.statusCode = 404;
response.end('文件不存在');
} else {
response.end(data.toString())
}
});
});
server.listen(8888);
- 此时只要url路径是和服务器的路径匹配即可访问到
四. 完成任务四:处理错误
- 新建一个404页面
- 完成错误逻辑
server.on('request', (request, response) => {
const {method, url: path, headers} = request
const {pathname, search} = url.parse(path)
let filename = pathname.substring(1);
if (filename==='') {
filename = 'index.html'
}
response.setHeader('Content-Type', 'text/html; charset=utf-8');
fs.readFile(p.resolve(publicDir, filename), (error, data) => {
if(error) {
console.log(error)
if(error.errno===-2) {
response.statusCode = 404;
fs.readFile(p.resolve(publicDir, '404.html'), (error, data) => {
response.end(data);
})
} else if (error.errno===-21) {
response.statusCode = 403;
response.end('无权查看目录内容');
} else {
response.statusCode = 500;
response.end('服务器繁忙,请稍后再尝试');
}
} else {
response.end(data)
}
});
});
server.listen(8888);
- 注意小细节,html中图片的路径写法,如果提示下划线,在public上右键mark as root directory
<img src="/images/404.png" alt="">
五. 目标五:处理非get请求
- 现在index.html构造一个post请求
<form action="/form" method="post" autocomplete="offs">
<label><input type="text" name="username"></label>
<button type="submit">提交</button>
</form>
- 我们需要阻止post请求,在index.ts中对method做过滤
if (method!=='GET') {
response.statusCode = 405
response.end();
return;
}
六. 完成任务六: 开启缓存选项
- 发现这次请求和上一次一样就使用缓存,通过Cache-Control做
- 响应成功的请求头加上这句话即可
response.setHeader('Cache-Control', 'public, max-age=31536000')
- 除了首页无法缓存,此时其它的文件都是从内存中读取
七. 对比业界优秀案例
- http-server和node-static
- 坚持维护三个月可以兑换webstorm一年的code