• NodeJs 简单的基于 http、url、querystring 模块的服务器项目示例(纯 NodeJs 库,无依赖第三方扩展包,支持跨域)


    不依赖第三方扩展包,支持路由,支持简单的 GET、POST、PUT、DELETE 请求类型。
    只有一个文件:server.js,源码如下:

    // 文件路径:server.js
    // 使用方法:node server.js,浏览器打开:http://127.0.0.1:3000
    
    /**
     * NodeJs 简单的基于 http、url、querystring 模块的服务器项目示例(纯 NodeJs 库,无依赖第三方扩展包)
     */
    const NmHttp = require('http');
    const NmUrl = require('url');
    const NmQueryString = require('querystring');
    // 引入 MD5 加密模块
    const NmCrypto = require('crypto');
    
    // 配置信息
    const host = {
      ip: '127.0.0.1',
      port: 3000
    }
    
    // 简易的路由类
    class Route {
      routes = {};
      getKey(method, url) {
        return NmCrypto.createHash('md5').update(method + url).digest('hex').substring(8, 16);
      }
      hasRoute(method = '', url = '') {
        return typeof (this.routes[this.getKey(method.toUpperCase(), url)]) != 'undefined';
      }
      getRoute(method = '', url = '') {
        return this.routes[this.getKey(method.toUpperCase(), url)];
      }
      getRouteCallBack(method = '', url = '') {
        return this.routes[this.getKey(method.toUpperCase(), url)].cb;
      }
      addRoute(method = '', url = '', cb = null) {
        method = method.toUpperCase();
        this.routes[this.getKey(method, url)] = {
          method: method,
          url: url,
          cb: cb
        };
      }
      get(url, cb) {
        this.addRoute('GET', url, cb);
      }
      post(url, cb) {
        this.addRoute('POST', url, cb);
      }
      put(url, cb) {
        this.addRoute('PUT', url, cb);
      }
      delete(url, cb) {
        this.addRoute('DELETE', url, cb);
      }
      header(url, cb) {
        this.addRoute('HEADER', url, cb);
      }
    }
    let routers = getRouters();
    
    // ===== 核心功能 =====
    
    // 创建服务实例
    const server = NmHttp.createServer((req, res) => {
      // 处理输入请求参数
      // 解析地址。req.url=/,是相对路径,所以要加 baseUrl 参数
      let urlObj = new NmUrl.URL(req.url, 'http://' + host.ip);
      let urlPathName = urlObj.pathname; // 路由路径(?前面的相对路径)
      // 获取 URL 参数对象
      let urlParams = urlObj.searchParams;
      // 获取表单提交的内容
      let reqBody = '';
      req.on('data', function (data) {
        reqBody += data;
      })
      // 用于数据接收完成后再获取
      req.on('end', function () {
        let formParams = NmQueryString.parse(reqBody);
        // 获取请求类型(GET,POST,DELETE...)
        let reqMethod = req.method;
        // 伪装请求类型处理,可以在表单中带 _method 文本域,值可为 GET,POST,PUT,DELETE。
        if (urlParams.has('_method')) {
          reqMethod = urlParams.get('_method');
        }
        if (typeof (formParams['_method']) != 'undefined') {
          reqMethod = formParams['_method'];
        }
        // 返回内容
        let content = {
          status: 0,
          msg: '路由错误 ',
          data: {
            method: reqMethod,
            path: urlPathName
          },
          code: 404
        };
        // 简易路由处理
        if (routers.hasRoute(reqMethod, urlPathName)) {
          content = routers.getRouteCallBack(reqMethod, urlPathName)(urlParams, formParams);
        }
    	// 处理跨域
    	res.setHeader("Access-Control-Allow-Origin", "*");
    	res.setHeader("Access-Control-Allow-Headers", "X-Requested-With");
    	res.setHeader("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
    	res.setHeader("X-Powered-By",' 3.2.1')
        // 处理输出
        if (content.status == 0 && content.code == 404) {
          res.writeHead(404);
          res.end(JSON.stringify(content));
          return;
        }
        res.statusCode = 200;
        switch (typeof (content)) {
          case 'object':
            content = JSON.stringify(content);
            res.setHeader('Content-Type', 'application/json');
            res.setHeader('Content-Length', Buffer.byteLength(content))
            res.end(content)
            break;
          default:
            if (content.indexOf('<') > -1 && content.indexOf('>') > -1) {
              res.setHeader('Content-Type', 'text/html');
            } else {
              res.setHeader('Content-Type', 'text/plain');
            }
            res.setHeader('Content-Length', Buffer.byteLength(content))
            res.end(content);
            break;
        }
      })
    })
    
    // 开始监听
    server.listen(host.port, host.ip, () => {
      console.log(`服务器运行在 http://${host.ip}:${host.port}`);
    })
    
    
    // ===== 业务功能 =====
    
    // 获取路由配置
    function getRouters() {
      let route = new Route();
      // 测试 http://127.0.0.1:3000/test
      route.get('/test',function(urlParams){
    	return {status:1,msg:'测试成功',data:{ts:new Date().getTime()},code:1}  
      })
      // 默认首页
      route.get('/', function (urlParams) {
        return `<!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>演示</title>
        </head>
        <body>
            <h2>演示</h2>
            <form target="_blank">
                编号ID:<input type="number" name="id" value="1" /><br />
                用户名:<input type="text" name="user_name" value="user-001" /><br />
                密码:<input type="password" name="password" value="123456" /><br />
                性别:<input type="radio" name="sex" value="1" checked /> 男 <input type="radio" name="sex" value="2" /> 女<br />
                <hr>
                路由地址:
                <select id="routePicker">
                    <option value="">==请选择==</option>
                    <option value="/user/read" data-method="GET">获取用户信息</option>
                    <option value="/user/save" data-method="POST">新增用户</option>
                    <option value="/user/update" data-method="PUT">更新用户</option>
                    <option value="/user/delete" data-method="DELETE">删除用户</option>
                </select><br />
                <div id="routeInfo">路由信息:</div>
                <hr>
                <input type="hidden" name="_method">
                <button type="submit">提交表单</button> <button type="reset">重置表单</button>
            </form>
            <script>
                let elRouteInfo = document.querySelector('#routeInfo');
                let elRoutePicker = document.querySelector('#routePicker')
                let elForm = document.querySelector('form');
                let elMethod = document.querySelector('input[name="_method"]');
                elRoutePicker.addEventListener('change', function (evt) {
                    let elOption = this.options[this.selectedIndex];
                    elRouteInfo.innerHTML = '方式:' + elOption.dataset.method + ',路径:' + elOption.value;
                    elForm.setAttribute('method', elOption.dataset.method == 'GET' ? 'GET' : 'POST');
                    elForm.setAttribute('action', elOption.value);
                    elMethod.value = elOption.dataset.method;
                })
                elForm.addEventListener('submit', function (evt) {
                    evt.preventDefault();
                    if (!elForm.hasAttribute('method') || !elForm.hasAttribute('action')) {
                        alert('未选择路由地址');
                        return false;
                    }
                    elForm.submit();
                })
            </script>
        </body>
        </html>`;
      })
    
      route.get('/user/read', function (urlParams) {
        let id = urlParams.has('id') ? parseInt(urlParams.get('id')) : 0;
        return {
          id: id,
          user_name: 'user-' + id,
          sex: 0
        };
      })
    
      route.post('/user/save', function (urlParams, formParams) {
        return {
          status: 1,
          msg: '保存成功',
          data: formParams,
          code: 0
        }
      })
    
      route.put('/user/update', function (urlParams, formParams) {
        let id = urlParams.has('id') ? parseInt(urlParams.get('id')) : 0;
        return {
          status: 1,
          msg: '更新成功',
          data: formParams,
          code: 0
        }
      })
    
      route.delete('/user/delete', function (urlParams, formParams) {
        let id = urlParams.has('id') ? urlParams.get('id') : null;
        if (id < 1 && typeof (formParams.id) != 'undefined') {
          id = formParams.id;
        }
        if (!id) {
          return {
            status: 0,
            msg: '编号无效',
            data: null,
            code: 0
          }
        }
        return {
          status: 1,
          msg: '删除成功',
          data: {
            id: id
          },
          code: 0
        }
      })
    
      return route;
    }
    

    运行:

    node server.js
    

    在浏览器打开如下URL

    http://127.0.0.1:3000
    

    界面效果:
    默认首页界面

  • 相关阅读:
    Scala教程之:静态类型
    java运行时跟编译时的区别,欢迎大家指正
    循环者的诅咒
    Python分支结构与流程控制
    底层剖析Python深浅拷贝
    I/O格式化与运算符
    详解Python垃圾回收机制
    LeetCode29 Medium 不用除号实现快速除法
    详解SkipList跳跃链表【含代码】
    高等数学——讲透微分中值定理
  • 原文地址:https://www.cnblogs.com/sochishun/p/14298940.html
Copyright © 2020-2023  润新知