2012
Aug
19

第一篇,Node.js 串 Apache CGI

Node.js 接到从 Aapache CGI 的 Request 过来后,会把所有的 Header 参数都存到 process.env , 其中包含 NODE_PATH 、HTTP_HOST,HTTP_USER_AGENT,HTTP_ACCEPT、REQUEST_METHOD、QUERY_STRING...等

这篇主要目的是处理 GET 、 POST 、 COOKIE 、File Upload 这四种 HTTP Protocol 讯息传输的方式。

GET Param

GET 的参数会存在 process.env.QUERY_STRING,像这样「 QUERY_STRING: 'account=test'」,所以只要将 QUERY_STRING 的内容做切割,就能够很轻易的取出参数。

Get参数处理
  1. o.getGET = function (p) {/*{{{*/
  2. var q = p.env.QUERY_STRING;
  3. if(!q){return ;}
  4. var g = q.split(/&(?=[a-z])/);
  5.  
  6. var get = {};
  7. var reg = /([^=]+)=(.+)/i,t;
  8. var n = g.length;
  9. for(var i=0 ;i<n ;i++) {
  10. t = g[i].match(reg);
  11. if(t && t.length==3)
  12. get[t[1]] = t[2];
  13. }
  14. this.GET = get;
  15. }/*}}}*/
  16.  

POST Param

POST 的参数比起 GET 会比较复杂一点,POST 传递的参数长度是没有限制,所以不能够存在任何的变数中,否则会造成 buffer 溢出,会有安全上的疑虑,而 POST 的内容会存在 input buffer 中,必须透过读取 buffer 的方式来操作。

透过读取 /dev/stdin 的方式,将 input buffer 的资料读进来「fs.readFileSync('/dev/stdin')」。

读到 POST 的资料后,跟 GET 一样使用 Regular Exp 的方式,将参数切割出来,存在 this.POST。

POST 参数处理
  1. /** param by method post**/
  2. o.getPOST = function(buff) {/*{{{*/
  3. if (!buff){return ; }
  4.  
  5. var g = buff.split(/&(?=[a-z])/);
  6.  
  7. var get = {};
  8. var reg = /([a-z0-9_\-]+)=(.+)/i,t;
  9. var n = g.length;
  10. for(var i=0 ;i<n ;i++) {
  11. t = g[i].match(reg);
  12. if(t && t.length==3)
  13. get[t[1]] = t[2];
  14. }
  15. this.POST = get;
  16.  
  17.  
  18. }/*}}}*/

COOKIE Param

浏览器传过来的 COOKIE 的参数会存在 process.env.HTTP_COOKIE,像这样「 HTTP_COOKIE: 'account=test; browser=ie'

正常的 cookie 的分割方式是使用 「; 」,一个分号,再加上一个空白,所以使用 RegExp 「/; /」就能快速的切割出来。

Cookie 处理
  1. o.getCookies = function () {
  2. if (!process.env.HTTP_COOKIE) {
  3. this.COOKIE={};
  4. return;
  5. }
  6. var cookieStr = process.env.HTTP_COOKIE;
  7. var cookieTmp = cookieStr.split(/; /i);
  8. var reg = /([a-z][^=]*)=(.+)/;
  9. var cookieList = {};
  10. var n = cookieTmp.length;
  11. for (var i=0; i<n;i++) {
  12. var t = cookieTmp[i].match(reg);
  13. cookieList[t[1]] = t[2];
  14. }
  15.  
  16. this.COOKIE = cookieList;
  17. }
  18.  
  19.  

File Upload

File Upload 的处理方式与 POST 有点像,File Upload 的资料一样是存在 input buffer 里,所以也是透过读取「 /dev/stin」这个档案。

在使用 File Upload 的 Form 表单中, HTML 都会出加上一个属性 「enctype="multipart/form-data"

当 Form 有这个属性时,档案才会上传成功,而加了 enctype 之后,原本 POST 的参数,也全部会变成 multipart/form-data 的上传格式,不再适用於 POST 的处理,也就是说上一段的 POST Param 处理方式,是没办法接收到 「multipart」上传的资料。

使用 multipart 上传方式,在「process.env.CONTENT_TYPE」中会记录一个字串 boundary , 这代表上传内容切割的字串为何 ,例如 「boundary=------------------------------6815a6a6ad9e」,这代表上传的参数必须使用「------------------------------6815a6a6ad9e」这一串字来做切割。

multipart 上传的格式如下, 第一个是指上传 key = account ,value = john ,第二个是指上传的档名为「test.txt」,内容是「test123」

Example
  1. ------------------------------6815a6a6ad9e
  2. Content-Disposition: form-data; name="account"
  3.  
  4. john
  5. ------------------------------6815a6a6ad9e
  6. Content-Disposition: form-data; name="file1"; filename="test.txt"
  7. Content-Type: application/octet-stream
  8.  
  9. test123

知道参数的储存方式之后,就可以写程式来实现档案上传罗,档案上传的程式码较长,我就不贴了,请看 github

完整 HTTP procotol 处理的程式


回應 (Leave a comment)