Skip to content

Commit 67f0b23

Browse files
authored
openapi3filter: de-register ZipFileBodyDecoder and make a few decoders public (#1059)
Signed-off-by: Pierre Fenoll <[email protected]>
1 parent 6da871e commit 67f0b23

File tree

5 files changed

+36
-20
lines changed

5 files changed

+36
-20
lines changed

.github/docs/openapi3filter.txt

+12
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ FUNCTIONS
4242
func ConvertErrors(err error) error
4343
ConvertErrors converts all errors to the appropriate error format.
4444

45+
func CsvBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error)
46+
CsvBodyDecoder is a body decoder that decodes a csv body to a string.
47+
4548
func DefaultErrorEncoder(_ context.Context, err error, w http.ResponseWriter)
4649
DefaultErrorEncoder writes the error to the ResponseWriter, by default a
4750
content type of text/plain, a body of the plain text of the error, and a
@@ -58,9 +61,11 @@ func JSONBodyDecoder(body io.Reader, header http.Header, schema *openapi3.Schema
5861
JSONBodyDecoder decodes a JSON formatted body. It is public so that is easy
5962
to register additional JSON based formats.
6063

64+
func MultipartBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error)
6165
func NoopAuthenticationFunc(context.Context, *AuthenticationInput) error
6266
NoopAuthenticationFunc is an AuthenticationFunc
6367

68+
func PlainBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error)
6469
func RegisterBodyDecoder(contentType string, decoder BodyDecoder)
6570
RegisterBodyDecoder registers a request body's decoder for a content type.
6671

@@ -84,6 +89,7 @@ func UnregisterBodyDecoder(contentType string)
8489
func UnregisterBodyEncoder(contentType string)
8590
UnregisterBodyEncoder disables package-wide decoding of contentType values
8691

92+
func UrlencodedBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error)
8793
func ValidateParameter(ctx context.Context, input *RequestValidationInput, parameter *openapi3.Parameter) error
8894
ValidateParameter validates a parameter's value by JSON schema. The function
8995
returns RequestError with a ParseError cause when unable to parse a value.
@@ -121,6 +127,12 @@ func ValidateSecurityRequirements(ctx context.Context, input *RequestValidationI
121127
requirements in order and returns nil on the first valid requirement.
122128
If no requirement is met, errors are returned in order.
123129

130+
func YamlBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error)
131+
func ZipFileBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error)
132+
ZipFileBodyDecoder is a body decoder that decodes a zip file body to a
133+
string. Use with caution as this implementation may be susceptible to a zip
134+
bomb attack.
135+
124136

125137
TYPES
126138

