express 4.x API

express()

创建一个express应用. The express() 函数是一个顶级函数通过express模块导出的.

var express = require('express')
var app = express()

express 函数

express.json([options])

v4.16.0及更高版本中提供了此中间件

下表描述了可选的`options’对象的属性。

PropertyDescriptionTypeDefault
inflate启用或禁用处理压缩的(压缩的)实体; 禁用时,放气的身体将被拒绝Booleantrue
limit控制最大请求正文大小。 如果这是一个数字,则该值指定字节数; 如果是字符串,则将值传递到[bytes]库进行解析Mixed"100kb"
reviverreviver选项被直接传递给JSON.parse作为第二个参数。 您可以在有关JSON.parse的MDN文档中找到有关此参数的更多信息。Functionnull
strict启用或禁用仅接受数组和对象; 禁用时将接受JSON.parse接受的任何内容。Booleantrue
type这用于确定中间件将解析的媒体类型。 此选项可以是字符串,字符串数组或函数。 如果不是函数,则将type选项直接传递给[type-is]库,它可以是扩展名(例如json),MIME类型(例如application / json)或mime类型。 带有通配符(例如* / ** / json)。 如果是函数,则将“类型”选项称为“ fn(req)”,如果请求返回真实值,则对该请求进行解析。Mixed"application/json"
verify如果提供此选项,则称为“ verify(req,res,buf,encoding)”,其中“ buf”是原始请求主体的“ Buffer”,而“ encoding”是请求的编码。 抛出错误可以中止解析。Functionundefined

express.raw([options])

Express v4.17.0及更高版本中提供了此中间件。

下表描述了可选的`options’对象的属性。

PropertyDescriptionTypeDefault
inflate启用或禁用处理压缩的(压缩的)实体; 禁用时,放气的身体将被拒绝。Booleantrue
limit控制最大请求正文大小。 如果这是一个数字,则该值指定字节数; 如果是字符串,则将值传递到[bytes]库进行解析。Mixed"100kb"
type这用于确定中间件将解析的媒体类型。 此选项可以是字符串,字符串数组或函数。 如果不是函数,则将type选项直接传递给[type-is]库,该库可以是扩展名(例如bin ),哑剧类型(如“ application / octet-stream”)或带有通配符的哑剧类型(如“ * / *”或“ application / *”)。 如果是函数,则将“类型”选项称为“ fn(req)”,如果请求返回真实值,则对该请求进行解析。 | Mixed |"application/octet-stream"`
verify如果提供此选项,则称为“ verify(req,res,buf,encoding)”,其中“ buf”是原始请求主体的“ Buffer”,而“ encoding”是请求的编码。 抛出错误可以中止解析。Functionundefined

express.Router([options])

创建一个新的router对象

var router = express.Router([options])

可选的“选项”参数指定路由器的行为。

PropertyDescriptionDefaultAvailability
caseSensitiveEnable case sensitivity.启用区分大小写。Disabled by default, treating “/Foo” and “/foo” as the same.
mergeParams保留父路由器的req.params值。 如果父母和孩子的参数名称冲突,则以孩子的值为准。false4.5.0+
strictEnable strict routing.启用严格路由。Disabled by default, “/foo” and “/foo/” are treated the same by the router.

express.static(root, [options])

下表描述了`options’对象的属性。 另请参见以下示例。

PropertyDescriptionTypeDefault
dotfiles确定如何处理点文件(以点“.”开头的文件或目录)。String“ignore”
etag启用或禁用etag生成,注意:express.static总是发送弱ETag。Booleantrue
extensions设置文件扩展名后备:如果未找到文件,请搜索具有指定扩展名的文件并提供找到的第一个文件。 例如:['html','htm']Mixedfalse
fallthrough让客户端错误作为未处理的请求进入,否则转发客户端错误。Booleantrue
immutable在“ Cache-Control”响应头中启用或禁用“ immutable”指令。 如果启用,还应指定“ maxAge”选项以启用缓存。 immutable指令将阻止受支持的客户端在maxAge选项有效期内发出条件请求,以检查文件是否已更改。Booleanfalse
index发送指定的目录索引文件。 设置为false禁用目录索引。Mixed“index.html”
lastModified将“ Last-Modified”标头设置为操作系统上文件的最后修改日期。Booleantrue
maxAge设置Cache-Control标头的max-age属性(以毫秒为单位)或以[ms]设置的字符串。Number0
redirect当路径名是目录时,重定向到结尾的“ /”。Booleantrue
setHeaders设置HTTP标头以与文件一起使用的功能。Function
dotfiles

