Request

Request

req.params

这是一个数组对象,命名过的参数会以键值对的形式存放。 比如你有一个路由/user/:name, “name”属性会存放在req.params.name. 这个对象默认为 {}.

// GET /user/tj
req.params.name
// => "tj"

当使用正则表达式定义路由的时候,req.params[N]会是这个应用这个正则后的捕获分组, N 是代表的是第N个捕获分组。这个规则同样适用于全匹配的路由,如 /file/*:

// GET /file/javascripts/jquery.js
req.params[0]
// => "javascripts/jquery.js"

req.query

这是一个解析过的请求参数对象,默认为{}.

// GET /search?q=tobi+ferret
req.query.q
// => "tobi ferret"

// GET /shoes?order=desc&shoe[color]=blue&shoe[type]=converse
req.query.order
// => "desc"

req.query.shoe.color
// => "blue"

req.query.shoe.type
// => "converse"

req.body

这个对应的是解析过的请求体。这个特性是bodyParser() 中间件提供,其它的请求体解析中间件可以放在这个中间件之后。当bodyParser()中间件使用后,这个对象默认为 {}。

// POST user[name]=tobi&user[email]=tobi@learnboost.com
req.body.user.name
// => "tobi"

req.body.user.email
// => "tobi@learnboost.com"

// POST { "name": "tobi" }
req.body.name
// => "tobi"

req.files

这是上传的文件的对象。这个特性是bodyParser() 中间件提供,其它的请求体解析中间件可以放在这个中间件之后。当bodyParser()中间件使用后,这个对象默认为 {}。

例如 file 字段被命名为“image”, 当一个文件上传完成后,req.files.image 将会包含下面的 File 对象:

{ size: 74643,
  path: '/tmp/8ef9c52abe857867fd0a4e9a819d1876',
  name: 'edge.png',
  type: 'image/png',
  hash: false,
  lastModifiedDate: Thu Aug 09 2012 20:07:51 GMT-0700 (PDT),
  _writeStream:
   { path: '/tmp/8ef9c52abe857867fd0a4e9a819d1876',
     fd: 13,
     writable: false,
     flags: 'w',
     encoding: 'binary',
     mode: 438,
     bytesWritten: 74643,
     busy: false,
     _queue: [],
     _open: [Function],
     drainable: true },
  length: [Getter],
  filename: [Getter],
  mime: [Getter] }

bodyParser() 中间件是在内部使用node-formidable来处理文件请求,所以接收的参数是一致的。 举个例子,使用formidable的选项keepExtensions , 它默认为 false , 在上面的例子可以看到给出的文件名“/tmp/8ef9c52abe857867fd0a4e9a819d1876” 不包含”.png“ 扩展名. 为了让它可以保留扩展名,你可以把参数传给 bodyParser():

app.use(express.bodyParser({ keepExtensions: true, uploadDir: '/my/files' }));

req.param(name)

返回 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 直接访问 req.body, req.params, 和 req.query 应该更合适,除非你真的需要从这几个对象里同时接受输入。

req.route

这个对象里是当前匹配的 Route 里包含的属性,比如原始路径字符串,产生的正则,等等

app.get('/user/:id?', function(req, res){
  console.log(req.route);
});

上面代码的一个输出:

{ path: '/user/:id?',
  method: 'get',
  callbacks: [ [Function] ],
  keys: [ { name: 'id', optional: true } ],
  regexp: /^\/user(?:\/([^\/]+?))?\/?$/i,
  params: [ id: '12' ] }

req.cookies

当使用 cookieParser()中间件之后,这个对象默认为{}, 它也包含了用户代理传过来的cookies。

// Cookie: name=tj
req.cookies.name
// => "tj"

req.signedCookies

当使用了cookieParser(secret) 中间件后,这个对象默认为{}, 否则包含了用户代理传回来的签名后的cookie,并等待使用。签名后的cookies被放在一个单独的对象里,恶意攻击者可以很简单的替换掉req.cookie 的值。需要注意的是签名的cookie不代表它是隐藏的或者加密的,这个只是简单的阻止篡改cookie。

// Cookie: user=tobi.CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3
req.signedCookies.user
// => "tobi"

req.get(field)

获取请求头里的field的值,大小写不敏感. Referrer 和 Referer 字段是可以互换的。

req.get('Content-Type');
// => "text/plain"

req.get('content-type');
// => "text/plain"

req.get('Something');
// => undefined

别名为 req.header(field).

req.accepts(types)

. 检查给定的types 是不是可以接受类型,当可以接受时返回最匹配的,否则返回undefined - 这个时候你应该响应一个406 “Not Acceptable”.

type 的值可能是单一的一个mime类型字符串,比如 “application/json”, 扩展名为”json“, 也可以为逗号分隔的列表或者数组。当给定的是数组或者列表,返回 最佳 匹配的。

// Accept: text/html
req.accepts('html');
// => "html"

// Accept: text/*, application/json
req.accepts('html');
// => "html"
req.accepts('text/html');
// => "text/html"
req.accepts('json, text');
// => "json"
req.accepts('application/json');
// => "application/json"

// Accept: text/*, application/json
req.accepts('image/png');
req.accepts('png');
// => undefined

// Accept: text/*;q=.5, application/json
req.accepts(['html', 'json']);
req.accepts('html, json');
// => "json"

req.accepted

返回一个从高质量到低质量排序的接受媒体类型数组

[ { value: 'application/json',
    quality: 1,
    type: 'application',
    subtype: 'json' },
{ value: 'text/html',
     quality: 0.5,
     type: 'text',
     subtype: 'html' } ]

req.is(type)

检查请求的文件头是不是包含“Content-Type” 字段, 它匹配给定的type.

// With Content-Type: text/html; charset=utf-8
req.is('html');
req.is('text/html');
req.is('text/*');
// => true

// When Content-Type is application/json
req.is('json');
req.is('application/json');
req.is('application/*');
// => true

req.is('html');
// => false

req.ip

返回远程地址,或者当“信任代理”使用时,返回上一级的地址

req.ip
// => "127.0.0.1"

req.ips

当设置“trust proxy” 为 true时, 解析”X-Forwarded-For“ 里的ip地址列表,并返回一个数组 否则返回一个空数组 举个例子,如果“X-Forwarded-For” 的值为”client, proxy1, proxy2“ 你将会得到数组["client", "proxy1", "proxy2"] 这里可以看到 “proxy2” 是最近一个使用的代理

req.path

返回请求的URL的路径名

// example.com/users?sort=desc
req.path
// => "/users"

req.host

返回从“Host”请求头里取的主机名,不包含端口号。

// Host: "example.com:3000"
req.host
// => "example.com"

req.fresh

判断请求是不是新的-通过对Last-Modified 或者 ETag 进行匹配, 来标明这个资源是不是“新的”.

req.fresh
// => true

req.stale

判断请求是不是旧的-如果Last-Modified 或者 ETag 不匹配, 标明这个资源是“旧的”. Check if the request is stale - aka Last-Modified and/or the ETag do not match, indicating that the resource is ”stale“.

req.stale
// => true

req.xhr

判断请求头里是否有“X-Requested-With”这样的字段并且值为”XMLHttpRequest“, jQuery等库发请求时会设置这个头

req.xhr
// => true

req.protocol

返回标识请求协议的字符串,一般是“http”,当用TLS请求的时候是”https“。 当“trust proxy” 设置被激活, ”X-Forwarded-Proto“ 头部字段会被信任。 如果你使用了一个支持https的反向代理,那这个可能是激活的。

req.protocol
// => "http"

req.secure

检查TLS 连接是否已经建立。 这是下面的缩写:

'https' == req.protocol;

req.subdomains

把子域当作一个数组返回

// Host: "tobi.ferrets.example.com"
req.subdomains
// => ["ferrets", "tobi"]

req.originalUrl

这个属性很像 req.url, 但是它保留了原始的url。 这样你在做内部路由的时候可以重写req.url。 比如app.use()的挂载功能会重写 req.url,把从它挂载的点开始

// GET /search?q=something
req.originalUrl
// => "/search?q=something"

req.acceptedLanguages

返回一个从高质量到低质量排序的接受语言数组

Accept-Language: en;q=.5, en-us
// => ['en-us', 'en']

req.acceptedCharsets

返回一个从高质量到低质量排序的可接受的字符集数组

Accept-Charset: iso-8859-5;q=.2, unicode-1-1;q=0.8
// => ['unicode-1-1', 'iso-8859-5']

req.acceptsCharset(charset)

检查给定的charset 是不是可以接受的

req.acceptsLanguage(lang)

检查给定的 lang 是不是可以接受的