Skip to content

Commit 579d5fd

Browse files
authored
Enforce path parameter required/optional with JSON specs
1 parent 5f824cf commit 579d5fd

File tree

6 files changed

+38
-9
lines changed

6 files changed

+38
-9
lines changed

compiler/src/steps/validate-rest-spec.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,35 @@ export default async function validateRestSpec (model: model.Model, jsonSpec: Ma
6868
}
6969
}
7070

71+
// are all path parameters properly required or optional?
72+
let urlPartsRequired = new Set(urlParts)
73+
// A part is considered required if it is included in
74+
// every path for the API endpoint.
75+
for (const path of spec.url.paths) {
76+
if (path.parts == null) {
77+
// No parts means that all path parameters are optional!
78+
urlPartsRequired = new Set()
79+
break
80+
}
81+
urlPartsRequired = new Set([...Object.keys(path.parts)].filter((x) => urlPartsRequired.has(x)))
82+
}
83+
84+
// transform [{name: ..., required: ...}] -> {name: {required: ...}}
85+
const pathPropertyMap: Record<string, model.Property> = requestProperties.path.reduce((prev, prop) => ({ ...prev, [prop.name]: prop }), {})
86+
for (const name of pathProperties) {
87+
// okay to skip if it's not included since this scenario
88+
// is covered above with a different error.
89+
if (!urlParts.includes(name)) {
90+
continue
91+
}
92+
// Find the mismatches between the specs
93+
if (urlPartsRequired.has(name) && !pathPropertyMap[name].required) {
94+
errors.addEndpointError(endpoint.name, 'request', `${endpoint.request.name}: path parameter '${name}' is required in the json spec`)
95+
} else if (!urlPartsRequired.has(name) && pathPropertyMap[name].required) {
96+
errors.addEndpointError(endpoint.name, 'request', `${endpoint.request.name}: path parameter '${name}' is optional in the json spec`)
97+
}
98+
}
99+
71100
if (spec.params != null) {
72101
const params = Object.keys(spec.params)
73102
const queryProperties = requestProperties.query.map(property => property.name)

output/schema/schema.json

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

output/typescript/types.ts

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

specification/_global/rank_eval/RankEvalRequest.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export interface Request extends RequestBase {
3434
* Comma-separated list of data streams, indices, and index aliases used to limit the request. Wildcard (`*`) expressions are supported.
3535
* To target all data streams and indices in a cluster, omit this parameter or use `_all` or `*`.
3636
*/
37-
index: Indices
37+
index?: Indices
3838
}
3939
query_parameters: {
4040
/**

specification/fleet/msearch/MultiSearchRequest.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export interface Request extends RequestBase {
4343
/**
4444
* A single target to search. If the target is an index alias, it must resolve to a single index.
4545
*/
46-
index: IndexName | IndexAlias
46+
index?: IndexName | IndexAlias
4747
}
4848
query_parameters: {
4949
/**

specification/ml/clear_trained_model_deployment_cache/MlClearTrainedModelDeploymentCacheRequest.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,6 @@ export interface Request extends RequestBase {
3737
/**
3838
* The unique identifier of the trained model.
3939
*/
40-
model_id?: Id
40+
model_id: Id
4141
}
4242
}

0 commit comments

Comments
 (0)