zoukankan      html  css  js  c++  java
  • 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);
  • 相关阅读:
    seaborn可视化NOTE
    快速入门pandas
    protege下载安装使用
    用上Latex实现编辑伪代码
    决策树可视化
    关于时间
    地理三维模型制作
    Python使用记录
    编码格式
    素数生成算法小结
  • 原文地址:https://www.cnblogs.com/lyraLee/p/12185151.html
Copyright © 2011-2022 走看看