"allow":允许带有点的文件
"deny":对请求点的文件发送一个403,同时调用下面一个中间件var express = require('express'); var app = express(); app.get('/', function(req, res){ res.send('hello world'); }); app.listen(3000);app对象有一下的方法:
app.locals:保存这个应用中的局部变量
app.locals.title // => 'My App' app.locals.email // => '[email protected]'只要设置了app.locals属性,那么在整个应用的生命周期内都是存在的。而res.locals属性仅仅在一个请求的生命周期中有效。你可以访问整个应用的访问模版中的局部变量。这对于为模板添加帮助函数非常有用,同时也可以提供一些应用层面的数据。局部的变量在中间件中可以通过req.app.locals来访问
app.locals.title = 'My App'; app.locals.strftime = require('strftime'); app.locals.email = '[email protected]';app.mountpath:保存的是一个或者多个路由模式,在这个路由模式下我们可以添加一个一个子应用。子应用表示的是一个express实例,这个实例用于处理特定路由的请求。
var express = require('express'); var app = express(); //主应用 var admin = express(); //子应用 admin.get('/', function (req, res) { //子应用的真实的处理逻辑 console.log(admin.mountpath); // /admin就是moutpath res.send('Admin Homepage'); }); app.use('/admin', admin); //添加子应用mountpath和req对象的baseUrl相似,只是req.baseUrl返回的是一个URL,而不是匹配的模式。如果一个子应用被添加在多个路径模式下那么app.mountpath返回这个pattern的集合
var admin = express(); admin.get('/', function (req, res) { console.log(admin.mountpath); // [ '/adm*n', '/manager' ] res.send('Admin Homepage'); }); var secret = express(); secret.get('/', function (req, res) { console.log(secret.mountpath); // /secr*t res.send('Admin Secret'); }); admin.use('/secr*t', secret); // load the 'secret' router on '/secr*t', on the 'admin' sub app app.use(['/adm*n', '/manager'], admin); // load the 'admin' router on '/adm*n' and '/manager', on the parent app我们看到admin是被绑定到['/adm*n','/manager']上面的,所以对于admin来说其mountpath就是这个数组。而对于secret来说,其通过admin来使用的额,而admin使用的时候被绑定到"/secr*t"路径上。 很显然看到这里对于secret来说其mountpath不是/manager/secr*t!
var admin = express(); admin.on('mount', function (parent) { console.log('Admin Mounted'); console.log(parent); // refers to the parent app }); admin.get('/', function (req, res) { res.send('Admin Homepage'); }); app.use('/admin', admin);注意:子应用不会继承值为默认值的配置信息,你必须自己在子应用上面的手动设置。同时他会自动继承不是默认值的配置信息
方法篇:
app.all(path, callback [, callback ...])
这个方法会拦截所有的HTTP动词的请求。如果把下面这个路由添加在其他路由的前面,这时候所有的去请求必须授权,同时他会自动查询一个用户。而且这时候loadUser还可以通过调用next来继续执行后面的二路由
app.all('*', requireAuthentication, loadUser);这个方法和下面是完全一致的:
app.all('*', requireAuthentication) app.all('*', loadUser);下面可以实现全局的白名单功能。但是路径必须是"/api"开始的
app.all('/api/*', requireAuthentication);app.delete(path, callback [, callback ...])
app.delete('/', function (req, res) { res.send('DELETE request to homepage'); });
app.disable(name)
就是把name设置为false,name的属性的值可以参考app的setting表格。如通过app.set('foo',false)相当于调用app.disable('foo')。
app.disable('trust proxy'); app.get('trust proxy'); // => falseapp.disabled(name)
app.disabled('trust proxy'); // => true app.enable('trust proxy'); app.disabled('trust proxy'); // => falseapp.enable(name)
app.enable('trust proxy'); app.get('trust proxy'); // => trueapp.engine(ext, callback)
app.engine('jade', require('jade').__express);如果为没有提供.__express的引擎使用这个方法,或者你想要为引擎指定一个不同的后缀。如下面的例子
app.engine('html', require('ejs').renderFile);这时候,EJS提供了一个renderFile方法,这个方法的签名和Express期望的是一样的:(path,options,callback)。这个方法还有一个内部相同功能的函数,也就是ejs._express,因此如果你使用.ejs后缀那么不需要做任何处理。
var engines = require('consolidate'); app.engine('haml', engines.haml); app.engine('html', engines.hogan);app.get(name)
app.get('title'); // => undefined app.set('title', 'My Site'); app.get('title'); // => "My Site"app.get(path, callback [, callback ...])
app.get('/', function (req, res) { res.send('GET request to homepage'); });app.listen(port, [hostname], [backlog], [callback])
var express = require('express'); var app = express(); app.listen(3000);返回的app其实是一个javascript的函数,这个函数被传入到Node的HTTP服务器作为一个请求的回调函数。这样你就可以为为你的应用同时添加HTTP和HTTPS版本的处理函数
var express = require('express'); var https = require('https'); var http = require('http'); var app = express(); http.createServer(app).listen(80); https.createServer(options, app).listen(443);我们知道app.listen方法返回一个http.Server对象,其实是后续代码的一个简化
app.listen = function() { var server = http.createServer(this); return server.listen.apply(server, arguments); };
挂载中间件的方法:
app.use(function (req, res, next) { next(); }) //一个router是有效的中间件。 var router = express.Router(); router.get('/', function (req, res, next) { next(); }) app.use(router); //一个Express程序是一个有效的中间件。 var subApp = express(); subApp.get('/', function (req, res, next) { next(); }) app.use(subApp);挂载一系列中间件:
var r1 = express.Router(); r1.get('/', function (req, res, next) { next(); }) var r2 = express.Router(); r2.get('/', function (req, res, next) { next(); }) app.use(r1, r2);挂载一组中间件:
var r1 = express.Router(); r1.get('/', function (req, res, next) { next(); }) var r2 = express.Router(); r2.get('/', function (req, res, next) { next(); }) app.use('/', [r1, r2]);在逻辑上使用一个数组来组织一组中间件。如果你传递一组中间件作为第一个或者唯一的参数,接着你需要指定挂载的路径。
function mw1(req, res, next) { next(); } function mw2(req, res, next) { next(); }//第三种方式直接通过挂载函数来完成 var r1 = express.Router();//第一种方式通过express.Router来挂载 r1.get('/', function (req, res, next) { next(); }); var r2 = express.Router(); r2.get('/', function (req, res, next) { next(); }); var subApp = express();//第二种方式通过创建express实例来挂载中间件 subApp.get('/', function (req, res, next) { next(); }); app.use(mw1, [mw2, r1, r2], subApp);//组合多种方式挂载中间件
req对象的属性:
req.app:中间件获取主页app对象
req.baseUrl(和app对象的mountpath属性相似,除了app.mountpath返回的是路径匹配模式
var express=require('express'); var app=express(); var admin = express(); //admin中间件的请求 admin.get('/', function (req, res) { console.log(admin.mountpath); // [ '/adm*n', '/manager' ] console.log(req.baseUrl); //返回的是/manager res.send('Admin Homepage'); }); var secret = express(); secret.get('/', function (req, res) { console.log(secret.mountpath); // /secr*t console.log(req.baseUrl); res.send('Admin Secret'); }); admin.use('/secr*t', secret); // load the 'secret' router on '/secr*t', on the 'admin' sub app app.use(['/adm*n', '/manager'], admin); // load the 'admin' router on '/adm*n' and '/manager', on the parent app app.listen(30000);注意:如果这时候的访问路径为http://localhost:30000/manager/secret那么就会打印/secr*t和/manager/secret,所有说mountpath只是子引用挂载的路径,而req.baseUrl 返回的是实际的路径,其中的通配符全部转化为实际的路径了,而且是从app开始计算的路径,因为我们的listen是挂载在主应用app下!
// Host: "example.com" req.hostname // => "example.com"
一个布尔值,如果X-Requested-With的值为XMLHttpRequest,那么其为true,其指示这个请求是被一个客服端库发送,比如jQuery。
req对象的方法:
req.accepts(types)
检查这个指定的内容类型是否被接受,基于请求的Accept HTTP头部。这个方法返回最佳匹配,如果没有一个匹配,那么其返回undefined(在这个case下,服务器端应该返回 406和"Not Acceptable")。 ype值可以是一个单的MIME type字符串(比如application/json),一个扩展名比如json,一个逗号分隔的列表,或者一个数组。对于一个列表或者数 组,这个方法返回最佳项(如果有的话)。
req.acceptsCharsets(charset[, ...])
返回指定的字符集集合中第一个的配置的字符集,基于请求的Accept-CharsetHTTP头。如果指定的字符集没有匹配的,那么就返回false。
req.acceptsEncodings(encoding[, ...])
返回指定的编码集合中第一个的配置的编码,基于请求的Accept-EncodingHTTP头。如果指定的编码集没有匹配的,那么就返回false。
req.acceptsLanguages(lang [, ...])
返回指定的语言集合中第一个的配置的语言,基于请求的Accept-LanguageHTTP头。如果指定的语言集没有匹配的,那么就返回false。
req.get(field)
返回指定的请求HTTP头部的域内容(不区分大小写)。Referrer和Referer的域内容可互换。其是req.header(field)的别名。
req.get('Content-type'); // => "text/plain" req.get('content-type'); // => "text/plain" req.get('Something') // => undefinedreq.is(type)
// ?name=tobi req.param('name') // => "tobi" // POST name=tobi req.param('name') // => "tobi" // /user/tobi for /user/:name req.param('name') // => "tobi"按下面给出的顺序查找:
res.app
这个属性持有express程序实例的一个引用,其可以在中间件中使用。 res.app和请求对象中的req.app属性是相同的。
res.headersSent
布尔类型的属性,指示这个响应是否已经发送HTTP头部。
res.locals:
包含的是某个请求中为response添加的局部变量,因此这个对象只对一个请求/响应生命周期中的视图可见。和app.locals类似。这个属性常用于暴露一些请求层面的信息,例 如请求路径名称,认证的用户,用户的设置等
app.use(function(req, res, next){ res.locals.user = req.user; res.locals.authenticated = ! req.user.anonymous; next(); });resonse对象的方法:
res.append(field [, value])
res.append()方法在Expresxs4.11.0以上版本才支持。在指定的field的HTTP头部追加特殊的值value。如果这个头部没有被设置,那么将用value新建这个头部。value可以是一个字符串或者数组。 注意:在res.append()之后调用app.set()函数将重置前面设置的值。
res.append('Lind', ['<http://localhost>', '<http://localhost:3000>']); res.append('Set-Cookie', 'foo=bar;Path=/;HttpOnly'); res.append('Warning', '199 Miscellaneous warning');res.attachment([filename])
res.attachment(); // Content-Disposition: attachment res.attachment('path/to/logo.png'); // Content-Disposition: attachment; filename="logo.png" // Content-Type: image/pngres.cookie(name, value [,options])
res.format({ 'text/plain':function() { res.send('hey')' }, 'text/html':function() { res.send('<p>hey</p>'); }, 'application/json':function() { res.send({message:'hey'}); }, 'default':function() { res.status(406).send('Not Acceptable'); }除了规范化的MIME类型之外,你也可以使用拓展名来映射这些类型来避免冗长的实现:
res.format({ text:function() { res.send('hey'); }, html:function() { res.send('<p>hey</p>'); }, json:function() { res.send({message:'hey'}); } })res.get(field)
// ?callback=foo res.jsonp({user:'tobo'}) // => foo({"user":"tobi"}) app.set('jsonp callback name', 'cb') // ?cb=foo res.status(500).jsonp({error:'message'}) // => foo({"error":"message"})
下面是三个例子:
方法1:通过jquery实现的jsonp请求:
function jsonp() { //向服务器发送请求,回调函数由jquery自己指定 $.getJSON("http://127.0.0.1:30000/jsonp?callback=?", function(data) { alert(data.name); }); }对应的服务器代码为:
app.get('/jsonp',function(req,res,next){ //和res.json一样,不过jsonp可以触发回调函数 res.status(200).jsonp({name:'高山上的鱼'}) });方法2:通过原生javascript实现的jsonp
function originalJsonp() { //回调函数 var url = "http://127.0.0.1:30000/jsonp1?pursue=callbackfunction"; var script = document.createElement('script'); script.setAttribute('src', url); //load javascript document.getElementsByTagName('head')[0].appendChild(script); } function callbackfunction(data){ alert(data.name); }服务器端的代码为:
app.get('/jsonp1',function(req,res,next){ //console.log(req.query); var callbackFunc=req.query.pursue; var result=JSON.stringify({name:"qinliang"}); res.write(callbackFunc+"("+result+")"); res.end(); });方法3:通过app.set('jsonp callback name', 'callbackfunction1') 自动修改回调函数
app.set('jsonp callback name', 'pursue') app.get('/jsonp2',function(req,res,next){ //和res.json一样,不过jsonp可以触发回调函数 res.status(200).jsonp({name:'高山上的鱼'}) });我们看看服务器返回的数据是什么:
/**/ typeof callbackfunction === 'function' && callbackfunction({"name":"高山上的鱼"});
res.links(links)
连接这些links,links是以传入参数的属性形式提供,连接之后的内容用来填充响应的Link HTTP头部(暂时不知道这个HTTP头有什么作用)。
var express=require('express'); var app = express() app.get('/',function(req,res){ res.links({ next:'http://api.example.com/users?page=2', last:'http://api.example.com/user?page=5' }); res.end('高山上的鱼我爱你'); //打印Link:<http://api.example.com/users?page=2>; rel="next", <http://api.example.com/user?page=5>; rel="last" }) app.listen(10000, function() { console.log('Ready'); });res.location(path)
var express=require('express'); var app = express() app.get('/',function(req,res){ //重定向到一个新的网址 res.status(301).location('http://www.baidu.com/'); res.end(); //也可以使用下面这种方式: // res.setHeader('location','http://www.baidu.com'); // res.writeHead();//多次setHead只会在最后一次writeHead会发送HTTP头部 }); app.listen(9999, function() { console.log('Ready'); });当path参数为back时,其具有特殊的意义,其指定URL为请求对象的Referer头部指定的URL。如果请求中没有指定,那么其即为"/"。
// pass a local variable to the view res.render('user', {name:'Tobi'}, function(err, html) { // ... });res.send([body])
app.get('/file/:name', function(req, res, next) { var options = { root:__dirname + '/public', dotfile:'deny', headers:{ 'x-timestamp':Date.now(), 'x-sent':true } }; var fileName = req.params.name; res.sendFile(fileName, options, function(err) { if (err) { console.log(err); res.status(err.status).end(); } else { console.log('sent', fileName); } }); });res.sendStatus(statusCode)
res.sendStatus(200); // equivalent to res.status(200).send('OK'); res.sendStatus(403); // equivalent to res.status(403).send('Forbidden'); res.sendStatus(404); // equivalent to res.status(404).send('Not Found'); res.sendStatus(500); // equivalent to res.status(500).send('Internal Server Error') //如果一个不支持的状态被指定,这个HTTP status依然被设置为statusCode并且用这个code的字符串作为Body。 res.sendStatus(2000); // equivalent to res.status(5000).send('2000');res.set(field [, value])