Skip to content

Commit e6535f7

Browse files
author
Fabian Niederer
committed
added validation & renabled OpenApiPaths validators
1 parent 3d62054 commit e6535f7

File tree

7 files changed

+97
-2
lines changed

7 files changed

+97
-2
lines changed

src/Microsoft.OpenApi/Properties/SRResource.Designer.cs

Lines changed: 10 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Microsoft.OpenApi/Properties/SRResource.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@
207207
<data name="Validation_PathItemMustBeginWithSlash" xml:space="preserve">
208208
<value>The path item name '{0}' MUST begin with a slash.</value>
209209
</data>
210+
<data name="Validation_PathSignatureMustBeUnique" xml:space="preserve">
211+
<value>The path signature '{0}' MUST begin be unique.</value>
212+
</data>
210213
<data name="Validation_RuleAddTwice" xml:space="preserve">
211214
<value>The same rule cannot be in the same rule set twice.</value>
212215
</data>

src/Microsoft.OpenApi/Services/OpenApiWalker.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ internal void Walk(OpenApiPaths paths)
219219
_visitor.CurrentKeys.Path = null;
220220
}
221221
}
222+
222223
}
223224

224225
/// <summary>
@@ -1036,6 +1037,7 @@ internal void Walk(IOpenApiElement element)
10361037
case OpenApiOAuthFlow e: Walk(e); break;
10371038
case OpenApiOperation e: Walk(e); break;
10381039
case OpenApiParameter e: Walk(e); break;
1040+
case OpenApiPaths e: Walk(e); break;
10391041
case OpenApiRequestBody e: Walk(e); break;
10401042
case OpenApiResponse e: Walk(e); break;
10411043
case OpenApiSchema e: Walk(e); break;

src/Microsoft.OpenApi/Validations/OpenApiValidator.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ public void AddError(OpenApiValidatorError error)
131131
/// <param name="item">The object to be validated</param>
132132
public override void Visit(OpenApiParameter item) => Validate(item);
133133

134+
/// <summary>
135+
/// Execute validation rules against an <see cref="OpenApiPaths"/>
136+
/// </summary>
137+
/// <param name="item">The object to be validated</param>
138+
public override void Visit(OpenApiPaths item) => Validate(item);
139+
134140
/// <summary>
135141
/// Execute validation rules against an <see cref="OpenApiSchema"/>
136142
/// </summary>

src/Microsoft.OpenApi/Validations/Rules/OpenApiPathsRules.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

4+
using System.Collections.Generic;
5+
using System.Text.RegularExpressions;
46
using Microsoft.OpenApi.Models;
57
using Microsoft.OpenApi.Properties;
68

@@ -34,6 +36,30 @@ public static class OpenApiPathsRules
3436
}
3537
});
3638

39+
/// <summary>
40+
/// A relative path to an individual endpoint. The field name MUST begin with a slash.
41+
/// </summary>
42+
public static ValidationRule<OpenApiPaths> PathMustBeUnique =>
43+
new ValidationRule<OpenApiPaths>(
44+
(context, item) =>
45+
{
46+
const string regexPath = "\\{([^/]+)\\}";
47+
var hashSet = new HashSet<string>();
48+
49+
foreach (var path in item.Keys)
50+
{
51+
context.Enter(path);
52+
53+
var pathSignature = Regex.Replace(path, regexPath, "{}");
54+
55+
if (!hashSet.Add(pathSignature))
56+
context.CreateError(nameof(PathMustBeUnique),
57+
string.Format(SRResource.Validation_PathSignatureMustBeUnique, pathSignature));
58+
59+
context.Exit();
60+
}
61+
});
62+
3763
// add more rules
3864
}
3965
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System.Linq;
2+
using FluentAssertions;
3+
using Microsoft.OpenApi.Extensions;
4+
using Microsoft.OpenApi.Models;
5+
using Microsoft.OpenApi.Properties;
6+
using Xunit;
7+
8+
namespace Microsoft.OpenApi.Validations.Tests
9+
{
10+
public class OpenApiPathsValidationTests
11+
{
12+
[Fact]
13+
public void ValidatePathsMustBeginWithSlash()
14+
{
15+
// Arrange
16+
var error = string.Format(SRResource.Validation_PathItemMustBeginWithSlash, "pets/{petId}");
17+
var paths = new OpenApiPaths
18+
{
19+
{"pets/{petId}",new OpenApiPathItem() }
20+
};
21+
22+
// Act
23+
var errors = paths.Validate(ValidationRuleSet.GetDefaultRuleSet());
24+
25+
// Assert
26+
errors.Should().NotBeEmpty();
27+
errors.Select(e => e.Message).Should().BeEquivalentTo(error);
28+
}
29+
30+
[Fact]
31+
public void ValidatePathsAreUnique()
32+
{
33+
// Arrange
34+
var error = string.Format(SRResource.Validation_PathSignatureMustBeUnique, "/pets/{}");
35+
var paths = new OpenApiPaths
36+
{
37+
{"/pets/{petId}",new OpenApiPathItem() },
38+
{"/pets/{name}",new OpenApiPathItem() }
39+
};
40+
41+
// Act
42+
var errors = paths.Validate(ValidationRuleSet.GetDefaultRuleSet());
43+
44+
// Assert
45+
errors.Should().NotBeEmpty();
46+
errors.Select(e => e.Message).Should().BeEquivalentTo(error);
47+
}
48+
}
49+
}

test/Microsoft.OpenApi.Tests/Validations/ValidationRuleSetTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public void DefaultRuleSetPropertyReturnsTheCorrectRules()
4343
Assert.NotEmpty(rules);
4444

4545
// Update the number if you add new default rule(s).
46-
Assert.Equal(21, rules.Count);
46+
Assert.Equal(22, rules.Count);
4747
}
4848
}
4949
}

0 commit comments

Comments
 (0)