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);
  • 相关阅读:
    命令拷屏之网络工具
    PHP 设计模式 笔记与总结(1)命名空间 与 类的自动载入
    Java实现 计蒜客 1251 仙岛求药
    Java实现 计蒜客 1251 仙岛求药
    Java实现 计蒜客 1251 仙岛求药
    Java实现 蓝桥杯 算法训练 字符串合并
    Java实现 蓝桥杯 算法训练 字符串合并
    Java实现 蓝桥杯 算法训练 字符串合并
    Java实现 LeetCode 143 重排链表
    Java实现 LeetCode 143 重排链表
  • 原文地址:https://www.cnblogs.com/lyraLee/p/12185151.html
Copyright © 2011-2022 走看看