初识Express框架-详细学习API

express.static(root, [options])
express.static是唯一的一个express内置的中间件,他用于处理静态文件,是基于serve-static来完成的。
    对于静态文件的请求时通过root+req.url拼接完成的。如果不存在这个静态文件那么交给下面一个中间件,而不是返回404。
   其中options可以是下面的这些参数:
  dotfiles:决定如何处理点的文件

        "allow":允许带有点的文件

        "deny":对请求点的文件发送一个403,同时调用下面一个中间件
        "ignore":如果这个点文件不存在,那么返回404,同时调用下面一个中间件
        注意:默认情况下不会忽略文件夹下面的以点开头的文件
  etag:开启或者关闭etag的生成。注意express.static一般都会发送弱的etag
  extensions:如果没有找到文件那么查找这个数组,然后发送给浏览器第一个找到的文件。如['html', 'htm'].
  fallthrough:让客户端产生一个未处理的请求
      true vs false:表示客户端非正确的请求或者请求一个不存在的文件都会导致简单的调用下面一个中间件,也就是调用next()
             如果是false那么就会调用next(err),这一点很重要。如果设置为false那么所有请求如GET/POST等都会调用
  index:发送一个特定目录的index文件,如果设置为false那么就会关闭这种请求文件的方式
  lastModified:为操作系统中的文件设置一个lastModified头
  maxAge:为cache-control这个头设置一个max-age属性。属性是毫秒值,或者是一个毫秒的字符串
  redirect:如果路径的名称为一个目录,那么就会去查找"/"
  setHeaders:为客户端请求的文件添加HTTP头
     指定一个函数用于发送自定义的响应头,对响应头的改变必须是同步的。这个函数的签名是fn(res, path, stat)
     其中res是一个response对象,path表示要发送的文件路径,stat表示这个文件的描述符
express.Router([options])
    用于创建一个新的路由对象,var router = express.Router([options]);
    caseSensitive(默认是false):表示是否大小写敏感
    mergeParams(defalut为false):保存来自于上一个路由的req.params的值,如果当前路由的值和上一个路由的值冲突那么会覆盖上一个路由的值

    strict(默认为false):开启严格的路由。默认情况下/foo和/foo/是一致的


  注意:可以添加中间件和HTTP方法的路由,如通过put/get/post等路由
		 var express = require('express');
		var app = express();
		app.get('/', function(req, res){
		  res.send('hello world');
		});
		app.listen(3000);
  app对象有一下的方法:
   .为HTTP请求添加路由

   .添加中间件,如app.route。用这种方式可以防止重名路由

var app = express();
app.route('/events')
.all(function(req, res, next) {
  // runs for all HTTP verbs first
  // think of it as route specific middleware!
})
.get(function(req, res, next) {
  res.json(...);
})
.post(function(req, res, next) {
  // maybe add a new event...
});

   .渲染HTML视图,如app.render

// send the rendered view to the client
res.render('index');
// if a callback is specified, the rendered HTML string has to be sent explicitly
res.render('index', function(err, html) {
  res.send(html);
});
// pass a local variable to the view
res.render('user', { name: 'Tobi' }, function(err, html) {
  // ...
});

   .添加一个模板引擎,如app.engine

var engines = require('consolidate');
app.engine('haml', engines.haml);
app.engine('html', engines.hogan);

   .有一些配置信息会影响express应用的行为


 app.locals:保存这个应用中的局部变量        

                              app.locals.title
				// => 'My App'
				app.locals.email
				// => 'me@myapp.com'
