Node.js:ExpressWeb
路由
### 路由方法 ```javascript // GET method route app.get('/', function (req, res) { res.send('GET request to the homepage') }) // POST method route app.post('/', function (req, res) { res.send('POST request to the homepage') }) ``` | Method | Description | | ---------------- | ------------------------------------------------------------ | | res.download() | Prompt a file to be downloaded. | | res.end() | End the response process. | | res.json() | Send a JSON response. | | res.jsonp() | Send a JSON response with JSONP support. | | res.redirect() | Redirect a request. | | res.render() | Render a view template. | | res.send() | Send a response of various types. | | res.sendFile() | Send a file as an octet stream. | | res.sendStatus() | Set the response status code and send its string representation as the response body. | **Express 应用**对象还提供了为其他所有 HTTP 动词定义路由处理器的方法,大多数处理器的使用方式完全一致: > `checkout()`, `copy()`, **`delete()`**, **`get()`**, `head()`, `lock()`, `merge()`, `mkactivity()`, `mkcol()`, `move()`, `m-search()`, `notify()`, `options()`, `patch()`, **`post()`**, `purge()`, **`put()`**, `report()`, `search()`, `subscribe()`, `trace()`, `unlock()`, `unsubscribe()`. 有一个特殊的路由方法 **`app.all()`**,它可以在响应任意 HTTP 方法时调用。用于在特定路径上为所有请求方法加载中间件函数。以下示例中的处理程序将在监听到针对 `/secret` 的任意 HTTP 动词的请求后执行: ```js app.all("/secret", (req, res, next) => { console.log("访问私有文件 ..."); next(); // 控制权传递给下一个处理器 }); ``` ### 路由路径 > 路由路径与请求方法相结合,定义可以发出请求的端点。路由路径可以是字符串、字符串模式或正则表达式。 > > 字符`?`、`+`、`*`和`()`是其正则表达式对应项的子集。连字符 ( `-`) 和点 ( `.`) 按字面意思解释为基于字符串的路径。 > > 如果需要`$`在路径字符串中使用美元字符 ( ),请将其转义包含在`([`和内`])`。例如,“ `/data/$book`”处的请求的路径字符串将为“ `/data/([\$])book`”。 ```js //该路由路径将匹配对根路由 的请求/ app.get('/', function (req, res) { res.send('root') }) //该路由路径将匹配对 的请求/about app.get('/about', function (req, res) { res.send('about') }) //该路由路径将匹配对 的请求/random.text app.get('/random.text', function (req, res) { res.send('random.text') }) //该路由路径将匹配acd和abcd app.get('/ab?cd', function (req, res) { res.send('ab?cd') }) //该路由路径将匹配abcd、abbcd、abbbcd等 app.get('/ab+cd', function (req, res) { res.send('ab+cd') }) //该路由路径将匹配abcd、abxcd、abRANDOMcd、ab123cd等 app.get('/ab*cd', function (req, res) { res.send('ab*cd') }) //该路由路径将匹配/abe和/abcde app.get('/ab(cd)?e', function (req, res) { res.send('ab(cd)?e') }) //该路由路径将匹配其中包含“a”的任何内容 app.get(/a/, function (req, res) { res.send('/a/') }) //此路由路径将匹配butterfly和dragonfly,但不匹配butterflyman, dragonflyman,等等 app.get(/.*fly$/, function (req, res) { res.send('/.*fly$/') }) ``` ### 路由参数 路由参数是命名的 URL 段,用于捕获在 URL 中其位置指定的值。捕获的值填充在`req.params`对象中,路径中指定的路由参数的名称作为它们各自的键。 路由参数的名称必须由“单词字符”([A-Za-z0-9_])组成。 ```javascript app.get('/users/:userId/books/:bookId', function (req, res) { res.send(req.params) }) Route path: /users/:userId/books/:bookId Request URL: http://localhost:3000/users/34/books/8989 req.params: { "userId": "34", "bookId": "8989" } ``` ```js // 由于连字符 ( -) 和点 ( .) 按字面意思解释,因此它们可以与路由参数一起使用以达到有用的目的。 Route path: /flights/:from-:to Request URL: http://localhost:3000/flights/LAX-SFO req.params: { "from": "LAX", "to": "SFO" } Route path: /plantae/:genus.:species Request URL: http://localhost:3000/plantae/Prunus.persica req.params: { "genus": "Prunus", "species": "persica" } ``` ```js // 要更好地控制路由参数可以匹配的确切字符串,您可以在括号 ( ) 中附加正则表达式(): Route path: /user/:userId(\d+) Request URL: http://localhost:3000/user/42 req.params: {"userId": "42"} ``` > 由于正则表达式通常是文字字符串的一部分,因此请务必`\`使用附加反斜杠对任何字符进行转义,例如`\\d+`。 > 在 Express 4.x 中,正则表达式中的[字符`*`不会以通常的方式解释](https://github.com/expressjs/express/issues/2495)。作为解决方法,请使用`{0,}`代替`*`.这可能会在 Express 5 中得到修复。 ### 路线处理程序 > 路由方法可以有多个回调函数作为参数。对于多个回调函数,重要的是作为参数提供`next`给回调函数,然后`next()`在函数体内调用以将控制权移交给下一个回调。 ```javascript //单个回调函数可以处理一条路由。例如: app.get('/example/a', function (req, res) { res.send('Hello from A!') }) //多个回调函数可以处理一条路由(确保您指定了`next`对象)。例如: app.get('/example/b', function (req, res, next) { console.log('the response will be sent by the next function ...') next() }, function (req, res) { res.send('Hello from B!') }) ``` ```javascript //回调函数数组可以处理路由。例如: var cb0 = function (req, res, next) { console.log('CB0') next() } var cb1 = function (req, res, next) { console.log('CB1') next() } var cb2 = function (req, res) { res.send('Hello from C!') } app.get('/example/c', [cb0, cb1, cb2]) ``` ```javascript //独立函数和函数数组的组合可以处理一条路线。例如: var cb0 = function (req, res, next) { console.log('CB0') next() } var cb1 = function (req, res, next) { console.log('CB1') next() } app.get('/example/d', [cb0, cb1], function (req, res, next) { console.log('the response will be sent by the next function ...') next() }, function (req, res) { res.send('Hello from D!') }) ``` ### 应用程序.route() > 您可以使用 为路由路径创建可链接的路由处理程序`app.route()`。由于路径是在单个位置指定的,因此创建模块化路由很有帮助,可以减少冗余和拼写错误。 ```javascript app.route('/book') .get(function (req, res) { res.send('Get a random book') }) .post(function (req, res) { res.send('Add a book') }) .put(function (req, res) { res.send('Update the book') }) ``` ### router.param(name,callback) ```js 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')) } }) }) ``` ```js 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() }) ``` ```js 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') }) ``` ```js 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.use([path], [function, ...] function) ```js 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) ``` ```js 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') }) ``` ```js router.use(express.static(path.join(__dirname, 'public'))) router.use(express.static(path.join(__dirname, 'files'))) router.use(express.static(path.join(__dirname, 'uploads'))) ``` ```js 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) ```
顶部
收展
底部
[TOC]
目录
Express/Node 入门
路由
中间件
API接口 express()
API接口 app()
API接口 res()
API接口 Router()
数据库操作 ODM mongoose
相关推荐
Node.js教程:新手入门
Node.js接口
朴灵《深入浅出 Node.js》