初涉Node:搭建一个简单的node服务器

2018-04-21  本文已影响10人  DHFE

文件路径示意:

C:\Users\Administrator\我的文档\HBuilderProject\httpServer


httpServer:
│  app.js
│  
└─HS\
    │  httpServer.html   // 主页面
    │  
    ├─css
    │      test.css
    │      
    ├─imgs
    │      img.jpg 
    │      
    └─js
            test.js        

静态资源内容:

httpServer.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <link rel="stylesheet" href="css/test.css">
</head>
<body>
    <h1>Hello World!</h1>
    <img src="imgs/img.jpg">
</body>
<script src="js/test.js"></script>
</html>
</html>

test.css

h1 {
    color: skyblue;
}

test.js

alert("sss");

img
一张图


静态服务器实现大致思路:

浏览器发送URL,服务端解析URL,对应到硬盘上的文件。如果文件存在,返回200状态码,并发送文件到浏览器端;如果文件不存在,返回404状态码,发送一个404的文件到浏览器端。

app.js
var http = require('http')
var path = require('path')
var fs = require('fs')
var url = require('url')

function staticRoot(staticPath, req, res) {

  console.log("staticPath: " + staticPath);

  console.log("req.url: " + req.url);           // 查看请求URL
  var pathObj = url.parse(req.url, true);
  console.log(pathObj);                         // 使用URL模块的功能函数解析请求URL,得到相关对象

  if (pathObj.pathname === '/') {
    pathObj.pathname += 'httpServer.html'
  }

  var filePath = path.join(staticPath, pathObj.pathname);         // 拼装为各资源文件绝对路径
  // c:\Users\Administrator\我的文档\HBuilderProject\httpServer\HS + ['httpServer.html','/css/test.css','/imgs/img.jpg','/js/test.js']
  console.log("filePath: " + filePath);

  
  fs.readFile(filePath, 'binary', function (err, fileContent) {  
    if (err) {
      console.log('404')
      res.writeHead(404, 'not found')
      res.end('<h1>404 Not Found</h1>')
    } else {
      console.log('ok');
      res.writeHead(200, 'OK');
      res.write(fileContent, 'binary');
      res.end();
    }
  });
  

  console.log("\n");
}

var server = http.createServer(function (req, res) {
  staticRoot(path.join(__dirname, 'HS'), req, res);             // 将其组装成资源文件夹路径
  // c:\Users\Administrator\我的文档\HBuilderProject\httpServer\ + HS
})
server.listen(8080);
console.log('visit http://localhost:8080');

访问localhost:8080,将会进入createServer函数,参数req res包括了浏览器的请求信息和响应信息(head),我们用一个staticRoot函数来接受并处理后续内容。

参数__dirname为app.js所在绝对路径的文件夹。
c:\Users\Administrator\我的文档\HBuilderProject\httpServer
使用join()方法,拼接静态资源内容所在文件夹。
// c:\Users\Administrator\我的文档\HBuilderProject\httpServer\HS

此时,本地服务器便可根据绝对路径找到相关静态文件,发送出去。

接下来需要解析请求URL。
console.log("req.url: " + req.url);
在我们传入staticRoot函数中的req对象包含了许多请求信息,如User-Agent、cookie、accept、host、method.........

QQ截图20180421171034.jpg

url.parse()可以将一个完整的URL地址,分为很多部分,常用的有:host、port、pathname、path、query。

var pathObj = url.parse(req.url, true);

我们可以从req对象里得到用户的请求URL,其实就是文件的路径。

每一次请求的pathObj如下:

'/httpServer.html' '/css/test.css' '/imgs/img.jpg' '/js/test.js'
var filePath = path.join(staticPath, pathObj.pathname);

拼接为绝对路径。

请求URL:
c:\Users\Administrator\我的文档\HBuilderProject\httpServer\HS\httpServer.html
c:\Users\Administrator\我的文档\HBuilderProject\httpServer\HS\css\test.css
c:\Users\Administrator\我的文档\HBuilderProject\httpServer\HS\imgs\img.jpg
c:\Users\Administrator\我的文档\HBuilderProject\httpServer\HS\js\test.js

进入下面的函数。

  fs.readFile(filePath, 'binary', function (err, fileContent) {   // 这个函数只执行了一次
    test++;
    if (err) {
      console.log('404')
      res.writeHead(404, 'not found')
      res.end('<h1>404 Not Found</h1>')
    } else {
      console.log('ok');
      res.writeHead(200, 'OK');
      res.write(fileContent, 'binary');
      res.end();
    }
  });

关于fs模块:

Node.js 文件系统
Node.js——文件系统模块

异步读取时,传入的回调函数接收两个参数,当正常读取时,err参数为nullfileContent参数为读取到的String。当读取发生错误时,err参数代表一个错误对象,fileContentundefined。这也是Node.js标准的回调函数:第一个参数代表错误信息,第二个参数代表结果。

res.writeHead()

向请求的客户端发送响应头。
该函数在一个请求内最多只能调用一次,如果不调用,则会自动生成一个响应头。

response.writeHead(statusCode, [reasonPhrase], [headers])
// statusCode:响应头的状态码,如:200、404等
// reasonPhase:[可选],用于简单说明的字符串。比如:“服务器因为维护暂时无法正常访问....”
// headers:类似关联数组的对象,表示响应头的每个属性
res.write()

向请求的客户端发送响应内容。
在 response.end() 之前,response.write() 可以被执行多次。

response.write(chunk, [encoding])
// chunk:一个buffer 或 字符串,表示发送的内容
// encoding:如果chunk是字符串,就需要指定encoding来说明它的编码方式,默认utf-8
res.end()

结束响应,告诉客户端所有消息已经发送。当所有要返回的内容发送完毕时,该函数必须被调用一次。
如何不调用该函数,客户端将永远处于等待状态

response.end([data], [encoding])
// data:end()执行完毕后要输出的字符,如果指定了 data 的值,那就意味着在执行完 response.end() 之后,会接着执行一条 response.write(data , encoding);
// encoding:对应data的字符编码

所有资源读取返回客户端后,将先弹出对话框,然后显示页面。

上一篇下一篇

猜你喜欢

热点阅读