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 的內容做切割,就能夠很輕易的取出參數。
- o.getGET = function (p) {/*{{{*/
- var q = p.env.QUERY_STRING;
- if(!q){return ;}
- var g = q.split(/&(?=[a-z])/);
- var get = {};
- var reg = /([^=]+)=(.+)/i,t;
- var n = g.length;
- for(var i=0 ;i<n ;i++) {
- t = g[i].match(reg);
- if(t && t.length==3)
- get[t[1]] = t[2];
- }
- this.GET = get;
- }/*}}}*/
POST Param
POST 的參數比起 GET 會比較複雜一點,POST 傳遞的參數長度是沒有限制,所以不能夠存在任何的變數中,否則會造成 buffer 溢出,會有安全上的疑慮,而 POST 的內容會存在 input buffer 中,必須透過讀取 buffer 的方式來操作。
透過讀取 /dev/stdin 的方式,將 input buffer 的資料讀進來「fs.readFileSync('/dev/stdin')」。
讀到 POST 的資料後,跟 GET 一樣使用 Regular Exp 的方式,將參數切割出來,存在 this.POST。
- /** param by method post**/
- o.getPOST = function(buff) {/*{{{*/
- if (!buff){return ; }
- var g = buff.split(/&(?=[a-z])/);
- var get = {};
- var reg = /([a-z0-9_\-]+)=(.+)/i,t;
- var n = g.length;
- for(var i=0 ;i<n ;i++) {
- t = g[i].match(reg);
- if(t && t.length==3)
- get[t[1]] = t[2];
- }
- this.POST = get;
- }/*}}}*/
COOKIE Param
瀏覽器傳過來的 COOKIE 的參數會存在 process.env.HTTP_COOKIE,像這樣「 HTTP_COOKIE: 'account=test; browser=ie'」
正常的 cookie 的分割方式是使用 「; 」,一個分號,再加上一個空白,所以使用 RegExp 「/; /」就能快速的切割出來。
- o.getCookies = function () {
- if (!process.env.HTTP_COOKIE) {
- this.COOKIE={};
- return;
- }
- var cookieStr = process.env.HTTP_COOKIE;
- var cookieTmp = cookieStr.split(/; /i);
- var reg = /([a-z][^=]*)=(.+)/;
- var cookieList = {};
- var n = cookieTmp.length;
- for (var i=0; i<n;i++) {
- var t = cookieTmp[i].match(reg);
- cookieList[t[1]] = t[2];
- }
- this.COOKIE = cookieList;
- }
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」
- ------------------------------6815a6a6ad9e
- Content-Disposition: form-data; name="account"
- john
- ------------------------------6815a6a6ad9e
- Content-Disposition: form-data; name="file1"; filename="test.txt"
- Content-Type: application/octet-stream
- test123
知道參數的儲存方式之後,就可以寫程式來實現檔案上傳囉,檔案上傳的程式碼較長,我就不貼了,請看 github。