Possible values for this option are:该选项的可能值为:

  • “allow” -对点文件没有特殊处理。
  • “deny” -拒绝对点文件的请求,以“ 403”响应,然后调用“ next()”。
  • “ignore” - 就像点文件不存在一样,以“ 404”响应,然后调用“ next()”。

NOTE: 使用默认值时,它将不会忽略以点开头的目录中的文件。

fallthrough

如果此选项为“ true”,则客户端错误(例如错误请求或对不存在文件的请求)将导致该中间件仅调用next()来调用堆栈中的下一个中间件。 如果为假,则这些错误(甚至是404错误)将调用“ next(err)”。

将此选项设置为“ true”,以便您可以将多个物理目录映射到同一网址,或用于路由以填充不存在的文件。

如果已将此中间件安装在严格设计为单个文件系统目录的路径上,请使用“ false”,这可以使404短路以减少开销。 该中间件还将答复所有方法。

setHeaders

对于此选项,指定一个函数来设置自定义响应头。 标头的更改必须同步进行。

该函数的签名是:

fn(res, path, stat)

Arguments:

  • res, the response object.
  • path,正在发送的文件路径。
  • stat, 发送文件的stat对象。
Example of express.static

这是将“ express.static”中间件功能与精心设计的options对象结合使用的示例:

var options = {
  dotfiles: 'ignore',
  etag: false,
  extensions: ['htm', 'html'],
  index: false,
  maxAge: '1d',
  redirect: false,
  setHeaders: function (res, path, stat) {
    res.set('x-timestamp', Date.now())
  }
}

app.use(express.static('public', options))

express.text([options])

4.17.0开始启用.

PropertyDescriptionTypeDefault
defaultCharsetSpecify the default character set for the text content if the charset is not specified in the Content-Type header of the request.String"utf-8"
inflateEnables or disables handling deflated (compressed) bodies; when disabled, deflated bodies are rejected.Booleantrue
limitControls the maximum request body size. If this is a number, then the value specifies the number of bytes; if it is a string, the value is passed to the bytes library for parsing.Mixed"100kb"
typeThis is used to determine what media type the middleware will parse. This option can be a string, array of strings, or a function. If not a function, type option is passed directly to the type-is library and this can be an extension name (like txt), a mime type (like text/plain), or a mime type with a wildcard (like */* or text/*). If a function, the type option is called as fn(req) and the request is parsed if it returns a truthy value.Mixed"text/plain"
verifyThis option, if supplied, is called as verify(req, res, buf, encoding), where buf is a Buffer of the raw request body and encoding is the encoding of the request. The parsing can be aborted by throwing an error.Functionundefined

express.urlencoded([options])

v4.16.0 开始启用

PropertyDescriptionTypeDefault
extendedThis option allows to choose between parsing the URL-encoded data with the querystring library (when false) or the qs library (when true). The “extended” syntax allows for rich objects and arrays to be encoded into the URL-encoded format, allowing for a JSON-like experience with URL-encoded. For more information, please see the qs library.Booleantrue
inflateEnables or disables handling deflated (compressed) bodies; when disabled, deflated bodies are rejected.Booleantrue
limitControls the maximum request body size. If this is a number, then the value specifies the number of bytes; if it is a string, the value is passed to the bytes library for parsing.Mixed"100kb"
parameterLimitThis option controls the maximum number of parameters that are allowed in the URL-encoded data. If a request contains more parameters than this value, an error will be raised.Number1000
typeThis is used to determine what media type the middleware will parse. This option can be a string, array of strings, or a function. If not a function, type option is passed directly to the type-is library and this can be an extension name (like urlencoded), a mime type (like application/x-www-form-urlencoded), or a mime type with a wildcard (like */x-www-form-urlencoded). If a function, the type option is called as fn(req) and the request is parsed if it returns a truthy value.Mixed"application/x-www-form-urlencoded"
verifyThis option, if supplied, is called as verify(req, res, buf, encoding), where buf is a Buffer of the raw request body and encoding is the encoding of the request. The parsing can be aborted by throwing an error.Functionundefined

Application

var express = require('express')
var app = express()

app.get('/', function (req, res) {
  res.send('hello world')
})

app.listen(3000)

