Skip to content
This repository has been archived by the owner on Jun 12, 2024. It is now read-only.

Commit

Permalink
Allow v1 as API major version in path
Browse files Browse the repository at this point in the history
  • Loading branch information
u217269 committed Oct 26, 2020
1 parent c09e36e commit 5e4caf2
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ import org.zalando.zally.core.plus
import org.zalando.zally.core.toEscapedJsonPointer
import org.zalando.zally.core.toJsonPointer
import org.zalando.zally.core.util.PatternUtil
import org.zalando.zally.rule.api.Check
import org.zalando.zally.rule.api.Context
import org.zalando.zally.rule.api.Rule
import org.zalando.zally.rule.api.Severity
import org.zalando.zally.rule.api.Violation
import org.zalando.zally.rule.api.*
import org.zalando.zally.ruleset.zalando.util.WordUtil.isPlural

@Rule(
Expand All @@ -24,6 +20,7 @@ class PluralizeResourceNamesRule(rulesConfig: Config) {
private val slash = "/"

private val slashes = "/+".toRegex()
private val semVerVersionFormat = "^[0-9]+([.][0-9]+){1,2}$".toRegex()

@Suppress("SpreadOperator")
internal val whitelist = mutableListOf(
Expand All @@ -49,12 +46,22 @@ class PluralizeResourceNamesRule(rulesConfig: Config) {
}

private fun pathSegments(path: String): List<String> {
return path.split(slashes).filter { !it.isEmpty() }
return path.split(slashes).filter { it.isNotEmpty() }
}

private fun isNonViolating(it: String) =
!PatternUtil.isPathVariable(it) && !isPlural(it)
(!PatternUtil.isPathVariable(it) && (!isPlural(it) || it.contains(".")))

private fun violation(context: Context, term: String, pointer: JsonPointer) =
context.violation("Resource '$term' appears to be singular", pointer)
when {
semVerVersionFormat.matches(term) -> {
context.violation("Resource '$term' is a version, instead of a resource", pointer)
}
term.contains(".") -> {
context.violation("Resource '$term' has a dot as delimiter", pointer)
}
else -> {
context.violation("Resource '$term' appears to be singular", pointer)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class VersionInUriRule {
@Check(severity = Severity.MUST)
fun checkResourceNames(context: Context): List<Violation> =
(violatingResourceNames(context.api))
.map { context.violation("Version found in resource name. Use versions only at the beginning of the path as an own resource, e.g. like .../v1/... .", it) }
.map { context.violation("Version found in resource name. Use versions only at the beginning of the path as an own resource and in format v\${major}, e.g. like .../v1/... .", it) }

private fun violatingServers(api: OpenAPI): Collection<Server> =
api.servers.orEmpty()
Expand Down
1 change: 1 addition & 0 deletions server/zally-ruleset-sbb/src/main/resources/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ PluralizeResourceNamesRule {
whitelist: [
/api/
/kpis/
/"v[0-9]"/
]
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,33 @@ class PluralizeResourceNamesRuleTest {
.isEmpty()
}

@Test
fun `validate with simple version in path returns no violations`() {
val context = openApiContextWithPath("/v1/things")

val violations = rule.validate(context)

assertThat(violations)
.isEmpty()
}

@Test
fun `validate with semver version or dot in path segment returns violations`() {
val context = openApiContextWithPath("/api/1.2.3/some.things")

val violations = rule.validate(context)

assertThat(violations)
.descriptionsEqualTo(
"Resource '1.2.3' is a version, instead of a resource",
"Resource 'some.things' has a dot as delimiter"
)
.pointersEqualTo(
"/paths/~1api~11.2.3~1some.things",
"/paths/~1api~11.2.3~1some.things"
)
}

@Test
fun `validate with whitelisted component returns other violations`() {
val context = openApiContextWithPath("/prefix/whitelisted/suffix")
Expand Down

0 comments on commit 5e4caf2

Please sign in to comment.