Skip to content

Commit d0339f5

Browse files
authored
Add RequestBodyEnforcer (#12)
1 parent c774271 commit d0339f5

File tree

3 files changed

+78
-1
lines changed

3 files changed

+78
-1
lines changed

.golangci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,5 @@ issues:
3434
- linters:
3535
- gomnd
3636
- goconst
37+
- dupl
3738
path: "_test.go"

openapi3/reflect.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,20 @@ const (
6969
mimeMultipart = "multipart/form-data"
7070
)
7171

72+
// RequestBodyEnforcer enables request body for GET and HEAD methods.
73+
//
74+
// Should be implemented on input structure, function body can be empty.
75+
// Forcing request body is not recommended and should only be used for backwards compatibility.
76+
type RequestBodyEnforcer interface {
77+
ForceRequestBody()
78+
}
79+
7280
func (r *Reflector) parseRequestBody(o *Operation, input interface{}, tag, mime string, httpMethod string) error {
7381
httpMethod = strings.ToUpper(httpMethod)
82+
_, forceRequestBody := input.(RequestBodyEnforcer)
7483

7584
// GET and HEAD requests should not have body.
76-
if httpMethod == http.MethodGet || httpMethod == http.MethodHead {
85+
if (httpMethod == http.MethodGet || httpMethod == http.MethodHead) && !forceRequestBody {
7786
return nil
7887
}
7988

openapi3/reflect_test.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,3 +320,70 @@ func TestReflector_SetRequest_pathParamAndBody(t *testing.T) {
320320

321321
assertjson.Equal(t, expected, b, string(b))
322322
}
323+
324+
type WithReqBody PathParamAndBody
325+
326+
func (*WithReqBody) ForceRequestBody() {}
327+
328+
func TestRequestBodyEnforcer(t *testing.T) {
329+
reflector := openapi3.Reflector{}
330+
op := openapi3.Operation{}
331+
332+
err := reflector.SetRequest(&op, new(WithReqBody), http.MethodGet)
333+
assert.NoError(t, err)
334+
335+
s := reflector.SpecEns()
336+
s.Info.Title = apiName
337+
s.Info.Version = apiVersion
338+
assert.NoError(t, s.AddOperation(http.MethodGet, "/somewhere/{id}", op))
339+
340+
b, err := json.MarshalIndent(s, "", " ")
341+
assert.NoError(t, err)
342+
343+
expected := []byte(`{
344+
"openapi": "3.0.2",
345+
"info": {
346+
"title": "SampleAPI",
347+
"version": "1.2.3"
348+
},
349+
"paths": {
350+
"/somewhere/{id}": {
351+
"get": {
352+
"parameters": [
353+
{
354+
"name": "id",
355+
"in": "path",
356+
"required": true,
357+
"schema": {
358+
"type": "string"
359+
}
360+
}
361+
],
362+
"requestBody": {
363+
"content": {
364+
"application/json": {
365+
"schema": {
366+
"$ref": "#/components/schemas/Openapi3TestWithReqBody"
367+
}
368+
}
369+
}
370+
},
371+
"responses": {}
372+
}
373+
}
374+
},
375+
"components": {
376+
"schemas": {
377+
"Openapi3TestWithReqBody": {
378+
"type": "array",
379+
"items": {
380+
"type": "string"
381+
},
382+
"nullable": true
383+
}
384+
}
385+
}
386+
}`)
387+
388+
assertjson.Equal(t, expected, b, string(b))
389+
}

0 commit comments

Comments
 (0)