app对象有以下函数:

app 属性

app.locals

app整个生命周期:

console.dir(app.locals.title)
// => 'My App'

console.dir(app.locals.email)
// => 'me@myapp.com'
app.locals.title = 'My App'
app.locals.strftime = require('strftime')
app.locals.email = 'me@myapp.com'

app.mountpath

var express = require('express')

var app = express() // the main app
var admin = express() // the sub app

admin.get('/', function (req, res) {
  console.log(admin.mountpath) // /admin
  res.send('Admin Homepage')
})

app.use('/admin', admin) // mount the sub app
var admin = express()

admin.get('/', function (req, res) {
  console.dir(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

Events

app.on(‘mount’, callback(parent))

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 函数

app.all(path, callback [, callback …])

app.all('/secret', function (req, res, next) {
  console.log('Accessing the secret section ...')
  next() // pass control to the next handler
})
app.all('*', requireAuthentication, loadUser)
app.all('*', requireAuthentication)
app.all('*', loadUser)
app.all('/api/*', requireAuthentication)

app.delete(path, callback [, callback …])

app.delete('/', function (req, res) {
  res.send('DELETE request to homepage')
})

app.disable(name)

app.disable('trust proxy')
app.get('trust proxy')
// => false

app.disabled(name)

app.disabled('trust proxy')
// => true

app.enable('trust proxy')
app.disabled('trust proxy')
// => false

app.enable(name)

app.enable('trust proxy')
app.get('trust proxy')
// => true

app.enabled(name)

app.enabled('trust proxy')
// => false

app.enable('trust proxy')
app.enabled('trust proxy')
// => true

app.engine(ext, callback)

app.engine('pug', require('pug').__express)
app.engine('html', require('ejs').renderFile)
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(path, [callback])

var express = require('express')
var app = express()
app.listen('/tmp/sock')

app.listen([port[, host[, backlog]]][, callback])

var express = require('express')
var app = express()
app.listen(3000)
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 = function () {
  var server = http.createServer(this)
  return server.listen.apply(server, arguments)
}

app.METHOD(path, callback [, callback …])

app.param([name], callback)

app.param('user', function (req, res, next, id) {
  // try to get the user details from the User model and attach it to the request object
  User.find(id, function (err, user) {
    if (err) {
      next(err)
    } else if (user) {
      req.user = user
      next()
    } else {
      next(new Error('failed to load user'))
    }
  })
})
app.param('id', function (req, res, next, id) {
  console.log('CALLED ONLY ONCE')
  next()
})

app.get('/user/:id', function (req, res, next) {
  console.log('although this matches')
  next()
})

app.get('/user/:id', function (req, res) {
  console.log('and this matches too')
  res.end()
})
app.get('/user/:id/:page', function (req, res) {
  console.log('and this matches too')
  res.end()
})
var express = require('express')
var app = express()

// customizing the behavior of app.param()
app.param(function (param, option) {
  return function (req, res, next, val) {
    if (val === option) {
      next()
    } else {
      next('route')
    }
  }
})

// using the customized app.param()
app.param('id', 1337)

// route to trigger the capture
app.get('/user/:id', function (req, res) {
  res.send('OK')
})

app.listen(3000, function () {
  console.log('Ready')
})
app.param(function (param, validator) {
  return function (req, res, next, val) {
    if (validator(val)) {
      next()
    } else {
      next('route')
    }
  }
})

app.param('id', function (candidate) {
  return !isNaN(parseFloat(candidate)) && isFinite(candidate)
})

Examples:

//captures '1-a_6' but not '543-azser-sder'
router.get('/[0-9]+-[[\\w]]*', function);

//captures '1-a_6' and '543-az(ser"-sder' but not '5-a s'
router.get('/[0-9]+-[[\\S]]*', function);

//captures all (equivalent to '.*')
router.get('[[\\s\\S]]*', function);

app.path()

var app = express()
var blog = express()
var blogAdmin = express()

app.use('/blog', blog)
blog.use('/admin', blogAdmin)

console.dir(app.path()) // ''
console.dir(blog.path()) // '/blog'
console.dir(blogAdmin.path()) // '/blog/admin'

app.render(view, [locals], callback)

app.render('email', function (err, html) {
  // ...
})

app.render('email', { name: 'Tobi' }, function (err, html) {
  // ...
})

app.route(path)

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...
  })

app.set(name, value)

app.set('title', 'My Site')
app.get('title') // "My Site"

app.use([path,] callback [, callback…])

path不传默认为"/"

app.use(function (req, res, next) {
  console.log('Time: %d', Date.now())
  next()
})
// this middleware will not allow the request to go beyond it
app.use(function (req, res, next) {
  res.send('Hello World')
})

// requests will never reach this route
app.get('/', function (req, res) {
  res.send('Welcome')
})
app.use(function (err, req, res, next) {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})
// GET /style.css etc
app.use(express.static(path.join(__dirname, 'public')))
// GET /static/style.css etc.
app.use('/static', express.static(path.join(__dirname, 'public')))
app.use(express.static(path.join(__dirname, 'public')))
app.use(logger())
app.use(express.static(path.join(__dirname, 'public')))
app.use(express.static(path.join(__dirname, 'files')))
app.use(express.static(path.join(__dirname, 'uploads')))

Request

app.get('/user/:id', function (req, res) {
  res.send('user ' + req.params.id)
})
app.get('/user/:id', function (request, response) {
  response.send('user ' + request.params.id)
})

Properties

在Express 4中,默认情况下,“ req.files”在“ req”对象上不再可用。 要访问“ req.files”对象上的上传文件,请使用多部分处理中间件,例如 busboy, multer, formidable, multiparty, connect-multiparty, or pez.

req.app

// index.js
app.get('/viewdirectory', require('./mymiddleware.js'))
// mymiddleware.js
module.exports = function (req, res) {
  res.send('The views directory is ' + req.app.get('views'))
}

req.baseUrl

var greet = express.Router()

greet.get('/jp', function (req, res) {
  console.log(req.baseUrl) // /greet
  res.send('Konichiwa!')
})

app.use('/greet', greet) // load the router on '/greet'
app.use(['/gre+t', '/hel{2}o'], greet) // load the router on '/gre+t' and '/hel{2}o'

req.body

var express = require('express')

var app = express()

app.use(express.json()) // for parsing application/json
app.use(express.urlencoded({ extended: true })) // for parsing application/x-www-form-urlencoded

app.post('/profile', function (req, res, next) {
  console.log(req.body)
  res.json(req.body)
})

req.cookies

// Cookie: name=tj
console.dir(req.cookies.name)
// => 'tj'

req.fresh

console.dir(req.fresh)
// => true

req.hostname

// Host: "example.com:3000"
console.dir(req.hostname)
// => 'example.com'

req.ip

console.dir(req.ip)
// => '127.0.0.1'

req.ips

req.method

req.originalUrl

// GET /search?q=something
console.dir(req.originalUrl)
// => '/search?q=something'
app.use('/admin', function (req, res, next) { // GET 'http://www.example.com/admin/new'
  console.dir(req.originalUrl) // '/admin/new'
  console.dir(req.baseUrl) // '/admin'
  console.dir(req.path) // '/new'
  next()
})

req.params

// GET /user/tj
console.dir(req.params.name)
// => 'tj'
// GET /file/javascripts/jquery.js
console.dir(req.params[0])
// => 'javascripts/jquery.js'

req.path

// example.com/users?sort=desc
console.dir(req.path)
// => '/users'

req.protocol

console.dir(req.protocol)
// => 'http'

req.query

// GET /search?q=tobi+ferret
console.dir(req.query.q)
// => 'tobi ferret'

// GET /shoes?order=desc&shoe[color]=blue&shoe[type]=converse
console.dir(req.query.order)
// => 'desc'

console.dir(req.query.shoe.color)
// => 'blue'

console.dir(req.query.shoe.type)
// => 'converse'

// GET /shoes?color[]=blue&color[]=black&color[]=red
console.dir(req.query.color)
// => ['blue', 'black', 'red']

req.route

app.get('/user/:id?', function userIdHandler (req, res) {
  console.log(req.route)
  res.send('GET')
})
{ path: '/user/:id?',
  stack:
   [ { handle: [Function: userIdHandler],
       name: 'userIdHandler',
       params: undefined,
       path: undefined,
       keys: [],
       regexp: /^\/?$/i,
       method: 'get' } ],
  methods: { get: true } }

req.secure

console.dir(req.protocol === 'https')
// => true

req.signedCookies

// Cookie: user=tobi.CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3
console.dir(req.signedCookies.user)
// => 'tobi'

req.stale

console.dir(req.stale)
// => true

req.subdomains

// Host: "tobi.ferrets.example.com"
console.dir(req.subdomains)
// => ['ferrets', 'tobi']

req.xhr

console.dir(req.xhr)
// => true

Methods

req.accepts(types)

// 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')
// => false

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

req.acceptsCharsets(charset [, …])

req.acceptsEncodings(encoding [, …])

req.acceptsLanguages(lang [, …])

req.get(field)

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

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

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

req.is(type)

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

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

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

req.param(name [, defaultValue])

// ?name=tobi
req.param('name')
// => "tobi"

// POST name=tobi
req.param('name')
// => "tobi"

// /user/tobi for /user/:name
req.param('name')
// => "tobi"

req.range(size[, options])

// parse header from request
var range = req.range(1000)

// the type of the range
if (range.type === 'bytes') {
  // the ranges
  range.forEach(function (r) {
    // do something with r.start and r.end
  })
}

Response

For example:

app.get('/user/:id', function (req, res) {
  res.send('user ' + req.params.id)
})

But you could just as well have:

app.get('/user/:id', function (request, response) {
  response.send('user ' + request.params.id)
})

Response属性

res.app

res.headersSent

app.get('/', function (req, res) {
  console.dir(res.headersSent) // false
  res.send('OK')
  console.dir(res.headersSent) // true
})

res.locals

app.use(function (req, res, next) {
  res.locals.user = req.user
  res.locals.authenticated = !req.user.anonymous
  next()
})

Response函数

res.append(field [, value])

res.append('Link', ['<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/png

res.cookie(name, value [, options])

PropertyTypeDescription
domainStringDomain name for the cookie. Defaults to the domain name of the app.
encodeFunctionA synchronous function used for cookie value encoding. Defaults to encodeURIComponent.
expiresDateExpiry date of the cookie in GMT. If not specified or set to 0, creates a session cookie.
httpOnlyBooleanFlags the cookie to be accessible only by the web server.
maxAgeNumberConvenient option for setting the expiry time relative to the current time in milliseconds.
pathStringPath for the cookie. Defaults to “/”.
secureBooleanMarks the cookie to be used with HTTPS only.
signedBooleanIndicates if the cookie should be signed.
sameSiteBoolean or StringValue of the “SameSite” Set-Cookie attribute. More information at https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00#section-4.1.1.
res.cookie('name', 'tobi', { domain: '.example.com', path: '/admin', secure: true })
res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true })
res
  .status(201)
  .cookie('access_token', 'Bearer ' + token, {
    expires: new Date(Date.now() + 8 * 3600000) // cookie will be removed after 8 hours
  })
  .cookie('test', 'test')
  .redirect(301, '/admin')
// Default encoding
res.cookie('some_cross_domain_cookie', 'http://mysubdomain.example.com', { domain: 'example.com' })
// Result: 'some_cross_domain_cookie=http%3A%2F%2Fmysubdomain.example.com; Domain=example.com; Path=/'

// Custom encoding
res.cookie('some_cross_domain_cookie', 'http://mysubdomain.example.com', { domain: 'example.com', encode: String })
// Result: 'some_cross_domain_cookie=http://mysubdomain.example.com; Domain=example.com; Path=/;'
res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true })
res.cookie('cart', { items: [1, 2, 3] })
res.cookie('cart', { items: [1, 2, 3] }, { maxAge: 900000 })
res.cookie('name', 'tobi', { signed: true })

