node-http实现服务(静态+动态)

http服务端有两种功能:

1. 提供静态服务 html /css 等

2. 提供动态数据服务

1. 浏览器请求示例

<!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>
  <!--服务器端不识别相对路径'../',默认/1.css-->
  <link href="../1.css" rel="stylesheet" />
</head>
<body>
  <script>
    // 在5000端口下启动
    const xhr = new XMLHttpRequest();
    //PUT非简单请求;会发送OPTIONS请求
    xhr.open('PUT', 'http://localhost:3000/userList', true);
    document.cookie = "token=20190993339" 
    xhr.withCredentials = true; //跨域携带cookie
    xhr.responseType = 'application/json';// 非简单请求
    xhr.onreadystatechange = function() {
      if(xhr.status === 200 && xhr.readyState === 4) {
        console.log(JSON.parse(xhr.response));
      }
    }
    xhr.send();
  </script>
</body>
</html>

2. 回调函数实现服务

let http = require('http');
let url = require('url');
let fs = require('fs');
let path = require('path');
// 上面都是核心内置模块
let mime = require('mime'); //第三方模块

// 回调函数实现服务
let server = http.createServer(function(req, res) {
  const { pathname } = url.parse(req.url);
  const method = req.method.toLowerCase();
  //处理动态数据
  switch(pathname) {
    case '/userList': 
      if(method === 'get') {
        res.setHeader('Content-Type', 'application/json');
        res.end(JSON.stringify({name: 'lyra'}));
        return;
      }
  }
  // 判断路径对应的是文件还是文件夹
  let absolutePath = path.join(__dirname, pathname);
  fs.stat(absolutePath, function(err, statObj) {
    if(err) {
      res.statusCode = 404;
      res.end('Not Found');
      return;// 结束
    }
    if (statObj.isFile()) {// 是文件则直接读取返回对应路径下文件
      const rs = fs.createReadStream(absolutePath);
      // 设置返回的响应头Content-Type
      res.setHeader('Content-Type', mime.getType(absolutePath)+";charset=utf-8");
      rs.pipe(res); //包含 res.end(...)逻辑
    } else {// 是文件夹;默认查找index.html
      const indexPath = path.join(absolutePath, 'index.html');
      fs.access(indexPath, function(err) {
        if(err) {
          res.statusCode = 404;
          res.end('Not Found');
          return;// 结束
        }
        res.setHeader('Content-Type', 'text/html;charset=utf-8');// utf-8中间要有间隔符,IE兼容
        fs.createReadStream(indexPath).pipe(res);
      })
    }
  })
});

server.listen(3000);

3. aysnc...await封装

使用第三方的mz/fs模块,该模块下文件处理Promise化。

let http = require('http');
let url = require('url');
let fs = require('mz/fs');
let path = require('path');
// 上面都是核心内置模块
let mime = require('mime'); //第三方模块

class Server {
  constructor() {
    this.handleRequest = this.handleRequest.bind(this);
  }
  async handleRequest(req, res) {
    const { pathname } = url.parse(req.url, true);
    //处理动态数据
    this.handleDataRequest(pathname,req, res);
    const absPath = path.join(__dirname, pathname);
    try {
      // 处理静态文件
      let statObj = await fs.stat(absPath);     
      if (statObj.isFile()) {
        this.sendFile(res, absPath);
      } else {
        const realpath = path.join(absPath, 'index.html');
        await fs.access(realpath);
        this.sendFile(res, realpath);
      } 
    } catch(e) {
      console.log(e);
      this.sendError(res);
    }
  }
  handleDataRequest(dataPath,req, res) {
    const method = req.method.toLowerCase();
    /*************************跨域的通用解决方案***********************************/
    res.setHeader('Access-Control-Allow-Origin', 'http://localhost:5000');
    res.setHeader('Access-Control-Allow-Credentials', true);
    res.setHeader('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET,OPTIONS,HEAD');
    res.setHeader('Access-Control-Allow-Headers', "Content-Type");
    res.setHeader('Access-Control-Max-Age', 10000); //s
    // options请求不做处理
    if(method === 'options') {
      res.end();// 可访问
    }
    /****************************************************************************/
    //处理动态数据
    switch(dataPath) {
      case '/userList': 
        if(method === 'get') {
          res.setHeader('Content-Type', 'application/json');
          res.end(JSON.stringify({name: 'lyra'}));
        }
        if(method === 'put') {

        }
    }
  }
  sendFile(res, realpath) {
    res.setHeader('Content-Type', mime.getType(realpath)+";charset=utf-8")
    fs.createReadStream(realpath).pipe(res);
  }
  sendError(res) {
    res.statusCode = 404;
    res.end('Not Found');
    return;
  }
  start(port) {
    let server = http.createServer(this.handleRequest);
    server.listen(port);
  }
}

let server = new Server();
server.start(3000);
posted @ 2020-01-12 22:55  Lyra李  阅读(353)  评论(0编辑  收藏  举报