只要设置了app.locals属性,那么在整个应用的生命周期内都是存在的。而res.locals属性仅仅在一个请求的生命周期中有效。你可以访问整个应用的访问模版中的局部变量。这对于为模板添加帮助函数非常有用,同时也可以提供一些应用层面的数据。局部的变量在中间件中可以通过req.app.locals来访问
                
                           app.locals.title = 'My App';
				app.locals.strftime = require('strftime');
				app.locals.email = 'me@myapp.com';
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!
app.on('mount', callback(parent))
这个mount事件在子应用上面被调用,当这个子应用被添加到父应用上面。而且这个事件回调中被传入父应用的引用。
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 ...])
为HTTP的DELETE添加一个路由,并且同时提供了一个回调函数。你可以提供多个回调函数,这些回调函数扮演中间件的作用,这些回调函数可以触发next('route')来跳过接下来的路由回调函数。我们可以使用这种机制来添加一些路由执行前的前提条件,然后把控制权交给后续的路由(如果当前路由不需要执行)
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');
// => false
app.disabled(name)
 表示属性是否被设置为false
app.disabled('trust proxy');
// => true
app.enable('trust proxy');
app.disabled('trust proxy');
// => false
app.enable(name)
  是否把name的值设置为true,如app.set('foo',true)相当于设置app.enable('foo')
app.enable('trust proxy');
app.get('trust proxy');
// => true
app.engine(ext, callback)
 用于注册一个模板引擎。默认情况下express通过文件后缀来添加模板引擎,如"foo.jade"文件,express就会在内部调用下面的代码,同时把这次的require缓存起来,当下次请求的时候就可以提升性能。
 app.engine('jade', require('jade').__express);
 如果为没有提供.__express的引擎使用这个方法,或者你想要为引擎指定一个不同的后缀。如下面的例子
 app.engine('html', require('ejs').renderFile);
 这时候,EJS提供了一个renderFile方法,这个方法的签名和Express期望的是一样的:(path,options,callback)。这个方法还有一个内部相同功能的函数,也就是ejs._express,因此如果你使用.ejs后缀那么不需要做任何处理。
 有些模板引擎和上面的方式还是有一点不同,如consolidate.js的库把Node库的模板引擎映射为以下的方式,以便于Express无缝融合:
 var engines = require('consolidate');
app.engine('haml', engines.haml);
app.engine('html', engines.hogan);
app.get(name)
 其中name的值来自于app setting
 app.get('title');
// => undefined
app.set('title', 'My Site');
app.get('title');
// => "My Site"
app.get(path, callback [, callback ...])
 为HTTP的get方法添加一个路由请求。你可以提供多个回调函数,这些回调函数就像中间件一样,但是这些回调函数可以通过调用next('route')来跳过后续的中间件。你可以使用这种机制来添加一些指定路径执行前的逻辑,然后也可以调用当前的路由。
app.get('/', function (req, res) {
  res.send('GET request to homepage');
});
app.listen(port, [hostname], [backlog], [callback])
  绑定对于某一个特定host+port的连接的监听。这个方法通过Node的http.Server.listen来完成
  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);//组合多种方式挂载中间件

我们来仔细看看app具体的信息:

app.listen = function(){
  var server = http.createServer(this);
  return server.listen.apply(server, arguments);
};
这说明我们的app.listen方法实际上返回的是http.Server对象,那我们看看这个对象有什么具体的信息:

 _events: { mount: [Function] },
  _maxListeners: undefined,
  setMaxListeners: [Function: setMaxListeners],
  //因为app继承了http.Server,而http.Server继承了net.Server,而net.Server是一个EventEmitter实例
  getMaxListeners: [Function: getMaxListeners],
  //getMaxListeners函数
  emit: [Function: emit],
  //继承事件Class: EventEmitter
  addListener: [Function: addListener],
    //继承事件Class: EventEmitter
  on: [Function: addListener],
    //继承事件Class: EventEmitter
  once: [Function: once],
    //继承事件Class: EventEmitter
  removeListener: [Function: removeListener],
    //继承事件Class: EventEmitter
  removeAllListeners: [Function: removeAllListeners],
    //继承事件Class: EventEmitter,返回一个事件回调的数组
  listeners: [Function: listeners],
  //继承事件Class: EventEmitter
  listenerCount: [Function: listenerCount],