res.clearCookie(name [, options])

res.cookie('name', 'tobi', { path: '/admin' })
res.clearCookie('name', { path: '/admin' })

res.download(path [, filename] [, options] [, fn])

res.download('/report-12345.pdf')

res.download('/report-12345.pdf', 'report.pdf')

res.download('/report-12345.pdf', 'report.pdf', function (err) {
  if (err) {
    // Handle error, but keep in mind the response may be partially-sent
    // so check res.headersSent
  } else {
    // decrement a download credit, etc.
  }
})

res.end([data] [, encoding])

res.end()
res.status(404).end()

res.format(object)

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 () {
    // log the request and respond with 406
    res.status(406).send('Not Acceptable')
  }
})
res.format({
  text: function () {
    res.send('hey')
  },

  html: function () {
    res.send('<p>hey</p>')
  },

  json: function () {
    res.send({ message: 'hey' })
  }
})

res.get(field)

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

res.json([body])

res.json(null)
res.json({ user: 'tobi' })
res.status(500).json({ error: 'message' })

res.jsonp([body])

res.jsonp(null)
// => callback(null)

res.jsonp({ user: 'tobi' })
// => callback({ "user": "tobi" })

res.status(500).jsonp({ error: 'message' })
// => callback({ "error": "message" })
// ?callback=foo
res.jsonp({ user: 'tobi' })
// => foo({ "user": "tobi" })

