Sails 允许您在 config/routes.js 文件中以几种不同的方式显式路由 URL。每个路由配置都包含一个 地址 和一个 目标,例如
'GET /foo/bar': 'UserController.subscribe'
^^^address^^^ ^^^^^^^^^^target^^^^^^^^^^
路由地址指示为了应用由目标定义的处理程序和选项而应匹配哪个 URL。路由由一个可选的动词和一个必填的路径组成
'POST /foo/bar'
^verb^ ^^path^^
如果没有指定动词,则路由将匹配任何 CRUD 方法(GET、PUT、POST、DELETE 或 PATCH)。如果将 ALL
指定为动词,则路由将匹配任何方法。
请注意路径中的初始 /
- 所有路径都应以一个开头才能正常工作。
除了指定像 foo/bar 这样的静态路径外,您还可以使用 *
作为通配符
'/*'
将匹配所有路径,而
'/user/foo/*'
将匹配以 /user/foo 开头的所有路径。
注意:使用带通配符的路由时,例如
'/*'
,请注意这也会匹配对静态资源的请求(即/js/dependencies/sails.io.js
)并覆盖它们。为了防止这种情况,请考虑使用skipAssets
选项 如下所述。
要在 现代 Sails action 中接收与此通配符 (*
) 对应的运行时值,请在 action 定义的顶层使用 urlWildcardSuffix
来指示您要用来表示动态值的输入的名称
urlWildcardSuffix: 'template',
inputs: {
template: {
description: 'The relative path to an EJS template within our `views/emails/` folder -- WITHOUT the file extension.',
extendedDescription: 'Use strings like "foo" or "foo/bar", but NEVER "foo/bar.ejs" or "/foo/bar". For example, '+
'"internal/email-contact-form" would send an email using the "views/emails/internal/email-contact-form.ejs" template.',
example: 'email-reset-password',
type: 'string',
required: true
},
},
fn: async function({ template }) {
// …
}
- 或者,在经典的 (req,res) action 中,您可以使用
req.param('0')
访问路由的 URL 通配符后缀 (*
) 的动态值。- 有关更多背景信息,请参阅 https://npmjs.net.cn/package/machine-as-action
另一种捕获地址部分的方法是使用 模式变量。这允许路由匹配特殊命名的参数,这些参数永远不包含任何 /
字符,方法是使用 :paramName
模式变量语法而不是 *
'/user/foo/bar/:name'
或者对于可选的路径参数,在模式变量末尾添加 ?
'/user/foo/bar/:name?'
这将匹配与 /user/foo/bar/*
几乎相同的请求,但会将路由 URL 的动态部分的值作为参数值提供给路由处理程序(例如 req.param('name')
)。
请注意,通配符 (
*
) 语法匹配斜杠,而 URL 模式变量 (:
) 语法不匹配。因此,在上面的示例中,给定路由地址GET /user/foo/bar/*
,具有像/user/foo/bar/baz/bing/bong/bang
这样的 URL 的传入请求将匹配(而如果您使用:name
语法,则相同的 URL 将不匹配)。
模式变量的一个常见用例是设计标识或 虚拟 URL。例如,考虑 Github 上存储库的 URL,http://www.github.com/balderdashy/sails
。在 Sails 中,我们可能会在 config/routes.js
文件的底部这样定义此路由
'get /:account/:repo': {
controller: 'RepoController',
action: 'show',
skipAssets: true
}
在您的 RepoController
的 show
action 中,我们将使用 req.param('account')
和 req.param('repo')
来查找相应存储库的数据,然后将其传递到适当的 视图 作为 局部变量。 skipAssets
选项 确保虚拟路由不会意外匹配我们的任何 资产(例如 /images/logo.png
),因此它们仍然可以访问。
除了通配符地址语法外,您还可以使用正则表达式来定义路由应匹配的 URL。使用正则表达式定义地址的语法是
'r|<正则表达式字符串>|<逗号分隔的参数名称列表>'
这是字母“r”,后跟管道字符 |
、一个没有分隔符的正则表达式字符串、另一个管道和一个应映射到正则表达式中括号组的参数名称列表。例如
'r|^/\\d+/(\\w+)/(\\w+)$|foo,bar": "message/my-action'
将匹配 /123/abc/def
,运行 api/controllers/message/my-action.js 中的 action,并将值 abc
和 def
分别作为 req.param('foo')
和 req.param('bar')
提供。
请注意 \\d
和 \\w
中的双反斜杠;此转义对于正则表达式正常工作是必要的!
虽然您可以按任何顺序将项目添加到 config/routes.js 文件中,但请注意,Sails 将在内部根据包容性对您的路由进行排序,包容性是地址可以处理的潜在请求数量的度量。通常,地址不包含动态组件的路由将首先匹配,然后是包含动态参数的路由,然后是包含通配符的路由。这可以防止路由相互阻塞(例如,如果将 /*
路由保留在列表的顶部,它将响应所有请求,并且将永远不会匹配任何其他路由)。
如果您有任何 正则表达式地址,它们将按您指定的顺序保留。例如,如果您的 config/routes.js 文件包含一个 GET /foo/bar
路由,后跟一个 GET r|^/foo/\\d+$|
路由,则第二个路由将始终排序为出现在 GET /foo/bar
之后。这是由于确定正则表达式路由的包容性极其困难。在指定这些路由时,请注意对其进行排序,以便它们不会匹配超出预期的请求。
自定义路由的地址部分指定路由应匹配哪些 URL。目标部分指定在匹配完成后 Sails 应该做什么。目标可以采用多种不同的形式。在某些情况下,您可能希望通过将多个目标放在数组中来将它们链接到单个地址,但在大多数情况下,每个地址只有一个目标。下面将讨论不同类型的目标,然后讨论可以应用于它们的各种选项。
此语法将路由绑定到 控制器文件 中的操作。以下四个路由是等效的
'GET /foo/go': 'FooController.myGoAction',
'GET /foo/go': 'foo.myGoAction',
'GET /foo/go': { controller: 'foo', action: 'myGoAction' },
'GET /foo/go': { controller: 'FooController', action:'myGoAction' },
它们都将 GET /foo/go
映射到 api/controllers/FooController.js 中控制器的 myGoAction
操作,或 api/controllers/foo/mygoaction.js 中的操作。如果不存在这样的控制器或操作,Sails 将输出错误消息并忽略路由。否则,每当发出对 /foo/go 的 GET 请求时,将运行该操作中的代码。
此语法中的控制器和操作名称不区分大小写。
此语法将地址绑定到 独立的 Sails action。只需指定 action 的路径(相对于 api/controllers
)
'GET /': { action: 'index' }, // Use the action in api/controllers/index.js
'GET /foo/go': { action: 'foo/go-action' } // Use the action in api/controllers/foo/go-action.js OR
// the "go-action" action in api/controllers/FooController.js
'GET /bar/go': 'foo/go-action' // Binds to the same action as above, using shorthand notation
蓝图 API 为您的每个模型添加了几个操作,所有这些操作都可用于路由。例如,如果您在 api/models/User.js
中定义了一个模型,您将能够自动执行
'GET /foo/go': 'user/find' // Return a list of users
或
'GET /foo/go': 'UserController.find' // Same as above
如果您在 api/controllers/user/find.js
或 api/controllers/UserController.js
中有自定义操作,则将运行该操作而不是默认的蓝图 find
。有关为您的模型提供的操作的完整列表,请参阅 蓝图 API 参考。
另一个常见目标是将路由绑定到 视图 的目标。这对于将静态视图绑定到自定义 URL 特别有用,并且它也是新项目的默认主页开箱即用的设置方式。
视图目标的语法很简单:它只是视图文件的路径,不带文件扩展名(例如 .ejs
)并且相对于 views/ 文件夹
'GET /team': { view: 'brochure/about' }
这告诉 Sails 通过提供位于 views/brochure/about.ejs
的视图模板来处理对 /team
的 GET
请求(假设使用默认的 EJS 模板引擎)。只要该视图文件存在,对 /home 的 GET 请求就会显示它。为了与 Express/consolidate 保持一致,如果指定的相对路径与视图文件不匹配,则 Sails 将查找具有相同名称的子文件夹(例如 pages/brochure
)并在该子文件夹中提供“index”视图(例如 pages/brochure/index.ejs
),如果存在的话。
请注意,由于此路由直接绑定到视图,因此不会应用您配置的任何策略。如果您需要配置策略,请从控制器操作中使用
res.view()
。有关更多背景信息,请参阅 此 StackOverflow 问题。
您可以让一个地址重定向到另一个地址,无论是在您的 Sails 应用程序中还是在完全不同的服务器上。这可以通过简单地将重定向 URL 指定为字符串来完成
'/alias' : '/some/other/route/url',
'GET /google': 'http://www.google.com'
在您的 Sails 应用程序中重定向时,请注意避免重定向循环!
请注意,在重定向时,原始请求的 HTTP 方法(以及任何额外的标头/参数)可能会丢失,并且请求将转换为简单的 GET 请求。在上面的示例中,对 /alias 的 POST 请求将导致对 /some/other/route 的 GET 请求。这在某种程度上是浏览器相关的行为,但建议您不要期望请求方法和其他数据能够在重定向后继续存在。
您可以使用此语法将地址直接映射到默认或自定义 响应
'/foo': { response: 'notFound' }
只需在您的 api/responses 文件夹中指定响应文件的名称,无需 .js 扩展名。此语法中的响应名称区分大小写。如果您尝试将路由绑定到不存在的响应,Sails 将输出错误并忽略路由。
在大多数情况下,您会希望使用策略以及config/policies.js配置文件来应用于您的控制器操作。但是,在某些情况下,您可能希望直接将策略应用于自定义路由,尤其是在使用视图目标语法时。策略目标语法如下所示:
'/foo': { policy: 'my-policy' }
请注意,您始终希望将策略链接到至少其他一种类型的目标,方法是使用数组
'/foo': [
{ policy: 'my-policy' },
{ view: 'dashboard' }
]
这会将my-policy策略应用于路由,如果通过,则继续显示views/dashboard.ejs视图。
对于一次性作业(例如快速测试),您可以将路由直接分配给函数
'/foo': function(req, res) {
return res.send('hello!');
},
您还可以使用数组将此语法与其他语法组合。这允许您定义快速、内联的中间件
'/foo': [
function(req, res, next) {
sails.log('Quick and dirty test:', req.allParams());
return next();
},
{ controller: 'user', action: 'find' }
],
您还可以使用带有fn
键的字典来分配函数。这允许您同时指定其他路由目标选项
'GET /*': {
skipAssets: true,
fn: function(req, res) {
return res.send('hello!');
}
},
最佳实践是仅将函数语法用于临时路由,因为这样做违反了使 Sails 有用的结构约定!(此外,您的 routes.js 文件越整洁越好。)
除了上面讨论的各种路由目标语法中的选项外,添加到路由目标对象的任何其他属性都将通过req.options
对象传递到路由处理程序。有一些保留属性可用于影响路由处理程序的行为。这些列在下表中。
属性 | 适用的目标类型 | 数据类型 | 详情 |
---|---|---|---|
skipAssets |
所有 | 如果不希望路由匹配包含点的 URL(例如myImage.jpg),则将其设置为true 。这将阻止您的路由使用通配符表示法匹配静态资产的 URL。在创建URL 片段时很有用。 |
|
skipRegex |
所有 | 如果跳过每个包含点的 URL 太过宽松,或者您需要根据完全不同的条件跳过路由的处理程序,则可以使用skipRegex 。此选项允许您指定一个正则表达式或正则表达式数组来匹配请求 URL;如果任何匹配成功,则处理程序将被跳过。请注意,与使用正则表达式绑定处理程序的语法不同,skipRegex 期望的是实际的RegExp 对象,而不是字符串。 |
|
locals |
控制器、视图、蓝图、响应 | 设置默认的局部变量,以传递给处理请求期间呈现的任何视图。 | |
cors |
所有 | 指定如何处理来自不同来源的此路由的请求。有关更多信息,请参阅主要 CORS 文档。 | |
csrf |
所有 | 指示路由是否应通过要求将 CSRF 令牌与请求一起传递来进行保护。有关更多信息,请参阅主要 CSRF 文档。 | |
parseBlueprintOptions |
蓝图 | 提供此函数以覆盖蓝图操作的默认行为(包括搜索条件、跳过、限制、排序和填充)。有关更多信息,请参阅蓝图配置参考。 |