README.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,7 @@ func main() {
130130

131131
## Custom content type for body of HTTP request/response
132132

133-
By default, the library parses a body of the HTTP request and response
134-
if it has one of the following content types: `"text/plain"` or `"application/json"`.
133+
By default, the library parses a body of the HTTP request and response of [a few content types](https://github.com/getkin/kin-openapi/blob/6da871e0e170b7637eb568c265c08bc2b5d6e7a3/openapi3filter/req_resp_decoder.go#L1264) e.g. `"text/plain"` or `"application/json"`.
135134
To support other content types you must register decoders for them:
136135

137136
```go
@@ -295,6 +294,9 @@ for _, path := range doc.Paths.InMatchingOrder() {
295294

296295
## CHANGELOG: Sub-v1 breaking API changes
297296

297+
### v0.131.0
298+
* No longer `openapi3filter.RegisterBodyDecoder` the `openapi3filter.ZipFileBodyDecoder` by default.
299+
298300
### v0.129.0
299301
* `openapi3.Discriminator.Mapping` and `openapi3.OAuthFlow.Scopes` fields went from a `map[string]string` to the new type `StringMap`
300302

openapi3filter/req_resp_decoder.go

+15-15
Original file line numberDiff line numberDiff line change
@@ -1269,16 +1269,15 @@ func init() {
12691269
RegisterBodyDecoder("application/vnd.api+json", JSONBodyDecoder)
12701270
RegisterBodyDecoder("application/octet-stream", FileBodyDecoder)
12711271
RegisterBodyDecoder("application/problem+json", JSONBodyDecoder)
1272-
RegisterBodyDecoder("application/x-www-form-urlencoded", urlencodedBodyDecoder)
1273-
RegisterBodyDecoder("application/x-yaml", yamlBodyDecoder)
1274-
RegisterBodyDecoder("application/yaml", yamlBodyDecoder)
1275-
RegisterBodyDecoder("application/zip", zipFileBodyDecoder)
1276-
RegisterBodyDecoder("multipart/form-data", multipartBodyDecoder)
1277-
RegisterBodyDecoder("text/csv", csvBodyDecoder)
1278-
RegisterBodyDecoder("text/plain", plainBodyDecoder)
1272+
RegisterBodyDecoder("application/x-www-form-urlencoded", UrlencodedBodyDecoder)
1273+
RegisterBodyDecoder("application/x-yaml", YamlBodyDecoder)
1274+
RegisterBodyDecoder("application/yaml", YamlBodyDecoder)
1275+
RegisterBodyDecoder("multipart/form-data", MultipartBodyDecoder)
1276+
RegisterBodyDecoder("text/csv", CsvBodyDecoder)
1277+
RegisterBodyDecoder("text/plain", PlainBodyDecoder)
12791278
}
12801279

1281-
func plainBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error) {
1280+
func PlainBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error) {
12821281
data, err := io.ReadAll(body)
12831282
if err != nil {
12841283
return nil, &ParseError{Kind: KindInvalidFormat, Cause: err}
@@ -1298,15 +1297,15 @@ func JSONBodyDecoder(body io.Reader, header http.Header, schema *openapi3.Schema
12981297
return value, nil
12991298
}
13001299

1301-
func yamlBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error) {
1300+
func YamlBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error) {
13021301
var value any
13031302
if err := yaml.NewDecoder(body).Decode(&value); err != nil {
13041303
return nil, &ParseError{Kind: KindInvalidFormat, Cause: err}
13051304
}
13061305
return value, nil
13071306
}
13081307

1309-
func urlencodedBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error) {
1308+
func UrlencodedBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error) {
13101309
// Validate schema of request body.
13111310
// By the OpenAPI 3 specification request body's schema must have type "object".
13121311
// Properties of the schema describes individual parts of request body.
@@ -1391,7 +1390,7 @@ func decodeProperty(dec valueDecoder, name string, prop *openapi3.SchemaRef, enc
13911390
return decodeValue(dec, name, sm, prop, false)
13921391
}
13931392

1394-
func multipartBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error) {
1393+
func MultipartBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error) {
13951394
if !schema.Value.Type.Is("object") {
13961395
return nil, errors.New("unsupported schema of request body")
13971396
}
@@ -1519,8 +1518,9 @@ func FileBodyDecoder(body io.Reader, header http.Header, schema *openapi3.Schema
15191518
return string(data), nil
15201519
}
15211520

1522-
// zipFileBodyDecoder is a body decoder that decodes a zip file body to a string.
1523-
func zipFileBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error) {
1521+
// ZipFileBodyDecoder is a body decoder that decodes a zip file body to a string.
1522+
// Use with caution as this implementation may be susceptible to a zip bomb attack.
1523+
func ZipFileBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error) {
15241524
buff := bytes.NewBuffer([]byte{})
15251525
size, err := io.Copy(buff, body)
15261526
if err != nil {
@@ -1569,8 +1569,8 @@ func zipFileBodyDecoder(body io.Reader, header http.Header, schema *openapi3.Sch
15691569
return string(content), nil
15701570
}
15711571

1572-
// csvBodyDecoder is a body decoder that decodes a csv body to a string.
1573-
func csvBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error) {
1572+
// CsvBodyDecoder is a body decoder that decodes a csv body to a string.
1573+
func CsvBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error) {
15741574
r := csv.NewReader(body)
15751575

15761576
var sb strings.Builder

openapi3filter/validate_request.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,9 @@ func appendToQueryValues[T any](q url.Values, parameterName string, v []T) {
113113
}
114114

115115
func joinValues(values []any, sep string) string {
116-
strValues := make([]string, len(values))
117-
for i, v := range values {
118-
strValues[i] = fmt.Sprintf("%v", v)
116+
strValues := make([]string, 0, len(values))
117+
for _, v := range values {
118+
strValues = append(strValues, fmt.Sprintf("%v", v))
119119
}
120120
return strings.Join(strValues, sep)
121121
}

openapi3filter/zip_file_upload_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import (
1717
)
1818

1919
func TestValidateZipFileUpload(t *testing.T) {
20+
openapi3filter.RegisterBodyDecoder("application/zip", openapi3filter.ZipFileBodyDecoder)
21+
2022
const spec = `
2123
openapi: 3.0.0
2224
info:

0 commit comments

Comments
 (0)