app.set('jsonp callback name', 'cb')

// ?cb=foo
res.status(500).jsonp({ error: 'message' })
// => foo({ "error": "message" })

res.links(links)

res.links({
  next: 'http://api.example.com/users?page=2',
  last: 'http://api.example.com/users?page=5'
})
Link: <http://api.example.com/users?page=2>; rel="next",
      <http://api.example.com/users?page=5>; rel="last"

res.location(path)

res.location('/foo/bar')
res.location('http://example.com')
res.location('back')

res.redirect([status,] path)

res.redirect('/foo/bar')
res.redirect('http://example.com')
res.redirect(301, 'http://example.com')
res.redirect('../login')
res.redirect('http://google.com')
res.redirect('/admin')
res.redirect('post/new')
res.redirect('..')
res.redirect('back')

res.render(view [, locals] [, callback])

// 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) {
  // ...
})

res.send([body])

res.send(Buffer.from('whoop'))
res.send({ some: 'json' })
res.send('<p>some html</p>')
res.status(404).send('Sorry, we cannot find that!')
res.status(500).send({ error: 'something blew up' })
res.set('Content-Type', 'text/html')
res.send(Buffer.from('<p>some html</p>'))
res.send('<p>some html</p>')
res.send({ user: 'tobi' })
res.send([1, 2, 3])