这只是其中一部分关于事件的函数,仔细看看这个http.Server,我们发现他继承了net.Server,而net.Server又是EventEmitter实例,所以最后http.Server也就具有了EventEmitter所有的属性和方法。
 request: IncomingMessage { app: [Circular] },
  //request对象也是一个IncomingMessage对象,其中的app对象就是我们打印出来的整个对象
  response: ServerResponse { app: [Circular] },
  //response对象也是一个IncomingMessage对象,其中的app对象就是我们打印出来的整个对象
同时我们也可以看到app本身封装了两个IncomingMessage,其实他具有app所有的方法,其他一些配置信息 可以阅读

req对象的属性:

首先我们必须弄清楚一个问题:req对象是一个IncomingMessage对象,也就是下面打印true,IncomingMessage具有的所有属性这个req对象都是有的:httpVersionMajor,httpVersionMinor,httpVersion,headers,rawHeaders,trailers等。也有一些特定的属性:baseUrl,originalUrl,params,query,res,locals  

var express=require('express');
var http=require('http');
var app=express();
function replacer(key, value) {
  if (key === "car") {
    return undefined;
  }
  return value;
}
app.set('json replacer', replacer);
app.set('json spaces',5)
app.set('x-powered-by',false);
//返回一个http.Server对象,然后继续调用其listen方法
var admin = express();
app.get('/',function(req,res){
  console.log(req instanceof http.IncomingMessage);
});

   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下!
     req.body:在请求的body中保存的是提交的一对对键值数据。默认情况下,它是undefined,当你使用比如body-parser和multer这类解析body数据的中间件时,它是填充 的。 
     req.cookies:当使用cookie-parser中间件的时候,这个属性是一个对象,其包含了请求发送过来的cookies。如果请求没有带cookies,那么其值为{}。如果没有指定cookie parser,那么保存cookie的地址为req.headers.cookie!很多属性都保存在req.headers空间下面
     req.fresh:
     req.hostname:包含了源自HostHTTP头部的hostname。 当trust proxy设置项被设置为启用值,X-Forwarded-Host头部被使用来代替Host。这个头部可以被客户端或者代理                             设置

                  // Host: "example.com"
                    req.hostname
                    // => "example.com"
           
     req.ips:当trust proxy设置项被设置为启用值,这个属性包含了一组在X-Forwarded-For请求头中指定的IP地址。不然,其就包含一个空的数组。这个头部可以被客户端或者代理设置。 例如,如果X-Forwarded-For是client,proxy1,proxy2,req.ips就是["clinet", "proxy1", "proxy2"],这里proxy2就是最远的下游。
    req.originalUrl:req.url不是一个原生的Express属性,它继承自Node's http module。这个属性很像req.url;然而,其保留了原版的请求链接,允许你自由地重定向req.url到内部路由。比如,app.use()的mounting特点可以重定向req.url跳转到挂载点。

 req.params
       一个对象,其包含了一系列的属性,这些属性和在路由中命名的参数名是一一对应的。例如,如果你有/user/:name路由,name属性可作为req.params.name。这个对象默       认值为{}。
  req.protocol
       请求的协议,一般为http,当启用TLS加密,则为https。当trust proxy设置一个启用的参数,如果存在X-Forwarded-Proto头部的话,其将被信赖和使用。这个头部可以被客        户端或者代理设置。
req.query
    一个对象,为每一个路由中的query string参数都分配一个属性。如果没有query string,它就是一个空对象,{}。
req.route
    当前匹配的路由,其为一串字符
req.signedCookies
    当使用cookie-parser中间件的时候,这个属性包含的是请求发过来的签名cookies,不签名的并且为使用做好了准备(这句真不知道怎么翻译了...)。签名cookies驻留在不同的对象中来体现开发者的意图;不然,一个恶意攻击可以被施加在req.cookie值上(它是很容易被欺骗的)。记住,签名一个cookie不是把它藏起来或者加密;而是简单的防止篡改(因为签名使用的加密是私人的)。如果没有发送签名的cookie,那么这个属性默认为{}。
req.stale
    指示这个请求是否是stale(陈旧的),它与req.fresh是相反的。更多信息,可以查看req.fresh。
req.subdomains
    请求中域名的子域名数组
