快速提问:OpenAPI 规范是否要求在将当前 URL 与路径匹配之前对验证器进行 URL 规范化?再一次,我发现正在使用的验证器似乎有缺陷,因为它会将规则应用于 /abc/path,但不应用于 /abc/path/(请注意额外的 /)。
谢谢。
快速提问:OpenAPI 规范是否要求在将当前 URL 与路径匹配之前对验证器进行 URL 规范化?再一次,我发现正在使用的验证器似乎有缺陷,因为它会将规则应用于 /abc/path,但不应用于 /abc/path/(请注意额外的 /)。
谢谢。
我们正在使用 MS 为 ASP.NET Core API 应用程序提供的全新 OpenAPI 开箱即用支持,但在生成 json 的方式上遇到了一些问题。我们有以下类型:
public class MsgMovimentacaoLocaisTrabalho {
public IList<InfoGeral>? LocaisRemover { get; set; }
public InfoGeral? LocaisAssociar { get; set; }
}
public class InfoGeral {
public Guid GuidDirecao { get; set; }
public IEnumerable<int> Locais { get; set; } = Enumerable.Empty<int>();
}
MsgMovimentacaoLocaisTrabalho
用作控制器方法之一的参数类型:
public async Task<IActionResult> MovimentaLocaisTrabalhoAsync(
[Description("Mensagem que ....")]MsgMovimentacaoLocaisTrabalho msg,
CancellationToken cancellationToken) {
...
问题在于类型的输出:
...
"MsgMovimentacaoLocaisTrabalho": {
"type": "object",
"properties": {
"locaisRemover": {
"type": "array",
"items": {
"$ref": "#/components/schemas/InfoGeral"
},
"nullable": true
},
"locaisAssociar": {
"$ref": "#/components/schemas/InfoGeral2"
}
}
},
"InfoGeral": {
"type": "object",
"properties": {
"guidDirecao": {
"type": "string",
"format": "uuid"
},
"locais": {
"type": "array",
"items": {
"type": "integer",
"format": "int32"
}
}
}
},
....
"InfoGeral2": {
"type": "object",
"properties": {
"guidDirecao": {
"type": "string",
"format": "uuid"
},
"locais": {
"$ref": "#/components/schemas/#/properties/locaisRemover/items/properties/locais"
}
},
"nullable": true
},
首先,查看InfoGeral
架构,它看起来不错(locais
表示为 的数组int
),但我不确定为什么会有类型InfoGeral2
。我假设这是因为该类型MsgMovimentacaoLocaisTrabalho
有 2 个引用该类型的属性...
第一个问题:有没有办法让这两个属性的架构重用InfoGeral
?
问题 2:为什么我最终得到的是错误的值locais
而不是数组?IEnumerable 不应该在架构上生成数组吗?
顺便说一句,这是错误:
Semantic error at components.schemas.InfoGeral2.properties.locais.$ref
$ref values must be RFC3986-compliant percent-encoded URIs
Jump to line 11623
假设您正在尝试匹配与以下 2 条规则兼容的 url:
最初,我从以下模式开始(模式 1):
^(?:(?:/.+)+/contactos/?(?!.))|(?:(?:/.*)+/gestao(?:/.+))$
它有效,但在这种情况下所需的负前瞻似乎不合适,所以我用以下模式替换(我们称之为模式 2):
^(?:(?:/.+)+/contactos/?)$|^(?:(?:/.*)+/gestao(?:/.+))$
主要区别在于,我使用开始/结束锚点来分隔每个表达式,而不是像第一个示例中那样使用单个对(我没有在两种情况下捕获组,因此这实际上是两种模式之间的唯一区别)。通过“隔离”每个“选项”,我可以放弃模式 1 中使用的负前瞻。
由于模式 2 不使用前瞻,我预计它应该比模式 1 更快。但是,情况似乎并非如此。我用 .net 8 构建了一个小型基准测试,看起来模式 1 比匹配 url 的模式稍快。这是我编写的代码(并不是真正有经验的 Benchmark 用户,所以也许我遗漏了一些东西):
[MemoryDiagnoser]
public class RegexPerformance {
private const string _patternNoCapture = "^(?:(?:/.+)+/contactos/?(?!.))|(?:(?:/.*)+/gestao(?:/.+))$";
private const string _patternNoCaptureWithStartEndAnchors = "^(?:(?:/.+)+/contactos/?)$|^(?:(?:/.*)+/gestao(?:/.+))$";
private Regex _noCapture = default!;
private Regex _noCaptureWithStart = default!;
[GlobalSetup]
public void Setup() {
_noCapture = new (_patternNoCapture,
RegexOptions.Compiled | RegexOptions.IgnoreCase);
_noCaptureWithStart = new (_patternNoCaptureWithStartEndAnchors,
RegexOptions.Compiled | RegexOptions.IgnoreCase);
}
public IEnumerable<string> Urls => [
"/test/contactos",
"/test/contactos/",
"/test/someplace/gestao/123/yyy",
"/test/someplace/gestao/123"
];
[Benchmark]
[ArgumentsSource(nameof(Urls))]
public bool MatchPatternNoCapture(string url) => _noCapture.IsMatch(url);
[Benchmark]
[ArgumentsSource(nameof(Urls))]
public bool MatchPatternNoCaptureWithStartEndAnchors(string url) => _noCaptureWithStart.IsMatch(url);
}
结果如下:
| Method | url | Mean | Error | StdDev | Median | Allocated |
|----------------------------------------- |--------------------- |-----------:|----------:|----------:|-----------:|----------:|
| MatchPatternNoCapture | /test/contactos | 244.5 ns | 8.25 ns | 23.53 ns | 238.6 ns | - |
| MatchPatternNoCaptureWithStartEndAnchors | /test/contactos | 224.3 ns | 3.14 ns | 2.62 ns | 223.5 ns | - |
| MatchPatternNoCapture | /test/contactos/ | 256.6 ns | 5.67 ns | 15.80 ns | 259.9 ns | - |
| MatchPatternNoCaptureWithStartEndAnchors | /test/contactos/ | 278.6 ns | 18.98 ns | 53.84 ns | 260.6 ns | - |
| MatchPatternNoCapture | /test(...)o/123 [26] | 1,081.5 ns | 37.01 ns | 104.39 ns | 1,057.7 ns | - |
| MatchPatternNoCaptureWithStartEndAnchors | /test(...)o/123 [26] | 1,367.4 ns | 167.26 ns | 493.18 ns | 1,121.6 ns | - |
| MatchPatternNoCapture | /test(...)3/yyy [30] | 1,861.4 ns | 73.08 ns | 201.28 ns | 1,789.4 ns | - |
| MatchPatternNoCaptureWithStartEndAnchors | /test(...)3/yyy [30] | 1,925.6 ns | 58.13 ns | 168.65 ns | 1,919.0 ns | - |
顺便说一句,我使用不匹配的 url ( /test/contactosbad
) 运行了另一个简单测试,在这种情况下,模式 2 的表现似乎比模式 1 稍好:
| Method | url | Mean | Error | StdDev | Allocated |
|----------------------------------------- |------------------- |---------:|---------:|---------:|----------:|
| MatchPatternNoCapture | /test/contactosbad | 668.4 ns | 13.44 ns | 14.38 ns | - |
| MatchPatternNoCaptureWithStartEndAnchors | /test/contactosbad | 518.2 ns | 10.30 ns | 14.43 ns | - |
我必须承认我对这些结果有点困惑。我预计模式 2 的表现会比模式 1 好得多,但情况似乎并非如此。关于为什么会发生这种情况有什么想法吗?
谢谢。