res.sendFile(path [, options] [, fn])

PropertyDescriptionDefaultAvailability
maxAgeSets the max-age property of the Cache-Control header in milliseconds or a string in ms format0
rootRoot directory for relative filenames.
lastModifiedSets the Last-Modified header to the last modified date of the file on the OS. Set false to disable it.Enabled4.9.0+
headersObject containing HTTP headers to serve with the file.
dotfilesOption for serving dotfiles. Possible values are “allow”, “deny”, “ignore”.“ignore”
acceptRangesEnable or disable accepting ranged requests.true4.14+
cacheControlEnable or disable setting Cache-Control response header.true4.14+
immutableEnable or disable the immutable directive in the Cache-Control response header. If enabled, the maxAge option should also be specified to enable caching. The immutable directive will prevent supported clients from making conditional requests during the life of the maxAge option to check if the file has changed.false4.16+
app.get('/file/:name', function (req, res, next) {
  var options = {
    root: path.join(__dirname, 'public'),
    dotfiles: 'deny',
    headers: {
      'x-timestamp': Date.now(),
      'x-sent': true
    }
  }

  var fileName = req.params.name
  res.sendFile(fileName, options, function (err) {
    if (err) {
      next(err)
    } else {
      console.log('Sent:', fileName)
    }
  })
})
app.get('/user/:uid/photos/:file', function (req, res) {
  var uid = req.params.uid
  var file = req.params.file

  req.user.mayViewFilesFrom(uid, function (yes) {
    if (yes) {
      res.sendFile('/uploads/' + uid + '/' + file)
    } else {
      res.status(403).send("Sorry! You can't see that.")
    }
  })
})

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')
res.sendStatus(9999) // equivalent to res.status(9999).send('9999')

res.set(field [, value])

res.set('Content-Type', 'text/plain')

res.set({
  'Content-Type': 'text/plain',
  'Content-Length': '123',
  ETag: '12345'
})

res.status(code)

res.status(403).end()
res.status(400).send('Bad Request')
res.status(404).sendFile('/absolute/path/to/404.png')

res.type(type)

res.type('.html')
// => 'text/html'
res.type('html')
// => 'text/html'
res.type('json')
// => 'application/json'
res.type('application/json')
// => 'application/json'
res.type('png')
// => 'image/png'

res.vary(field)

res.vary('User-Agent').render('docs')

Router(路由)

express有一个Router()函数,创建一个新的router对象

var router = express.Router()
// invoked for any requests passed to this router
router.use(function (req, res, next) {
  // .. some logic here .. like any other middleware
  next()
})

// will handle any request that ends in /events
// depends on where the router is "use()'d"
router.get('/events', function (req, res, next) {
  // ..
})
// only requests to /calendar/* will be sent to our "router"
app.use('/calendar', router)

