從零開始學(xué)習(xí)Node.js系列教程之設(shè)置HTTP頭的方法示例
本文實(shí)例講述了Node.js設(shè)置HTTP頭的方法。分享給大家供大家參考,具體如下:
server.js
//basic server的配置文件
var port = 3000;
var server = require('./basicserver').createServer();
server.useFavIcon("localhost", "./docroot/favicon.png");
server.addContainer(".*", "/l/(.*)$", require('./redirector'), {})
server.docroot("localhost", "/", "./docroot");
//server.useFavIcon("127.0.0.1", "./docroot/favicon.png");
//server.docroot("127.0.0.1", "/", "./docroot");
server.listen(port);
basicserver.js
Response Header 服務(wù)器發(fā)送到客戶端
文件擴(kuò)展名不足以完全恰當(dāng)?shù)臉?biāo)識(shí)文件類型,而且文件擴(kuò)展名沒(méi)有標(biāo)準(zhǔn),于是,人們?cè)O(shè)計(jì)了Content-Type頭和整個(gè)MIME類型標(biāo)準(zhǔn)來(lái)作為數(shù)據(jù)類型的表示系統(tǒng)。
對(duì)于某些應(yīng)用,特別是一些處理固定數(shù)據(jù)的小型應(yīng)用,我們可以精準(zhǔn)的知道該使用哪一種Content-Type頭,因?yàn)閼?yīng)用發(fā)送的數(shù)據(jù)是特定已知的。然而staticHandler能發(fā)送任何文件,通常不知道該使用哪種Content-Type。通過(guò)匹配文件擴(kuò)展名列表和Content-Type可以解決這個(gè)問(wèn)題,但是這個(gè)方案不完美。最好的實(shí)踐方案是使用一個(gè)外部的配置文件,它通常由操作系統(tǒng)提供。
MIME npm包使用了Apache項(xiàng)目的mime.types文件,該文件包含超過(guò)600個(gè)Content-Type的有關(guān)數(shù)據(jù),如果有需要,mime模塊也支持添加自定義的MIME類型。
npm install mime
var mime = require('mime');
var mimeType = mime.lookup('image.gif'); //==> image/gif
res.setHeader('Content-Type', mimeType);
一些相關(guān)的HTTP頭:
Content-Encoding 數(shù)據(jù)被編碼時(shí)使用,例如gzip
Content-Language 內(nèi)容中使用的語(yǔ)言
Content-Length 字節(jié)數(shù)
Content-Location 能取到數(shù)據(jù)的一個(gè)候補(bǔ)位置
Content-MD5 內(nèi)容主題的MD5校驗(yàn)和
HTTP協(xié)議是無(wú)狀態(tài)的,意味著web服務(wù)器不能辨認(rèn)不同的請(qǐng)求發(fā)送端?,F(xiàn)在普遍的做法是,服務(wù)器發(fā)送cookie到客戶端瀏覽器,cookie中定義了登陸用戶的身份,對(duì)于每一次請(qǐng)求,web瀏覽器都會(huì)發(fā)送對(duì)應(yīng)所訪問(wèn)網(wǎng)站的cookie。
發(fā)送cookie時(shí),我們應(yīng)以如下方式為Set-Cookie或Set-Cookie2頭設(shè)一個(gè)值:
res.setHeader('Set-Cookie2', ..cookie value..);
/*
Basic Server的核心模塊會(huì)創(chuàng)建一個(gè)HTTP服務(wù)器對(duì)象,附加Basic Server上用于檢查請(qǐng)求,然后給予適當(dāng)響應(yīng)的功能
Basic Server可以通過(guò)判斷Host頭部匹配的容器對(duì)象響應(yīng)來(lái)自多個(gè)域名的請(qǐng)求
*/
var http = require('http');
var url = require('url');
exports.createServer = function(){
var htserver = http.createServer(function(req, res){
req.basicServer = {urlparsed: url.parse(req.url, true)};
processHeaders(req, res);
dispatchToContainer(htserver, req, res);
});
htserver.basicServer = {containers: []};
htserver.addContainer = function(host, path, module, options){
if (lookupContainer(htserver, host, path) != undefined){
throw new Error("Already mapped " + host + "/" + path);
}
htserver.basicServer.containers.push({host: host, path: path, module: module, options: options});
return this;
}
htserver.useFavIcon = function(host, path){
return this.addContainer(host, "/favicon.ico", require('./faviconHandler'), {iconPath: path});
}
htserver.docroot = function(host, path, rootPath){
return this.addContainer(host, path, require('./staticHandler'), {docroot: rootPath});
}
return htserver;
}
var lookupContainer = function(htserver, host, path){
for (var i = 0; i < htserver.basicServer.containers.length; i++){
var container = htserver.basicServer.containers[i];
var hostMatches = host.toLowerCase().match(container.host);
var pathMatches = path.match(container.path);
if (hostMatches !== null && pathMatches !== null){
return {container: container, host: hostMatches, path: pathMatches};
}
}
return undefined;
}
//用于搜索req.headers數(shù)組以查找cookie和host頭部,因?yàn)檫@兩個(gè)字段對(duì)請(qǐng)求的分派都很重要
//這個(gè)函數(shù)在每一個(gè)HTTP請(qǐng)求到達(dá)時(shí)都會(huì)被調(diào)用
//還有很多其他的HTTP頭部字段(Accept Accept-Encoding Accept-Language User-Agent)
var processHeaders = function(req, res){
req.basicServer.cookies = [];
var keys = Object.keys(req.headers);
for (var i = 0; i < keys.length; i++){
var hname = keys[i];
var hval = req.headers[hname];
if (hname.toLowerCase() === "host"){
req.basicServer.host = hval;
}
//提取瀏覽器發(fā)送的cookie
if (hname.toLowerCase() === "cookie"){
req.basicServer.cookies.push(hval);
}
}
}
//查找匹配的容器,分派請(qǐng)求到對(duì)應(yīng)的容器中
//這個(gè)函數(shù)在每一個(gè)HTTP請(qǐng)求到達(dá)時(shí)都會(huì)被調(diào)用
var dispatchToContainer = function(htserver, req, res){
var container = lookupContainer(htserver, req.basicServer.host, req.basicServer.urlparsed.pathname);
if (container !== undefined){
req.basicServer.hostMatches = container.host;
req.basicServer.pathMatches = container.path;
req.basicServer.container = container.container;
container.container.module.handle(req, res);
}else {
res.writeHead(404, {'Content-Type': 'text/plain'});
res.end("no handler found for " + req.basicServer.host + "/" + req.basicServer.urlparsed);
}
}
staticHandler.js
//用于處理文件系統(tǒng)內(nèi)的文件,docroot選項(xiàng)指被存放文件所在文件夾的路徑,讀取該目錄下的指定文件
var fs = require('fs');
var mime = require('mime');
var sys = require('sys');
exports.handle = function(req, res){
if (req.method !== "GET"){
res.writeHead(404, {'Content-Type': 'text/plain'});
res.end("invalid method " + req.method);
} else {
var fname = req.basicServer.container.options.docroot + req.basicServer.urlparsed.pathname;
if (fname.match(/\/$/)) fname += "index.html"; //如果URL以/結(jié)尾
fs.stat(fname, function(err, stats){
if (err){
res.writeHead(500, {'Content-Type': 'text/plain'});
res.end("file " + fname + " not found " + err);
} else {
fs.readFile(fname, function(err, buf){
if (err){
res.writeHead(500, {'Content-Type': 'text/plain'});
res.end("file " + fname + " not readable " + err);
} else {
res.writeHead(200, {'Content-Type': mime.lookup(fname),
'Content-Length': buf.length});
res.end(buf);
}
});
}
});
}
}
faviconHandler.js
//這個(gè)處理函數(shù)處理對(duì)favicon.ico的請(qǐng)求
//MIME模塊根據(jù)給出的圖標(biāo)文件確定正確的MIME類型,網(wǎng)站圖標(biāo)favicon可以是任何類型的圖片,但是我們必須要告訴瀏覽器是哪個(gè)類型
//MIME模塊,用于生成正確的Content-Type頭
var fs = require('fs');
var mime = require('mime');
exports.handle = function(req, res){
if (req.method !== "GET"){
res.writeHead(404, {'Content-Type': 'text/plain'});
res.end("invalid method " + req.method);
} else if (req.basicServer.container.options.iconPath !== undefined){
fs.readFile(req.basicServer.container.options.iconPath, function(err, buf){
if (err){
res.writeHead(500, {'Content-Type': 'text/plain'});
res.end(req.basicServer.container.options.iconPath + "not found");
} else {
res.writeHead(200, {'Content-Type': mime.lookup(req.basicServer.container.options.iconPath),
'Content-Length': buf.length});
res.end(buf);
}
});
} else {
res.writeHead(404, {'Content-Type': 'text/plain'});
res.end("no favicon");
}
}
redirector.js
/*
把一個(gè)域的請(qǐng)求重定向到另一個(gè)上,例如將www.example.com重定向到example.com上,或者使用簡(jiǎn)短的URL跳轉(zhuǎn)到較長(zhǎng)的URL
實(shí)現(xiàn)這兩種情況,我們需要在HTTP響應(yīng)中發(fā)送301(永久移除)或者302(臨時(shí)移除)狀態(tài)碼,并且指定location頭信息。有了這個(gè)組合
信號(hào),web瀏覽器就知道要跳轉(zhuǎn)到另一個(gè)web位置了
*/
//地址http://localhost:3000/l/ex1 會(huì)跳轉(zhuǎn)到http://example1.com
var util = require('util');
var code2url = {'ex1': 'http://example1.com', 'ex2': "http://example2.com"};
var notFound = function(req, res){
res.writeHead(404, {'Content-Type': 'text/plain'});
res.end("no matching redirect code found for " + req.basicServer.host + "/" + req.basicServer.urlparsed.pathname);
}
exports.handle = function(req, res){
if (req.basicServer.pathMatches[1]){
var code = req.basicServer.pathMatches[1];
if (code2url[code]){
var url = code2url[code];
res.writeHead(302, {'Location': url});
res.end();
} else {
notFound(req, res);
}
} else {
notFound(req, res);
}
}
docroot目錄下:有favicon.png
index.html
<html> <head> </head> <body> <h1>Index</h1> <p>this is a index html.</p> </body> </html>

