feat(validation): implement Rule 47 for response content-type and schema#754
feat(validation): implement Rule 47 for response content-type and schema#754Junnygram wants to merge 2 commits intomeshery:masterfrom
Conversation
Signed-off-by: Junnygram <junnexclusive@gmail.com>
There was a problem hiding this comment.
Code Review
This pull request introduces Rule 47 to the API audit validation, which mandates that all 2xx responses, excluding 204 (No Content), must include a content block and a defined schema. The implementation includes the validation logic in rules_design.go and corresponding unit tests. Feedback suggests extending the exclusion list to include the 205 (Reset Content) status code, as per RFC 9110, which also prohibits a response body. This involves updating the rule's logic, documentation, violation messages, and adding a specific test case for the 205 status code.
validation/rules_design.go
Outdated
| return names | ||
| } | ||
|
|
||
| // --- Rule 47: 2xx responses (except 204) must have content and schema --- |
There was a problem hiding this comment.
Rule 47 should also exclude the 205 Reset Content status code. According to RFC 9110, a 205 response MUST NOT include a content part, similar to 204. I've updated the comment to reflect this.
| // --- Rule 47: 2xx responses (except 204) must have content and schema --- | |
| // --- Rule 47: 2xx responses (except 204 and 205) must have content and schema --- |
validation/rules_design.go
Outdated
| label := fmt.Sprintf("%s %s", strings.ToUpper(method), path) | ||
| for code, respRef := range op.Responses.Map() { | ||
| // Only interested in 2xx responses, excluding 204 (No Content). | ||
| if !strings.HasPrefix(code, "2") || code == "204" { |
There was a problem hiding this comment.
The 205 Reset Content status code is defined by RFC 9110 as a response that must not contain a body. It should be excluded from this validation rule to prevent false positives when auditing valid API specifications.
| if !strings.HasPrefix(code, "2") || code == "204" { | |
| if !strings.HasPrefix(code, "2") || code == "204" || code == "205" { |
validation/rules_design.go
Outdated
| if len(resp.Content) == 0 { | ||
| out = append(out, Violation{ | ||
| File: filePath, | ||
| Message: fmt.Sprintf("%s — response %s is missing a `content` block. All 2xx responses (except 204) must declare a content-type.", label, code), |
There was a problem hiding this comment.
Updating the violation message to include 205 in the list of excluded status codes for clarity.
| Message: fmt.Sprintf("%s — response %s is missing a `content` block. All 2xx responses (except 204) must declare a content-type.", label, code), | |
| Message: fmt.Sprintf("%s — response %s is missing a content block. All 2xx responses (except 204 and 205) must declare a content-type.", label, code), |
| if len(vs) != 0 { | ||
| t.Errorf("expected 0 violations for 204 response without content, got %d", len(vs)) | ||
| } | ||
| } |
There was a problem hiding this comment.
Adding a test case for the 205 Reset Content status code to ensure it is correctly handled as an exception to Rule 47.
}
func TestCheckRule47_Valid205(t *testing.T) {
doc := &openapi3.T{
OpenAPI: "3.0.0",
Info: &openapi3.Info{Title: "Test", Version: "v1"},
Paths: openapi3.NewPaths(),
}
responses := openapi3.NewResponses()
desc := "Reset Content"
responses.Set("205", &openapi3.ResponseRef{Value: &openapi3.Response{Description: &desc}})
doc.Paths.Set("/api/test", &openapi3.PathItem{
Post: &openapi3.Operation{Responses: responses},
})
vs := checkRule47("api.yml", doc, AuditOptions{})
if len(vs) != 0 {
t.Errorf("expected 0 violations for 205 response without content, got %d", len(vs))
}
}Signed-off-by: Junnygram <junnexclusive@gmail.com>
Closes #719. Ensures 2xx responses (except 204) have a content block and schema.