1.server 对象创建,通过http模块创建server对象,这里我们对请求的路径未做区分,只是单纯的返回当前的请求地址
let http = require('http');
class staticServer{
constructor(){
this.port = 8080;
}
useServer(){
http.createServer((req,res)=>{
res.end(`The current request address is : ${req.url}`)
}).listen(this.port,()=>{
console.log(`Server started on port ${this.port}`)
})
}
}
module.exports = staticServer;
当请求地址为:http://localhost:8080/index.html时,页面返回为:
2.下面我们对路径进行区分,即当请求对应的文件路径时,如果文件存在则返回对应的静态文件,如果请求静态文件不存在,那么返回"404"
- 这里用的是流的形式createReadStream
而不是readFile
,是因为后者会在得到完整文件内容之前将其先读到内存里。这样万一文件很大,再遇上多个请求同时访问,readFile
就承受不来了。使用文件可读流,服务端不用等到数据完全加载到内存再发回给客户端,而是一边读一边发送分块响应
class staticServer{
constructor(){
this.port = 8080;
this.rootPath = './public';
}
// 404响应
respondNotFound(pathname,res){
res.statusCode = '404';
res.end(`${pathname} is not found~~`);
}
// 用于返回文件的内容
respondFile(filename,res){
res.setHeader('Content-type','text/html');
fs.createReadStream(filename).pipe(res);
}
useServer(){
http.createServer((req,res)=>{
let pathname = url.parse(req.url,true).pathname;
let filename = this.rootPath+pathname;
if (!fs.existsSync(filename)){
this.respondNotFound(pathname,res);
}else{
this.respondFile(filename,res);
}
}).listen(this.port,()=>{
console.log(`Server started on port ${this.port}`)
})
}
}
3.此时进行请求,我们通过响应头,看到不论是css亦或是图片的网络文件的类型都是"text/html",这是由于我们在respondFile函数中设置了"Content-type"一致为"text/html",这样就导致了除了text/html类型的文件无法正常查看
- 为了解决上述的问题,需要对不同的文件类型设置不同的"Content-type",这里我们采用node自带的mime模块来响应不同文件类型的请求,更改respondFile函数如下:
// 用于返回文件的内容
respondFile(filename,res){
res.setHeader('Content-type',`${mime.getType(filename)};charset=utf-8`);
fs.createReadStream(filename).pipe(res);
}
- 此时我们再看文件的"Content-type"就会是其文件对应的"Content-type":
4.在上面的代码中,我们请求的地址一直是某一个具体的文件,例如http://localhost:8080/index.html这样的url,如果我们请求的地址为http://localhost:8080,那么就会发生如下报错:
- 为了解决这个问题,我们在对非文件进行请求时,即对目录文件进行请求时,默认返回请求目录下的index.html,如果index.html不存在的话,那么返回这个目录下的所有文件。首先我们先默认返回请求目录下的index.html
fs.stat(filename,(err,stats)=>{
if (err) return console.log(err);
if (stats.isFile()){ // 如果是文件的话,则返回文件内容
this.respondFile(filename,res);
}else if (stats.isDirectory()){ // 如果不是文件的话,则执行respondDirectory
this.reapondDiretory(filename,res);
}
});
- reapondDiretory如下:
// 用于返回当路径为目录时的内容
reapondDiretory(filename,res){
let p = filename+'index.html';
if (fs.existsSync(p)){
this.respondFile(p,res);
}
}
- 此时如果当前目录下并没有index.html的话,那么则返回目录下的所有 文件,代码如下:
// 用于返回当路径为目录时的内容
reapondDiretory(filename,res,req){
let p = filename+'index.html';
if (fs.existsSync(p)){
this.respondFile(p,res);
}else{
fs.readdir(filename,(err,files)=>{
if (err) return console.log(err);
let str = '<ul>';
files.forEach((file,index)=>{
let itemLink = req.url+'/'+file;
let stats = fs.statSync(path.join(filename,file));
str += `<li><a href="${itemLink}">${itemLink}</a></li>`;
});
str += '</ul>';
res.setHeader('Content-type','text/html;charset=utf-8');
res.end(str);
})
}
}
5.以上就是使用node搭建的简单的静态服务器,完整代码如下:
let http = require('http');
let url = require('url');
let fs = require('fs');
let path = require('path');
let mime = require('mime');
class staticServer{
constructor(){
this.port = 8080;
this.rootPath = './public';
}
// 404响应
respondNotFound(pathname,res){
res.statusCode = '404';
res.end(`${pathname} is not found~~`);
}
// 用于返回文件的内容
respondFile(filename,res){
res.setHeader('Content-type',`${mime.getType(filename)};charset=utf-8`);
let rs = fs.createReadStream(filename);
rs.pipe(res);
}
// 用于返回当路径为目录时的内容
reapondDiretory(filename,res,req){
let p = filename+'index.html';
if (fs.existsSync(p)){
this.respondFile(p,res);
}else{
fs.readdir(filename,(err,files)=>{
if (err) return console.log(err);
let str = '<ul>';
files.forEach((file,index)=>{
let itemLink = req.url+'/'+file;
let stats = fs.statSync(path.join(filename,file));
str += `<li><a href="${itemLink}">${itemLink}</a></li>`;
});
str += '</ul>';
res.setHeader('Content-type','text/html;charset=utf-8');
res.end(str);
})
}
}
useServer(){
http.createServer((req,res)=>{
let pathname = url.parse(req.url,true).pathname;
let filename = this.rootPath+pathname;
if (!fs.existsSync(filename)){
this.respondNotFound(pathname,res);
}else{
fs.stat(filename,(err,stats)=>{
if (err) return console.log(err);
if (stats.isFile()){
this.respondFile(filename,res);
}else if (stats.isDirectory()){
this.reapondDiretory(filename,res,req);
}
});
}
}).listen(this.port,()=>{
console.log(`Server started on port ${this.port}`)
})
}
}
module.exports = staticServer;
文章参考:使用Node.js搭建静态资源服务器