req.xhr

一个布尔值,如果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')
        // => undefined
  
req.is(type)
    如果进来的请求的Content-type头部域匹配参数type给定的MIME type,那么其返回true。否则返回false。
req.param(naem, [, defaultValue])
过时的。可以在适合的情况下,使用req.params,req.body或者req.query。返回当前参数name的值。
// ?name=tobi
req.param('name')
// => "tobi"
// POST name=tobi
req.param('name')
// => "tobi"
// /user/tobi for /user/:name
req.param('name')
// => "tobi"
按下面给出的顺序查找:
req.params
req.body
req.query
可选的,你可以指定一个defaultValue来设置一个默认值,如果这个参数在任何一个请求的对象中都不能找到。直接通过req.params,req.body,req.query取得应该更加的清晰-除非你确定每一个对象的输入。 Body-parser中间件必须加载,如果你使用req.param()。详细请看req.body。
response对象的属性:

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])
设置HTTP响应的Content-Disposition头内容为"attachment"。如果提供了filename,那么将通过res.type()获得扩展名来设置Content-Type,并且设置Content-Disposition          内容为"filename="parameter。

	res.attachment();
	// Content-Disposition: attachment
	res.attachment('path/to/logo.png');
	// Content-Disposition: attachment; filename="logo.png"
	// Content-Type: image/png
res.cookie(name, value [,options])
设置name和value的cookie,value参数可以是一串字符或者是转化为json字符串的对象。 res.cookie()所作的都是基于提供的options参数来设置Set-Cookie头部。没有指 定任何的options,那么默认值在RFC6265中指定。
res.clearCookie(name [,options])
根据指定的name清除对应的cookie。更多关于options对象可以查阅res.cookie()。
res.download(path, [,filename], [,fn])
    传输path指定文件作为一个附件。通常,浏览器提示用户下载。默认情况下,Content-Disposition头部"filename="的参数为path(通常会出现在浏览器的对话框中)。通过指 定filename参数来覆盖默认值。 当一个错误发生时或者传输完成,这个方法将调用fn指定的回调方法。这个方法使用res.sendFile()来传输文件。
res.end([data] [, encoding])
结束本响应的过程。这个方法实际上来自Node核心模块,具体的是response.end() method of http.ServerResponse。用来快速结束请求,没有任何的数据。如果你需要发 送数据,可以使用res.send()和res.json()这类的方法。
res.format(object)
进行内容协商,根据请求的对象中AcceptHTTP头部指定的接受内容。它使用req.accepts()来选择一个句柄来为请求服务,这些句柄按质量值进行排序。如果这个头部没有指定,那么第一个方法默认被调用。当不匹配时,服务器将返回406"Not Acceptable",或者调用default回调。 Content-Type请求头被设置,当一个回调方法被选择。然而你可以改变他,在这个方法中使用这些方法,比如res.set()或者res.type()。 
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)
返回field指定的HTTP响应的头部。匹配是区分大小写。
res.json([body])
发送一个json的响应。这个方法和将一个对象或者一个数组作为参数传递给res.send()方法的效果相同。不过,你可以使用这个方法来转换其他的值到json,例如null,undefined。(虽然这些都是技术上无效的JSON)。
res.jsonp([body])
发送一个json的响应,并且支持JSONP。这个方法和res.json()效果相同,除了其在选项中支持JSONP回调。
默认情况下,jsonp的回调方法简单写作callback。可以通过jsonp callback name设置来重写它。 
     // ?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)
设置响应的Location的HTTP头部为指定的path参数。某些情况下由于网站迁移,权限,页面错误时我们可能需要跳转页面到错误页面,但是我们发送响应码只是一种状态机制(如301,302, 404等),因此往往我们需要选择合适的跳转方式,Location跳转是一种常见的方式,特别对于做SEO的同学来说。   表示客户应当到哪里去提取文档。Location通常不是直接设置的,而是通过HttpServletResponse(Servlet技术)的sendRedirect方法,该方法同时设置状态 代码为302。
    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。如果请求中没有指定,那么其即为"/"。
