像ASP.NET或Nancy这样的框架提供了可用于指定路由的语法,例如:
MapRoute("/customers/{id}/invoices/{invoiceId}", ...)
在ASP.NET路由中工作在两个方向。他们可以匹配请求URI,例如/customers/32/invoices/19
到路由,他们可以解析参数,例如{ id: 37, invoiceId: 19 }
到URI中。
RFC 6570: URI Templates还定义了一个类似的,虽然更丰富的URI规范,通常用于解析 URI。例如:
UriTemplate("/customers/{id}/invoices{/invoiceId}{?sort}", { id: 37, invoiceId: 19, sort: 'asc' } )
// returns: /customers/37/invoices/19?sort=asc
我的问题是,RFC 6570中指定的语法是否可用于匹配请求URI到路由?是否有一部分语法会使给定的URI与给定的URI模板匹配变得模糊不清?是否有任何库支持将URI与URI模板匹配?
答案 0 :(得分:1)
我怀疑这将非常困难。当然,像前缀语法这样的东西将无法重新生成原始参数。
路径段扩展
等 {/list*} /red/green/blue
您如何知道路径的哪些部分是文字,哪些部分是参数的一部分?在URITemplate规范中有很多相当怪异的行为,我怀疑即使它可以匹配,也会相当昂贵。
您是否有兴趣为路由目的这样做?
答案 1 :(得分:0)
关于匹配很简单,但关于解决,您需要使用RFC 6570替换ASP.net部分。
不幸的是我在使用快速js的节点中执行此操作,这可能没有帮助,但我确信在ASP中也可以使用类似https://github.com/geraintluff/uri-templates(用于解析)的内容。
这里有一些.js代码来说明hyperschema的重写 使用RFC 6570与快速js一起使用(在模式中使用的优点是您还可以为uri模板定义正则表达式):
var deref = require('json-schema-deref'); var tv4 = require('tv4'); var url = require('url'); var rql = require('rql/parser'); var hyperschema = { "$schema": "http://json-schema.org/draft-04/hyper-schema", "links": [ { "href": "{/id}{/ooo*}{#q}", "method": "GET", "rel": "self", "schema": { "type": "object", "properties": { "params": { "type": "object", "properties": { "id": {"$ref": "#/definitions/id"} }, "additionalProperties": false } }, "additionalProperties": true } } ], "definitions": { "id": { "type": "string", "pattern": "[a-z]{0,3}" } } }
// DOJO lang AND _
function getDottedProperty(object, parts, create) {
var key;
var i = 0;
while (object && (key = parts[i++])) {
if (typeof object !== 'object') {
return undefined;
}
object = key in object ? object[key] : (create ? object[key] = {} : undefined);
}
return object;
}
function getProperty(object, propertyName, create) {
return getDottedProperty(object, propertyName.split('.'), create);
}
function _rEscape(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function getPattern(k, ldo, customCat) {
// ...* = explode = array
// ...: = maxLength
var key = ((k.slice(-1) === '*') ? k.slice(0,-1) : k).split(':')[0];
var cat = (customCat) ? customCat : 'params'; // becomes default of customCat in TS
var pattern = '';
if (typeof ldo === 'object' && ldo.hasOwnProperty('schema')) {
var res = getProperty(ldo.schema, ['properties',cat,'properties',key,'pattern'].join('.'));
if (res) {
console.log(['properties',cat,'properties',key,'pattern'].join('.'),res);
return ['(',res,')'].join('');
}
}
return pattern;
}
function ldoToRouter(ldo) {
var expression = ldo.href.replace(/(\{\+)/g, '{') // encoding
.replace(/(\{\?.*\})/g, '') // query
.replace(/\{[#]([^}]*)\}/g, function(_, arg) {
// crosshatch
//console.log(arg);
return ['(?:[/]*)?#:',arg,getPattern(arg,ldo,'anchor')].join('');
})
.replace(/\{([./])?([^}]*)\}/g, function(_, op, arg) {
// path seperator
//console.log(op, '::', arg, '::', ldo.schema);
return [op,':',arg,getPattern(arg,ldo)].join('');
});
return {method: ldo.method.toLowerCase(), args:[expression]};
}
deref(hyperschema, function(err, fullSchema) {
console.log('deref hyperschema:',JSON.stringify(fullSchema));
var router = fullSchema.links.map(ldoToRouter);
console.log('router:',JSON.stringify(router));
});