-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Standardization of cross-parameter validation issue types #113
Comments
Match for id between PUT path and body is normally a programmatic error in client. Structure like this should suffice: PUT /address/456 { What if id from path param is different from body? {
"type": "urn:problem-type:belgif:badRequest",
"href": "https://www.belgif.be/specification/rest/api-guide/problems/badRequest.html",
"status": 400,
"title": "Bad Request",
"detail": "The input message is incorrect",
"issues": [
{
"type": "urn:problem-type:belgif:input-validation:shouldMatchPathParameter",
"detail": "id in body should match value 456 of path parameter",
"in": "body",
"name": "id",
"value": "123",
}
]
} |
GET /employers?enterpriseNumber=1234&name=Smals {
"type": "urn:problem-type:belgif:badRequest",
"href": "https://www.belgif.be/specification/rest/api-guide/problems/badRequest.html",
"status": 400,
"title": "Bad Request",
"detail": "The input message is incorrect",
"issues": [
{
"type": "urn:problem-type:belgif:input-validation:mutuallyExclusiveParameters",
"detail": "Search allowed on either companyId or name, but not both",
"in": "query",
"name": "name",
"value": "Smals"
}
]
} alternatives:
{
"type": "urn:problem-type:belgif:input-validation:mutuallyExclusiveParameters",
"detail": "Search allowed on either companyId or name, but not both",
"in": "query",
"name": "name",
"value": "Smals",
"relatedTo": ["in": "query", "name": "companyId", "value": "1234" ]
} Program logic has to (arbitrarily?) decide which one is "main" parameter or "relatedTo". |
use case GET /organizations?alternateIdType=companyId {
"type": "urn:problem-type:belgif:badRequest",
"href": "https://www.belgif.be/specification/rest/api-guide/problems/badRequest.html",
"status": 400,
"title": "Bad Request",
"detail": "The input message is incorrect",
"issues": [
{
"type": "urn:problem-type:belgif:input-validation:incompleteParameterGroup",
"detail": "When alternateIdType is used, alternateIdValue query param should be present as well",
"in": "query",
"name": "alternateIdType"
}
]
}
|
@jpraet , I changed the issue opener, removing some parts I split off to new separate issues: |
Discussed on WG: If there are many cases to standardize, use a common prefix like urn:problem-type:belgif:input-validation:invalidCombination: or urn:problem-type:belgif:input-validation:dependencyViolation:. The name "parameter" in OpenAPI isn't used for fields within the body part, so its use in the name is not appropriate. Use cases and naming could be inspired on https://medium.com/isa-group/inter-parameter-dependencies-in-rest-apis-4664e901c124. Alternatively, some issue types might be reformulated, Naming ideas:
TODO: is it possible to reduce the number of above restrictions by replacing them by a combination of separate ones? |
no progress yet, I'll keep you posted. I expect to work on it +/- two weeks before the next WG. |
Overview of relevant JSON Schema keywords:
If we'd model the above use cases using these, we'd get following below. Of course, these keywords can't actually be used across multiple query parameters and a body parameter.
oneOf:
- required: [propertyOne]
- required: [propertyTwo]
- required: [propertyThree]
- not:
anyOf: [propertyOne, propertyTwo, propertyThree]
oneOf:
- required: [propertyOne]
- required: [propertyTwo]
oneOf:
- required: [propertyOne, propertyTwo, propertyThree]
- not:
anyOf: [propertyOne, propertyTwo, propertyThree]
Next, I'll try to propose issue types, aligned with this where possible. update: fixed some errors: not: required -> not: anyOf |
Proposal:
update: edited based on @jpraet 's feedback While theoretically you could express "exactlyOneOfRequired" as applying both "zeroOrOneRequired" and "anyOfRequired", it seems more expressive to me, or would be confusing or renaming would be inconsistent with JSON schema naming:
|
The *Required suffix is a bit confusing to me because, as I understand it, it means something else here than "required" in openapi spec? e.g. by zeroOrOneRequired you mean there must be zero or one of a given set of inputs, correct? Could we drop the *Required suffix? And zerorOrOne also seems inconsistent with exactlyOneOf? There's also something that bothers me slightly and that's that existing issue types like urn:problem-type:belgif:input-validation:schemaViolation and urn:problem-type:belgif:input-validation:unknownParameter and proposals in #126 are named after "what went wrong", whereas these are named after "what was expected". It's a subtle difference, I don't know if I'm making myself clear? e.g. for urn:problem-type:belgif:input-validation:mustBeEqual, a naming style that would be more consistent with the preexisting issue types is urn:problem-type:belgif:input-validation:notEqual or urn:problem-type:belgif:input-validation:mismatch. But I think such naming style is difficult for the other issue types in this proposal. |
I forgot to add "Required" for allOrNone, added it now. Still TBD if "Required" suffix is necessary. I actually added it to avoid misinterpretation that the issue type is "what was expected". For the existing problem types, it's quite clear that they are to be interpreted as "what went wrong". So I'd suggest to either keep the suffix or try to come up with a unambiguous "what went wrong" naming style.
Right. Renamed it to "zeroOrOneOf". TBD if "Of" suffix is necessary (alignment with OpenAPI)? |
A half attempt at alternative "what went wrong" naming style:
|
suffix: Expected instead of Required is preferred | zeroOrOneOfExpected | moreThanOne/tooMany/mutuallyExclusive | @JDMKSZ : preference for combined exactlyOneOfExpected (or similar) instead of split into two; easier for client and server logic. @VirginieHayot / @wsalembi : worthwhile to standardize? Wouldn't free text suffice bc mainly used for developers, not UI/end users? @wsalembi : simplified issue types proposal: |
@pvdbosch @wsalembi @VirginieHayot @JDMKSZ Let me give this one more shot and try to summarize and clarify the standpoint of CBSS in this matter. Cross-parameter input validations are omnipresent in REST APIs. For query parameters, and in some cases for body properties, these cross-parameter validations cannot be enforced through the OpenAPI schema. So it is up to the API developer to perform these validations and return a proper problem type. Therefore, for the most common categories of cross-parameter input validations, a standardization is desirable for the issue type codes to use (#113), as well as for the way to represent multiple parameter references in the issue payload (#108). For us, these two tickets are intertwined. After all, if it is decided to standardize the issue type codes, then these will also need to be documented with examples. Standardization in this area allows for a common reusable InputValidator to be implemented, so the API developer is not burdened with the tedious task of performing these validations and constructing the problem payload (which issue type, title, detail message to use? how to represent the parameters?). As an example, let's say we have an API with "name", "alternateId.type" and "alternateId.value" query parameters:
new InputValidator()
.mutuallyExclusive(queryParam("alternateId.value", alternateIdValue), queryParam("name", name))
.inputGroup(queryParam("alternateId.type", alternateIdType), queryParam("alternateId.value", alternateIdValue))
.ssin(queryParam("ssin", ssin))
.validate(); Not let's say we invoke The validation library would throw the following problem (returning multiple issues in one go): {
"type": "urn:problem-type:belgif:badRequest",
"href": "https://www.belgif.be/specification/rest/api-guide/problems/badRequest.html",
"title": "Bad Request",
"status": 400,
"detail": "The input message is incorrect",
"issues": [
{
"type": "urn:problem-type:belgif:input-validation:mutuallyExclusive",
"title": "Mutually exclusive inputs",
"detail": "The inputs [alternateId.value, name] are mutually exclusive",
"inputs": [
{
"in": "query",
"name": "alternateId.value",
"value": "12345"
},
{
"in": "query",
"name": "name",
"value": "test"
}
]
},
{
"type": "urn:problem-type:belgif:input-validation:incompleteGroup",
"title": "Incomplete input group",
"detail": "The input group [alternateId.type, alternateId.value] is incomplete",
"inputs": [
{
"in": "query",
"name": "alternateId.type",
"value": null
},
{
"in": "query",
"name": "alternateId.value",
"value": "12345"
}
]
}
]
} The validation library has access to all this information, so why not expose it in a structured manner to API consumers? Some of you are suggesting that returning only a "detail" message is sufficient. But then why do we even have "in"/"name"/"value" properties on InputValidationIssue at all? Why return "in"/"name"/"value" properties for a single-parameter input validation error, but not for a cross-parameter validation error? Returning a problem that references multiple invalid parameters was possible in openapi-problem v1.0.0, but in v1.2.0 support for a problem with multiple input validation issues was added (also an important feature) at the expense of this pre-existing functionality. To Smals, eHealth and other workgroup members: do you have any real-world examples of the problem payloads you currently return in your REST APIs when performing cross-parameter input validations? Both for format validations (that should perhaps only occur during development) as for business issues (where the API consumer is expected to handle them in production too). What do you put in the issue type? And do you fill in the "in"/"name"/"value"? |
CBSS uses the following issue types for cross-parameter validation based on the proposal in #113 (comment): urn:problem-type:cbss:input-validation:exactlyOneOfExpected And we return an extension of the Belgif InputValidationIssue with an inputs[] array for these issue types: {
"type": "urn:problem-type:belgif:badRequest",
"href": "https://www.belgif.be/specification/rest/api-guide/problems/badRequest.html",
"title": "Bad Request",
"status": 400,
"detail": "The input message is incorrect",
"issues": [
{
"type": "urn:problem-type:cbss:input-validation:exactlyOneOfExpected",
"title": "Exactly one of these inputs must be present",
"detail": "Exactly one of these inputs must be present: sector, enterpriseNumber",
"inputs": [
{
"in": "query",
"name": "sector",
"value": null
},
{
"in": "query",
"name": "enterpriseNumber",
"value": null
}
]
}
]
} |
As these urn:problem-type:cbss:input-validation:* cross-parameter issue types are now also present in the Belgif rest-problem library, it would be good if they could be standardized under urn:problem-type:belgif:input-validation:*
|
Standardize some general validation issues for constraints that cannot be enforced through schema validation (related to #108):
The text was updated successfully, but these errors were encountered: