从零开始学习Node.js系列教程之设置HTTP头的方法示例
本文实例讲述了node.js设置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 服务器发送到客户端
文件扩展名不足以完全恰当的标识文件类型,而且文件扩展名没有标准,于是,人们设计了content-type头和整个mime类型标准来作为数据类型的表示系统。
对于某些应用,特别是一些处理固定数据的小型应用,我们可以精准的知道该使用哪一种content-type头,因为应用发送的数据是特定已知的。然而statichandler能发送任何文件,通常不知道该使用哪种content-type。通过匹配文件扩展名列表和content-type可以解决这个问题,但是这个方案不完美。最好的实践方案是使用一个外部的配置文件,它通常由操作系统提供。
mime npm包使用了apache项目的mime.types文件,该文件包含超过600个content-type的有关数据,如果有需要,mime模块也支持添加自定义的mime类型。
npm install mime
var mime = require('mime'); var mimetype = mime.lookup('image.gif'); //==> image/gif res.setheader('content-type', mimetype);
一些相关的http头:
content-encoding
数据被编码时使用,例如gzipcontent-language
内容中使用的语言content-length
字节数content-location
能取到数据的一个候补位置content-md5
内容主题的md5校验和
http协议是无状态的,意味着web服务器不能辨认不同的请求发送端。现在普遍的做法是,服务器发送cookie到客户端浏览器,cookie中定义了登陆用户的身份,对于每一次请求,web浏览器都会发送对应所访问网站的cookie。
发送cookie时,我们应以如下方式为set-cookie或set-cookie2头设一个值:
res.setheader('set-cookie2', ..cookie value..);
/* basic server的核心模块会创建一个http服务器对象,附加basic server上用于检查请求,然后给予适当响应的功能 basic server可以通过判断host头部匹配的容器对象响应来自多个域名的请求 */ 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数组以查找cookie和host头部,因为这两个字段对请求的分派都很重要 //这个函数在每一个http请求到达时都会被调用 //还有很多其他的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; } //提取浏览器发送的cookie if (hname.tolowercase() === "cookie"){ req.basicserver.cookies.push(hval); } } } //查找匹配的容器,分派请求到对应的容器中 //这个函数在每一个http请求到达时都会被调用 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
//用于处理文件系统内的文件,docroot选项指被存放文件所在文件夹的路径,读取该目录下的指定文件 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以/结尾 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
//这个处理函数处理对favicon.ico的请求 //mime模块根据给出的图标文件确定正确的mime类型,网站图标favicon可以是任何类型的图片,但是我们必须要告诉浏览器是哪个类型 //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
/* 把一个域的请求重定向到另一个上,例如将www.example.com重定向到example.com上,或者使用简短的url跳转到较长的url 实现这两种情况,我们需要在http响应中发送301(永久移除)或者302(临时移除)状态码,并且指定location头信息。有了这个组合 信号,web浏览器就知道要跳转到另一个web位置了 */ //地址http://localhost:3000/l/ex1 会跳转到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>
希望本文所述对大家nodejs程序设计有所帮助。
下一篇: 简单实现JS上传图片预览功能