詳解Node.js API系列 Http模塊(1) 構造一個簡單的靜態頁服務器

HTTP

http api的文檔翻譯得太無聊了,很多用不上,例子太少,翻譯到一半就覺得受不了,決定放棄,決定,用另外一種方式去介紹這部分的API。http模塊,主要的應用是兩部分,一部分是http.createServer 擔當web服務器,另一部分是http.createClient,擔當客戶端,實現爬蟲之類的工作。從這兩方面着手介紹HTTP api。下文將會介紹http.createServer部分。

設計目標

實現一個靜態頁服務器

目標功能

  • url解析
  • 500頁面,404頁面回覆
  • 讀取路徑目錄下的靜態頁文件

最簡單的web服務器

var http = require('http');
http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/plain'});
  response.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

瀏覽器輸入http://127.0.0.1:1337/,將會看到熟悉的hello world

response.writeHead(200, {'Content-Type': 'text/plain'});
  • writeHead,200表示頁面正常,text/plain表示是文字。
  • write 寫入網頁內容。
  • end 完成寫入。

創建HTTP代理http.createServer,返回代理對象,通過返回的對象可以進行

事件監聽

proxy = http.createServer()
proxy.on('connect')    
proxy.on('upgrade')
proxy.on('close')
proxy.on('socket')
proxy.on('response')
proxy.on('checkContinue')

http.createServer 回調返回 req 和 res 對象

requestd對象

  • request.url

客戶端請求的url地址,如http://127.0.0.1/hello/world,那麼request.url就是/hello/world

  • request.headers

客戶端請求的http header

  • request.method

獲取請求的方式,一般有幾個選項,POST,GET和DELETE等,服務器可以根據客戶端的不同請求方法進行不同的處理。

response對象

  • response.writeHead(statusCode, [reasonPhrase], [headers])

statusCode html頁面狀態值
header 返回的http header,可以是字符串,也可以是對象

response.setTimeout(msecs, callback)

設置http超時返回的時間,一旦超過了設定時間,連接就會被丟棄

  • response.statusCode

設置返回的網頁狀態碼

  • response.setHeader(name, value)

設置http協議頭

  • response.headersSent

判斷是否設置了http的頭

  • response.write(chunk, [encoding])

返回的網頁數據,[encoding] 默認是 utf-8

  • response.end([data], [encoding])

將設置的數據包,發送數據到客戶端。

博客地址:http://blog.whattoc.com/2013/09/15/nodejs_http1/

url解析

                          url.parse(string).query
                                       |
           url.parse(string).pathname  |
                       |               |
                       |               |
                     ------     ---------------
http://localhost:8888/start?foo=bar&hello=world
        --------------      
              |
              |
       req.header.host       

錯誤頁面設計

500頁面

var page_500 = function(req, res, error){
    res.writeHead(500, {
      'Content-Type': 'text/html'
    });
    res.write('<!doctype html>\n');
    res.write('<title>Internal Server Error</title>\n');
    res.write('<h1>Internal Server Error</h1>');
    res.write('<pre>' + util.inspect(error) + '</pre>');
}

404頁面

var page_404 = function(req, res, path){
    res.writeHead(404, {
      'Content-Type': 'text/html'
    });
    res.write('<!doctype html>\n');
    res.write('<title>404 Not Found</title>\n');
    res.write('<h1>Not Found</h1>');
    res.write(
    '<p>The requested URL ' +
     path +
    ' was not found on this server.</p>'
    );
    res.end();
}

讀取網頁文件

var mimetype = {
  'txt': 'text/plain',
  'html': 'text/html',
  'css': 'text/css',
  'xml': 'application/xml',
  'json': 'application/json',
  'js': 'application/javascript',
  'jpg': 'image/jpeg',
  'jpeg': 'image/jpeg',
  'gif': 'image/gif',
  'png': 'image/png',
  'svg': 'image/svg+xml'
}

var fs = require('fs');
fs.exists(realPath, function(exists){
    if(!exists){

        return page_404(req, res, pathname);

    } else {
        var file = fs.createReadStream(realPath);

        res.writeHead(200, {
            'Content-Type': mimetype[realPath.split('.').pop()] || 'text/plain'
        });

        file.on('data', res.write.bind(res));
        file.on('close', res.end.bind(res));
        file.on('error', function(err){
            return page_500(req, res, err);
        });
    }
});

完整靜態服務器代碼

項目地址:https://github.com/youyudehexie/node-webstatic

var http = require('http');
var url = require('url');
var fs = require('fs');
var util = require('util');
var mimetype = {
  'txt': 'text/plain',
  'html': 'text/html',
  'css': 'text/css',
  'xml': 'application/xml',
  'json': 'application/json',
  'js': 'application/javascript',
  'jpg': 'image/jpeg',
  'jpeg': 'image/jpeg',
  'gif': 'image/gif',
  'png': 'image/png',
  'svg': 'image/svg+xml'
}
var page_404 = function(req, res, path){
    res.writeHead(404, {
      'Content-Type': 'text/html'
    });
    res.write('<!doctype html>\n');
    res.write('<title>404 Not Found</title>\n');
    res.write('<h1>Not Found</h1>');
    res.write(
    '<p>The requested URL ' +
     path + 
    ' was not found on this server.</p>'
    );
    res.end();
}
var page_500 = function(req, res, error){
    res.writeHead(500, {
      'Content-Type': 'text/html'
    });
    res.write('<!doctype html>\n');
    res.write('<title>Internal Server Error</title>\n');
    res.write('<h1>Internal Server Error</h1>');
    res.write('<pre>' + util.inspect(error) + '</pre>');
}
http.createServer(function (req, res) {

    var pathname = url.parse(req.url).pathname;
    var realPath = __dirname +  "/static" + pathname;
    fs.exists(realPath, function(exists){
    if(!exists){
        return page_404(req, res, pathname);
    } else {
        var file = fs.createReadStream(realPath);

            res.writeHead(200, {
               'Content-Type': mimetype[realPath.split('.').pop()] || 'text/plain'
            });
        file.on('data', res.write.bind(res));
        file.on('close', res.end.bind(res));      
        file.on('error', function(err){
        return page_500(req, res, err);
        });
    }    
    });  
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章