`---
主题列表:juejin, github, smartblue, cyanosis, channing-cyan, fancy, hydrogen, condensed-night-purple, greenwillow, v-green, vue-pro, healer-readable, mk-cute, jzman, geek-black, awesome-green
贡献主题:github.com/xitu/juejin…
theme: juejin highlight:
前面一篇文章大概了解了http模块的基本框架。接下来深入了解:
1. 如何根据不同的url请求不同的文件
这是我们目前的目录结构。在public中的三个文件,需要被请求。而且html引用了css和js。
import * as http from 'http';
import {IncomingMessage, ServerResponse} from 'http';
import * as fs from 'fs';
import * as path from 'path';
import * as url from 'url';
const server=http.createServer()
server.on('request',(request: IncomingMessage,response:ServerResponse)=>{
const publicDir=path.resolve(__dirname,'public')
const {url:myUrl}=request
console.log(myUrl);
const {pathname}=url.parse(myUrl)
switch(pathname){
case '/index.html':
response.setHeader('Content-Type','text/html;charset=utf-8')
fs.readFile(path.resolve(publicDir,'index.html'),(err,data)=>{
if(err) throw err;
response.end(data.toString())
})
break;
case '/style.css':
response.setHeader('Content-Type','text/css;charset=utf-8')
fs.readFile(path.resolve(publicDir,'style.css'),(err,data)=>{
if(err) throw err;
response.end(data.toString())
})
break;
case '/main.js':
response.setHeader('Content-Type','text/javascript;charset=utf-8')
fs.readFile(path.resolve(publicDir,'main.js'),(err,data)=>{
if(err) throw err;
response.end(data.toString())
})
break;
default:
response.statusCode=404
response.end('Not Found')
}
})
server.listen(8888)
当然首先必须监听server的request事件,在回调里,可以通过request对象的url
属性,获取请求的路径。比如如果我在浏览器输入http://localhost:8888/index.html
那request.url === /index.html
所以通过条件判断request.url
分情况返回不同的文件内容:
- 首先文件的类型各有不同,通过
response.setHeader
设置文件类型。 - 怎么获取文件里的内容并且响应回去呢?首先要读文件内容:这里用到了另一个模块
fs
文件模块。fs.readFile
的第一个参数是文件路径,第二个参数是回调:接受err和data,这个data是buffer类型的。所以我们拿到了文件内容,使用response.end
返回。
fs
模块是文件系统,用于与文件系统进行交互。
找路径的时候用到了另一个模块path
,用于处理文件和目录的路径。path.resolve()
用于将多个路径序列合并成绝对路径,因为我们不确定路径连接用/还是\,所以用resolve连接很方便。
node中的__dirname
变量表示当前文件所在的目录的绝对路径
2. 请求url中有查询参数怎么办
如果我在浏览器输入http://localhost:8888/index.html
那request.url === /index.html
这没有问题。但是如果我带了查询参数呢?http://localhost:8888/index.html?age=18
发现此时request.url === /index.html?age=18
怎么获取干净纯粹的文件路径呢?
用到了url
模块:用于处理与解析 URL
url.parse(myUrl)
myUrl就是request.url ,也就是/index.html?age=18
这样一段字符串。得到一个对象:可以看到这个对象有个pathname
属性,就是我们想要的
3. webstorm中将目录设置为根目录的使用
这是目前的目录结构。写了一个404.html,作为404页面,当用户请求的路径不存在,就显示它。在404.html里,用了一张图片:
<body>
<h1>你要找的页面不存在</h1>
<p>
<img src="./images/404.png" alt="">
</p>
</body>
使用相对路径设置src属性。
// index.ts
fs.readFile(path.resolve(publicDir,filename),(err,data)=>{
if(err){
if(err.errno===-4058){
response.statusCode=404
fs.readFile(path.resolve(publicDir,'404.html'),(err,data)=>{
response.end(data)
})
}else{
response.statusCode=500
response.end('服务器繁忙')
}
}else{
response.end(data)
}
})
在node运行的文件index.ts里,如果错误码是-4058,就是用户请求的路径不存在,就返回404.html
。
如果我请求:http://localhost:8888/x.html
明显路径不存在,此时页面会正确显示404及图片。
但是如果请求的路径里又多了一层目录,比如:http://localhost:8888/xxx/x.html
发现图片显示不了!我们打开Network,发现对404.png的请求路径变成了目录xxx
里的images/404.png
。但是images/404.png
明明是在public
目录里啊!
这是因为src写的是相对路径:<img src="./images/404.png" alt="">
所以当我多加了一层目录xxx
,就会请求xxx/images/404.png
写绝对路径就好了<img src="/images/404.png" alt="">
然后再把目录public
变成/
也就是当前的根目录:鼠标移到public,右键,Mark Directory as
Resource Root
之后不管我请求多少个目录里的不存在路径,404.png的请求src就永远是public里的images/404.png