如何用Node去写一个Web应用框架

第一步,用node输出一个hello world


  1. var http=require('http'); 
  2. http.createServer(function(req,res){ 
  3.     var urlPares=url.parse(req.url); 
  4.     var query=querystring.parse(urlPares.query); 
  5.     res.end('hello world'); 
  6. }).listen(80); 

大部分的node教程在这里会告诉你,我们很容易的建立的一个服务器。但是在实际使我们通常使用的是express.(f**k,难道Node必须要用express吗?自己实现一个Web应用框架真的很难吗?)其实并不是。

那么既然打算自己写我们首先要知道我们要做哪些事情。 1.路由或者智能路由 2.静态文件输出 3.session/cookie 4.模版渲染 5.数据库处理 6.文件上传

第二步,路由

路由好高大上的名字,它是干啥的?url对应具体方法就是它该做的事情。 那么我们为什么不让url对应xxx文件的xx方法。 例如:/user/login能不能自动对应到user.js的login方法上。实现起来很难么?其实只需要几句代码


  1. var fs = require("fs"); 
  2. module.exports=function(req,res){ 
  3.     var query=req.query; 
  4.     var urlPares=req.urlPares; 
  5.     var pathname=urlPares.pathname; 
  6.     var arr=pathname.split("/"); 
  7.     req.arr=arr; 
  8.     //start 这段代码处理默认行为。可以先忽略 
  9.     if(arr.length==0||arr.length==1){ 
  10.         arr=["","index","index"]; 
  11.     }else if(arr.length==2){ 
  12.         arr.push("index"); 
  13.     } 
  14.     if(arr[1]==""){ 
  15.         arr[1]="index"; 
  16.     } 
  17.     if(arr[2]==""){ 
  18.         arr[2]="index"; 
  19.     } 
  20.     //end 这段代码处理默认行为。可以先忽略 
  21.     if (fs.existsSync(APP_PATH+'/controller/'+arr[1]+'.js')){ 
  22.         var controller=require('./controller/'+arr[1]); 
  23.         if(controller[arr[2]]){ 
  24.             controller[arr[2]](req,res); 
  25.         }else{ 
  26.             res.writeHead(404,{'Content-Type': 'text/plain' }); 
  27.             res.end("你访问的控制器不存在指定方法"); 
  28.         } 
  29.     }else{ 
  30.         res.writeHead(404,{'Content-Type': 'text/plain' }); 
  31.         res.end("你访问的路径不存在"); 
  32.     } 

通过fs判断文件是否存在。然后去require它就行了。APP_PATH是个全局变量表示程序入口的路径。

第三步,静态文件输出

静态文件输出我们需要一个库MIME


  1. var url = require("url"); 
  2. var fs = require("fs"); 
  3. var mime = require('mime'); 
  4. /** 
  5.  * [[检测是否为静态资源]] 
  6.  * @param   {Object}   req [[Description]] 
  7.  * @param   {[[Type]]} res [[Description]] 
  8.  * @returns {bool} [[Description]] 
  9.  */ 
  10. module.exports = function (req, res) { 
  11.     //正则表达式检测文件后缀 
  12.     var url_resource_reg = /.*\.(html|htm|gif|jpg|jpeg|bmp|webp|htc|swf|png|ico|txt|js|css)/; 
  13.     if (!url_resource_reg.test(req.url)) { 
  14.         return false; 
  15.     } 
  16.     var urlPares = url.parse(req.url); 
  17.     var pathname = urlPares.pathname; 
  18.     var fileUrl = APP_PATH + "/static" + pathname; 
  19.  
  20.     if (fs.existsSync(fileUrl)) { 
  21.         var contentType = mime.lookup(fileUrl); 
  22.         res.setHeader('Content-Type', contentType || "text/plain"); 
  23.  
  24.         var fileStream = fs.createReadStream(fileUrl); 
  25.         fileStream.pipe(res); 
  26.         fileStream.on('end', function () { 
  27.             res.end(); 
  28.         }); 
  29.         return true; 
  30.     } else { 
  31.         return false; 
  32.     } 

第四步,session/cookie

这里稍微有点。但是代码量也不多


  1. var sessions = {}; 
  2. var sessionKey = 'session_key'; 
  3. var EXPIRES = 30 * 60 * 1000; 
  4. function randString(size) { 
  5.     var result = ''; 
  6.     var allChar = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; 
  7.     size = size || 1; 
  8.     while (size--) { 
  9.         result += allChar.charAt(rand(0, allChar.length - 1)); 
  10.     } 
  11.     return result; 
  12. var generate = function () { 
  13.     var session = {}; 
  14.     session.id = Date.now() + randString(12); 
  15.     session.cookies = { 
  16.         expire: Date.now() + EXPIRES 
  17.     } 
  18.     sessions[session.id] = session; 
  19.     return session; 
  20. var parseCookie= function (cookie) { 
  21.     var cookies = {}; 
  22.     if (!cookie) { 
  23.         return cookies; 
  24.     } 
  25.     var list = cookie.split(";"); 
  26.     for (var i = 0; i < list.length; i++) { 
  27.         var pair = list[i].split("="); 
  28.         cookies[pair[0].trim()] = pair[1]; 
  29.     } 
  30.     return cookies; 
  31. var serializeCookies = function (cookies) { 
  32.     var arr = []; 
  33.     for (var key in cookies) { 
  34.         arr.push(serialize(key, cookies[key])); 
  35.     } 
  36.     return arr; 
  37. var serialize = function (name, value, option) { 
  38.     var pairs = [name + '=' + encodeURI(value)]; 
  39.     //设置cookie默认共用"/"路径 
  40.     option = option || { 
  41.         path: "/" 
  42.     }; 
  43.     if (option.maxAge) pairs.push('Max-Age=' + option.maxAge); 
  44.     if (option.domain) pairs.push('Domain=' + option.domain); 
  45.     if (option.path) pairs.push('Path=' + option.path); 
  46.     if (option.expires) pairs.push('Expires=' + option.expires); 
  47.     if (option.httpOnly) pairs.push('HttpOnly'); 
  48.     if (option.secure) pairs.push('Secure'); 
  49.     return pairs.join('; '); 
  50. module.exports = function (req, res) { 
  51.     req.cookies = parseCookie(req.headers.cookie); 
  52.     var id = req.cookies[sessionKey]; 
  53.     if (!id) { 
  54.         req.session = generate(); 
  55.     } else { 
  56.         var session = sessions[id]; 
  57.         if (session) { 
  58.             if (session.cookies.expire > Date.now()) { 
  59.                 session.cookies.expire = Date.now() + EXPIRES; 
  60.                 req.session = session; 
  61.             } else { 
  62.                 delete sessions[id]; 
  63.                 req.session = generate(); 
  64.             } 
  65.         } else { 
  66.             req.session = generate(); 
  67.         } 
  68.     } 
  69.     for (var key in sessions) { 
  70.         if (sessions[key].cookies.expire < Date.now()) { 
  71.             delete sessions[key]; 
  72.         } 
  73.     } 
  74.     var writeHead = res.writeHead; 
  75.     res.writeHead = function () { 
  76.         delete req.cookies[ham_sessionKey]; 
  77.         var sessionStr = serialize(ham_sessionKey, req.session.id); 
  78.         res.setHeader('Set-Cookie', serializeCookies(req.cookies).concat(sessionStr)); 
  79.         return writeHead.apply(res, arguments); 
  80.     } 

第五步,模版渲染

这是最简单的。因为我用https://github.com/aui/artTemplate ,自己用自己喜欢的模块组件就行了

第六步,数据库处理

这里可以是用一些ORM框架。例如https://github.com/dresende/node-sql-query

第七步,文件上传,post

这里只需要一个组件https://github.com/felixge/node-formidable

第八步,就是你把上面的代码组织起来。

可以参考我的实现 https://coding.net/u/as3long/p/today/git/tree/master/node_modules/ham 代码比较乱,见谅。

来源:51CTO

时间: 2024-09-20 11:32:55

如何用Node去写一个Web应用框架的相关文章

c语言-如何用C语言写一个暴力破解SSH的程序

问题描述 如何用C语言写一个暴力破解SSH的程序 也就是用同文件夹里的一个字典,可以用fopen和fgets把密码一条一条打开,可是我不知道怎么在C语言里对一个其他地址进行SSH 求大神解答 解决方案 C语言没有 SSH 的功能,所以需要你去自己搞 SSH 算法. 解决方案二: 参考openssh,这个是开源的,可以用它来调用,连接http://www.openssh.com/

自己想写一个轻量级的框架 请问大神thinkphp中的common模块是怎样实现的

问题描述 自己想写一个轻量级的框架 请问大神thinkphp中的common模块是怎样实现的 就是我现在有很多的函数 怎样能像放在thinkphp中的common中的function和config中自动调用 求实现方法和原理 最好有代码 在此谢谢了

如何用node.js实现一个简单的web服务器

node.js实现web服务器还是比较简单的,我了解node.js是从<node入门>开始的,如果你不了解node.js也可以看看! 我根据那书一步一步的练习完了,也的确大概了解了node.js,不过里面写的路由的地方总感觉不方便,十一放假最后一天,试着写了个简单的web服务器,现在分享记录于此! http模块已提供了基本功能,所以我主要解决两个问题,1是静态资源的处理,2是动态资源的路由. 静态资源在node.js里的意思是不变的,如图片.前端js.css.html页面等. 动态资源我们一般

AST解析基础: 如何写一个简单的html语法分析库

前言 虚拟语法树(Abstract Syntax Tree, AST)是解释器/编译器进行语法分析的基础, 也是众多前端编译工具的基础工具, 比如webpack, postcss, less等. 对于ECMAScript, 由于前端轮子众多, 人力过于充足, 早已经被人们玩腻了. 光是语法分析器就有 uglify , acorn , bablyon , typescript , esprima 等等若干种. 并且也有了AST的社区标准: ESTree. 这篇文章主要介绍如何去写一个AST解析器,

如何写一个框架(转)

  说明:作者也没写过什么框架,只是分享一些自己的理解,抛砖引玉罢了.如果你写过一些框架可能会产生一些共鸣欢迎讨论,如果你正在写或正打算写一个框架可能会给你一些启发.本文以为较长可能会分多个篇博客来写,现在能想到的是主要分为步骤.模式两部分.如果你觉得好,按一个推荐举手之劳让更多的人可以看到.   步骤   定位   所谓定位就是回答几个问题,我出于什么目的要写一个框架,我的这个框架是干什么的,有什么特性适用于什么场景,我的这个框架的用户对象是谁,他们会怎么使用,框架由谁维护将来怎么发展等等.

写一个通用的代码生成器

       代码生成器对于JAVA码农来说并不陌生.在一些业务性比较强,但编码比较规范的项目中,往往会有大量的重复或者类似的代码要写.比如对表的增删改查,比如生成用于远程调用的客户端方法存根等等.面对这种情况,程序员通常的做法就是拿一个现成模块的代码copy过来再改改.于是,为了避免这种低效而容易出错的编码方式,诞生了各种各样的能跟据当前项目特证自动生成代码的代码生成器程序.这种程序的本质上就是将大量重复的复制修改工作用程序自动来做,以便自动产生适合自己项目的代码.        然而,这种代

本人要做一个视频教学的系统,由于要控制视频,自己用Flex写一个播放器靠谱吗?

问题描述 本人没有Flex的基础听说挺容易入门的现在我这个系统由于要对视频做一些控制需要视频的源代码于是想到自己去写一个不知道这样靠谱不靠谱大家给出出主意谢谢! 解决方案 解决方案二:大家给出出主意啊有点急!解决方案三:本人也想告诉你呀没办法偶太菜了!解决方案四:引用2楼qiuyujiaoqiuyulong的回复: 本人也想告诉你呀没办法偶太菜了! 额..同为菜鸟可以互相交流呀解决方案五:有人对这方面有研究的吗能不能给指点一下如果这样靠谱的话那我就不在网上乱找开源播放器了(找了很多,有些看不懂,

日期时间-如何写一个jar,完全用CPU计算出来的当前时间,为其他程序提供服务

问题描述 如何写一个jar,完全用CPU计算出来的当前时间,为其他程序提供服务 各位大神早上好,有个问题现在没眉目,现在有个需求,自己去写一个jar,计算出当前日期时间,就是完全用CPU计算出的时间,然后根据时钟来进行校准.为其他程序提供服务.而不是去获取当前系统的时间,因为系统的时间是容易被改掉的.求解. 解决方案 时间还能直接计算出来?活了这么大还第一次听说.你确认你睡醒了么?昨晚喝多了? 解决方案二: ntp是联网获得,你说"完全用CPU计算",这是一回事么?

SPWebServer:一个基于 SPServer 的 web 服务器框架

看到这个题目,估计很多人会问:为什么要再实现一个 web 服务器? 这里有几个原因: 1.这是一个 web 服务器框架,不是一个完整的 web 服务器.也就是说 SPWebServer 提供的是一套 API 和类库,可以方便地集成到现有的应用程序中.可以称 SPWebServer 为 embedded web server . 2.有些时候,我们需要的不是一个功能强大完整的 web 服务器(例如 apache ),我们只是需要一个能提供最基本的 http 功能的服务器框架.比如要用 C/C++