Router函数

router.all(path, [callback, …] callback)

router.all('*', requireAuthentication, loadUser)
router.all('*', requireAuthentication)
router.all('*', loadUser)
router.all('/api/*', requireAuthentication)

router.METHOD(path, [callback, …] callback)

router.get('/', function (req, res) {
  res.send('hello world')
})
router.get(/^\/commits\/(\w+)(?:\.\.(\w+))?$/, function (req, res) {
  var from = req.params[0]
  var to = req.params[1] || 'HEAD'
  res.send('commit range ' + from + '..' + to)
})

router.param(name, callback)

router.param('user', function (req, res, next, id) {
  // try to get the user details from the User model and attach it to the request object
  User.find(id, function (err, user) {
    if (err) {
      next(err)
    } else if (user) {
      req.user = user
      next()
    } else {
      next(new Error('failed to load user'))
    }
  })
})
router.param('id', function (req, res, next, id) {
  console.log('CALLED ONLY ONCE')
  next()
})

router.get('/user/:id', function (req, res, next) {
  console.log('although this matches')
  next()
})

router.get('/user/:id', function (req, res) {
  console.log('and this matches too')
  res.end()
})

On GET /user/42, the following is printed:

CALLED ONLY ONCE
although this matches
and this matches too
var express = require('express')
var app = express()
var router = express.Router()

// customizing the behavior of router.param()
router.param(function (param, option) {
  return function (req, res, next, val) {
    if (val === option) {
      next()
    } else {
      res.sendStatus(403)
    }
  }
})

// using the customized router.param()
router.param('id', '1337')

// route to trigger the capture
router.get('/user/:id', function (req, res) {
  res.send('OK')
})

app.use(router)

app.listen(3000, function () {
  console.log('Ready')
})
router.param(function (param, validator) {
  return function (req, res, next, val) {
    if (validator(val)) {
      next()
    } else {
      res.sendStatus(403)
    }
  }
})

router.param('id', function (candidate) {
  return !isNaN(parseFloat(candidate)) && isFinite(candidate)
})

router.route(path)

var router = express.Router()

router.param('user_id', function (req, res, next, id) {
  // sample user, would actually fetch from DB, etc...
  req.user = {
    id: id,
    name: 'TJ'
  }
  next()
})

router.route('/users/:user_id')
  .all(function (req, res, next) {
    // runs for all HTTP verbs first
    // think of it as route specific middleware!
    next()
  })
  .get(function (req, res, next) {
    res.json(req.user)
  })
  .put(function (req, res, next) {
    // just an example of maybe updating the user
    req.user.name = req.params.name
    // save user ... etc
    res.json(req.user)
  })
  .post(function (req, res, next) {
    next(new Error('not implemented'))
  })
  .delete(function (req, res, next) {
    next(new Error('not implemented'))
  })
var express = require('express')
var app = express()
var router = express.Router()

// simple logger for this router's requests
// all requests to this router will first hit this middleware
router.use(function (req, res, next) {
  console.log('%s %s %s', req.method, req.url, req.path)
  next()
})

// this will only be invoked if the path starts with /bar from the mount point
router.use('/bar', function (req, res, next) {
  // ... maybe some additional /bar logging ...
  next()
})

// always invoked
router.use(function (req, res, next) {
  res.send('Hello World')
})

app.use('/foo', router)

app.listen(3000)
var logger = require('morgan')
var path = require('path')

router.use(logger())
router.use(express.static(path.join(__dirname, 'public')))
router.use(function (req, res) {
  res.send('Hello')
})
router.use(express.static(path.join(__dirname, 'public')))
router.use(logger())
router.use(function (req, res) {
  res.send('Hello')
})
router.use(express.static(path.join(__dirname, 'public')))
router.use(express.static(path.join(__dirname, 'files')))
router.use(express.static(path.join(__dirname, 'uploads')))
var authRouter = express.Router()
var openRouter = express.Router()

authRouter.use(require('./authenticate').basic(usersdb))

authRouter.get('/:user_id/edit', function (req, res, next) {
  // ... Edit user UI ...
})
openRouter.get('/', function (req, res, next) {
  // ... List users ...
})
openRouter.get('/:user_id', function (req, res, next) {
  // ... View user ...
})

app.use('/users', authRouter)
app.use('/users', openRouter)
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