res.redirect([status,] path)
重定向来源于指定path的URL,以及指定的HTTP status codestatus。如果你没有指定status,status code默认为"302 Found"。
res.render(view [, locals] [, callback])
渲染一个视图,然后将渲染得到的HTML文档发送给客户端。可选的参数为:
	// pass a local variable to  the view
		res.render('user', {name:'Tobi'}, function(err, html) {
		    // ...
		});
res.send([body])
发送HTTP响应。 body参数可以是一个Buffer对象,一个字符串,一个对象,或者一个数组。
res.sendFile(path [, options] [, fn])
    从Express v4.8.0开始支持。传输path指定的文件。根据文件的扩展名设置Content-TypeHTTP头部。除非在options中有关于root的设置,path一定是关于文件的绝对路径。 
当传输完成或者发生了什么错误,这个方法调用fn回调方法。如果这个回调参数指定了和一个错误发生,回调方法必须明确地通过结束请求-响应循环或者传递控制到下个路由来处理响应过程。 下面是使用了所有参数的使用res.sendFile()的例子:
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)   
设置响应对象的HTTP status code为statusCode并且发送statusCode的相应的字符串形式作为响应的Body。
 
     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])
设置响应对象的HTTP头部field为value。为了一次设置多个值,那么可以传递一个对象为参数。其和res.header(field [,value])效果一致。
res.status(code)
使用这个方法来设置响应对象的HTTP status
res.type(type)
如果参数type包含"/",那么就把参数type设置为Content-Type,否则通过mime.lookup()来获取mime type
res.vary(field)
设置Vary响应头为 field。"代理服务器缓存两种版本的资源:压缩和非压缩,这有助于避免一些公共代理不能正确地检测Content-Encoding标头的问题"。这和服务器端和 浏        览器端的 容协商有关。也就是说 Vary 字段用于列出一个响应字段列表,告诉 缓存服务器遇到同一个 URL 对应着不同版本文档的情况时,如何缓存和筛选合适的版本。而 不是对所有的相同的URL请求返回相同的 版本
Router对象
一个router对象是一个单独的实例关于中间件和路由。你可以认为其是一个"mini-application"(迷你程序),其具有操作中间件和路由方法的能力。每个Express程序有一个内建的app路由。 
路由自身表现为一个中间件,所以你可以使用它作为app.use()方法的一个参数或者作为另一个路由的use()的参数。 顶层的express对象有一个Router()方法,你可以使用Router()来创建一个新的router对象。
    var router = express.Router([options]);
router.all(path, [callback, ...] callback)
    这个方法和router.METHOD()方法一样,除了这个方法会匹配所有的HTTP动作。 这个方法对想映射全局的逻辑处理到特殊的路径前缀或者任意匹配是十分有用的。比如,如果你放置下面所示的这个路由在其他路由的前面,那么其将要求从这个点开始的所有的路由进行验证操作和自动加载用户信息。记住,这些全局的逻辑操作,不需要结束请求响应周期:loaduser可以执行一个任务,然后调用next()来将执行流程移交到随后的路由。
router.all('*', requireAuthentication, loadUser);
router.METHOD(path, [callback, ...] callback)
router.METHOD()方法提供了路由方法在Express中,这里的METHOD是HTTP方法中的一个,比如GET,PUT,POST等等,但router中的METHOD是小写的。所以,实际的方法是router.get(),router.put(),router.post()等等。 你可以提供多个回调函数,它们的行为和中间件一样,除了这些回调可以通过调用next('router')来绕过剩余的路由回调。你可以使用这个机制来为一个路由设置一些前提条件,如果请求没有满足当前路由的处理条件,那么传递控制到随后的路由。 
router.param(name, callback)
给路由参数添加回调触发器,这里的name是参数名,function是回调方法。回调方法的参数按序是请求对象,响应对象,下个中间件,参数值和参数名。虽然name在技术上是可选的,但是自Express V4.11.0之后版本不推荐使用。不像app.param(),router.param()不接受一个数组作为路由参
  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值