希望本文所述對(duì)大家nodejs程序設(shè)計(jì)有所幫助。
- 從零開始學(xué)習(xí)Node.js系列教程之SQLite3和MongoDB用法分析
- 從零開始學(xué)習(xí)Node.js系列教程六:EventEmitter發(fā)送和接收事件的方法示例
- 從零開始學(xué)習(xí)Node.js系列教程五:服務(wù)器監(jiān)聽方法示例
- 從零開始學(xué)習(xí)Node.js系列教程四:多頁(yè)面實(shí)現(xiàn)數(shù)學(xué)運(yùn)算的client端和server端示例
- 從零開始學(xué)習(xí)Node.js系列教程之基于connect和express框架的多頁(yè)面實(shí)現(xiàn)數(shù)學(xué)運(yùn)算示例
- 從零開始學(xué)習(xí)Node.js系列教程四:多頁(yè)面實(shí)現(xiàn)的數(shù)學(xué)運(yùn)算示例
- 從零開始學(xué)習(xí)Node.js
相關(guān)文章
Windows系統(tǒng)下安裝Node.js的步驟圖文詳解
這篇文章主要給大家介紹了Windows系統(tǒng)下Node.js的安裝教程,Node.js是用于后端編程的JavaScript框架,文中給出了詳細(xì)圖文介紹,有需要的朋友可以參考下,下面來(lái)一起看看吧。2016-11-11
npm install -g 遇到權(quán)限問(wèn)題解析
這篇文章主要為大家介紹了npm install -g 遇到權(quán)限問(wèn)題解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06
Express進(jìn)階之log4js實(shí)用入門指南
本篇文章主要介紹了Express進(jìn)階之log4js實(shí)用入門指南,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-02-02
Nodejs使用exceljs實(shí)現(xiàn)excel導(dǎo)入導(dǎo)出
在日常開發(fā)中,我們常需在后臺(tái)管理系統(tǒng)中實(shí)現(xiàn)數(shù)據(jù)的導(dǎo)入與導(dǎo)出功能,以便與?Excel?文件進(jìn)行交互,本文將使用使用exceljs實(shí)現(xiàn)excel導(dǎo)入導(dǎo)出功能,需要的可以參考下2024-03-03
Node.js?全局變量無(wú)法掛載問(wèn)題解決分析
這篇文章主要為大家介紹了Node.js?全局變量無(wú)法掛載問(wèn)題解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04

