Skip to content

Commit 44ad6d5

Browse files
rledisezlwj5
authored andcommitted
[go-server] Support min/max/defaults for values (#15185)
* [go-server] Support min/max/defaults for values Enforce, for the go-server, to check the minimum and maximum values specified in the openapi description. Also apply the default if the parameter is not passed. Fix #14013 * Fix merge conflict Co-authored-by: Ween Jiann <16207788+lwj5@users.noreply.github.com> * Improve UnmarshalJSON implementation Co-authored-by: Ween Jiann <16207788+lwj5@users.noreply.github.com> * Improve default value handling for string Co-authored-by: Ween Jiann <16207788+lwj5@users.noreply.github.com> * Fix suggested changes * rework option pattern * add imports based on types/min max values --------- Co-authored-by: Ween Jiann <16207788+lwj5@users.noreply.github.com>
1 parent d3f63ca commit 44ad6d5

39 files changed

+1162
-478
lines changed

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoServerCodegen.java

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,39 @@
1717

1818
package org.openapitools.codegen.languages;
1919

20-
import io.swagger.v3.oas.models.media.ComposedSchema;
21-
import io.swagger.v3.oas.models.media.Schema;
22-
import org.openapitools.codegen.*;
23-
import org.openapitools.codegen.meta.features.*;
20+
import java.io.File;
21+
import java.util.Arrays;
22+
import java.util.EnumSet;
23+
import java.util.HashMap;
24+
import java.util.List;
25+
import java.util.Map;
26+
27+
import org.openapitools.codegen.CliOption;
28+
import org.openapitools.codegen.CodegenConstants;
29+
import org.openapitools.codegen.CodegenModel;
30+
import org.openapitools.codegen.CodegenOperation;
31+
import org.openapitools.codegen.CodegenParameter;
32+
import org.openapitools.codegen.CodegenProperty;
33+
import org.openapitools.codegen.CodegenType;
34+
import org.openapitools.codegen.SupportingFile;
35+
import org.openapitools.codegen.meta.features.DocumentationFeature;
36+
import org.openapitools.codegen.meta.features.GlobalFeature;
37+
import org.openapitools.codegen.meta.features.ParameterFeature;
38+
import org.openapitools.codegen.meta.features.SchemaSupportFeature;
39+
import org.openapitools.codegen.meta.features.SecurityFeature;
40+
import org.openapitools.codegen.meta.features.WireFormatFeature;
2441
import org.openapitools.codegen.model.ModelMap;
42+
import org.openapitools.codegen.model.ModelsMap;
2543
import org.openapitools.codegen.model.OperationMap;
2644
import org.openapitools.codegen.model.OperationsMap;
2745
import org.openapitools.codegen.utils.ModelUtils;
2846
import org.slf4j.Logger;
2947
import org.slf4j.LoggerFactory;
3048

31-
import java.io.File;
32-
import java.util.*;
49+
import com.google.common.collect.Iterables;
50+
51+
import io.swagger.v3.oas.models.media.ComposedSchema;
52+
import io.swagger.v3.oas.models.media.Schema;
3353

3454
public class GoServerCodegen extends AbstractGoCodegen {
3555

@@ -114,7 +134,7 @@ public GoServerCodegen() {
114134
optAddResponseHeaders.defaultValue(addResponseHeaders.toString());
115135
cliOptions.add(optAddResponseHeaders);
116136

117-
137+
118138
// option to exclude service factories; only interfaces are rendered
119139
CliOption optOnlyInterfaces = new CliOption("onlyInterfaces", "Exclude default service creators from output; only generate interfaces");
120140
optOnlyInterfaces.setType("bool");
@@ -287,6 +307,38 @@ public void processOpts() {
287307
.doNotOverwrite());
288308
}
289309

310+
@Override
311+
public ModelsMap postProcessModels(ModelsMap objs) {
312+
// The superclass determines the list of required golang imports. The actual list of imports
313+
// depends on which types are used. So super.postProcessModels must be invoked at the beginning
314+
// of this method.
315+
objs = super.postProcessModels(objs);
316+
317+
List<Map<String, String>> imports = objs.getImports();
318+
319+
for (ModelMap m : objs.getModels()) {
320+
imports.add(createMapping("import", "encoding/json"));
321+
322+
CodegenModel model = m.getModel();
323+
if (model.isEnum) {
324+
continue;
325+
}
326+
327+
Boolean importErrors = false;
328+
329+
for (CodegenProperty param : Iterables.concat(model.vars, model.allVars, model.requiredVars, model.optionalVars)) {
330+
if (param.isNumeric && ((param.minimum != null && param.minimum != "") || (param.maximum != null && param.maximum != ""))) {
331+
importErrors = true;
332+
}
333+
}
334+
335+
if (importErrors) {
336+
imports.add(createMapping("import", "errors"));
337+
}
338+
}
339+
return objs;
340+
}
341+
290342
@Override
291343
public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<ModelMap> allModels) {
292344
objs = super.postProcessOperationsWithModels(objs, allModels);

modules/openapi-generator/src/main/resources/go-server/controller-api.mustache

Lines changed: 143 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -93,35 +93,70 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re
9393
{{#allParams}}
9494
{{#isPathParam}}
9595
{{#isNumber}}
96-
{{paramName}}Param, err := parseFloat32Parameter({{#routers}}{{#mux}}params["{{baseName}}"]{{/mux}}{{#chi}}chi.URLParam(r, "{{baseName}}"){{/chi}}{{/routers}}, {{required}})
97-
if err != nil {
96+
{{paramName}}Param, err := parseNumericParameter[float32](
97+
{{#routers}}{{#mux}}params["{{baseName}}"]{{/mux}}{{#chi}}chi.URLParam(r, "{{baseName}}"){{/chi}}{{/routers}},{{#defaultValue}}
98+
WithDefaultOrParse[float32]({{defaultValue}}, parseFloat32),{{/defaultValue}}{{^defaultValue}}{{#required}}
99+
WithRequire[float32](parseFloat32),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
100+
WithParse[float32](parseFloat32),{{/required}}{{/defaultValue}}{{#minimum}}
101+
WithMinimum[float32]({{minimum}}),{{/minimum}}{{#maximum}}
102+
WithMaximum[float32]({{maximum}}),{{/maximum}}
103+
)
104+
if err != nil {
98105
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
99106
return
100107
}
101108
{{/isNumber}}
102109
{{#isFloat}}
103-
{{paramName}}Param, err := parseFloat32Parameter({{#routers}}{{#mux}}params["{{baseName}}"]{{/mux}}{{#chi}}chi.URLParam(r, "{{baseName}}"){{/chi}}{{/routers}}, {{required}})
110+
{{paramName}}Param, err := parseNumericParameter[float32](
111+
{{#routers}}{{#mux}}params["{{baseName}}"]{{/mux}}{{#chi}}chi.URLParam(r, "{{baseName}}"){{/chi}}{{/routers}},{{#defaultValue}}
112+
WithDefaultOrParse[float32]({{defaultValue}}, parseFloat32),{{/defaultValue}}{{^defaultValue}}{{#required}}
113+
WithRequire[float32](parseFloat32),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
114+
WithParse[float32](parseFloat32),{{/required}}{{/defaultValue}}{{#minimum}}
115+
WithMinimum[float32]({{minimum}}),{{/minimum}}{{#maximum}}
116+
WithMaximum[float32]({{maximum}}),{{/maximum}}
117+
)
104118
if err != nil {
105119
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
106120
return
107121
}
108122
{{/isFloat}}
109123
{{#isDouble}}
110-
{{paramName}}Param, err := parseFloat64Parameter({{#routers}}{{#mux}}params["{{baseName}}"]{{/mux}}{{#chi}}chi.URLParam(r, "{{baseName}}"){{/chi}}{{/routers}}, {{required}})
124+
{{paramName}}Param, err := parseNumericParameter[float64](
125+
{{#routers}}{{#mux}}params["{{baseName}}"]{{/mux}}{{#chi}}chi.URLParam(r, "{{baseName}}"){{/chi}}{{/routers}},{{#defaultValue}}
126+
WithDefaultOrParse[float64]({{defaultValue}}, parseFloat64),{{/defaultValue}}{{^defaultValue}}{{#required}}
127+
WithRequire[float64](parseFloat64),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
128+
WithParse[float64](parseFloat64),{{/required}}{{/defaultValue}}{{#minimum}}
129+
WithMinimum[float64]({{minimum}}),{{/minimum}}{{#maximum}}
130+
WithMaximum[float64]({{maximum}}),{{/maximum}}
131+
)
111132
if err != nil {
112133
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
113134
return
114135
}
115136
{{/isDouble}}
116137
{{#isLong}}
117-
{{paramName}}Param, err := parseInt64Parameter({{#routers}}{{#mux}}params["{{baseName}}"]{{/mux}}{{#chi}}chi.URLParam(r, "{{baseName}}"){{/chi}}{{/routers}}, {{required}})
138+
{{paramName}}Param, err := parseNumericParameter[int64](
139+
{{#routers}}{{#mux}}params["{{baseName}}"]{{/mux}}{{#chi}}chi.URLParam(r, "{{baseName}}"){{/chi}}{{/routers}},{{#defaultValue}}
140+
WithDefaultOrParse[int64]({{defaultValue}}, parseInt64),{{/defaultValue}}{{^defaultValue}}{{#required}}
141+
WithRequire[int64](parseInt64),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
142+
WithParse[int64](parseInt64),{{/required}}{{/defaultValue}}{{#minimum}}
143+
WithMinimum[int64]({{minimum}}),{{/minimum}}{{#maximum}}
144+
WithMaximum[int64]({{maximum}}),{{/maximum}}
145+
)
118146
if err != nil {
119147
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
120148
return
121149
}
122150
{{/isLong}}
123151
{{#isInteger}}
124-
{{paramName}}Param, err := parseInt32Parameter({{#routers}}{{#mux}}params["{{baseName}}"]{{/mux}}{{#chi}}chi.URLParam(r, "{{baseName}}"){{/chi}}{{/routers}}, {{required}})
152+
{{paramName}}Param, err := parseNumericParameter[int32](
153+
{{#routers}}{{#mux}}params["{{baseName}}"]{{/mux}}{{#chi}}chi.URLParam(r, "{{baseName}}"){{/chi}}{{/routers}},{{#defaultValue}}
154+
WithDefaultOrParse[int32]({{defaultValue}}, parseInt32),{{/defaultValue}}{{^defaultValue}}{{#required}}
155+
WithRequire[int32](parseInt32),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
156+
WithParse[int32](parseInt32),{{/required}}{{/defaultValue}}{{#minimum}}
157+
WithMinimum[int32]({{minimum}}),{{/minimum}}{{#maximum}}
158+
WithMaximum[int32]({{maximum}}),{{/maximum}}
159+
)
125160
if err != nil {
126161
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
127162
return
@@ -141,78 +176,143 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re
141176
{{/isPathParam}}
142177
{{#isQueryParam}}
143178
{{#isNumber}}
144-
{{paramName}}Param, err := parseFloat32Parameter(query.Get("{{baseName}}"), {{required}})
179+
{{paramName}}Param, err := parseNumericParameter[float32](
180+
query.Get("{{baseName}}"),{{#defaultValue}}
181+
WithDefaultOrParse[float32]({{defaultValue}}, parseFloat32),{{/defaultValue}}{{^defaultValue}}{{#required}}
182+
WithRequire[float32](parseFloat32),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
183+
WithParse[float32](parseFloat32),{{/required}}{{/defaultValue}}{{#minimum}}
184+
WithMinimum[float32]({{minimum}}),{{/minimum}}{{#maximum}}
185+
WithMaximum[float32]({{maximum}}),{{/maximum}}
186+
)
145187
if err != nil {
146188
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
147189
return
148190
}
149191
{{/isNumber}}
150192
{{#isFloat}}
151-
{{paramName}}Param, err := parseFloat32Parameter(query.Get("{{baseName}}"), {{required}})
193+
{{paramName}}Param, err := parseNumericParameter[float32](
194+
query.Get("{{baseName}}"),{{#defaultValue}}
195+
WithDefaultOrParse[float32]({{defaultValue}}, parseFloat32),{{/defaultValue}}{{^defaultValue}}{{#required}}
196+
WithRequire[float32](parseFloat32),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
197+
WithParse[float32](parseFloat32),{{/required}}{{/defaultValue}}{{#minimum}}
198+
WithMinimum[float32]({{minimum}}),{{/minimum}}{{#maximum}}
199+
WithMaximum[float32]({{maximum}}),{{/maximum}}
200+
)
152201
if err != nil {
153202
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
154203
return
155204
}
156205
{{/isFloat}}
157206
{{#isDouble}}
158-
{{paramName}}Param, err := parseFloat64Parameter(query.Get("{{baseName}}"), {{required}})
207+
{{paramName}}Param, err := parseNumericParameter[float64](
208+
query.Get("{{baseName}}"),{{#defaultValue}}
209+
WithDefaultOrParse[float64]({{defaultValue}}, parseFloat64),{{/defaultValue}}{{^defaultValue}}{{#required}}
210+
WithRequire[float64](parseFloat64),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
211+
WithParse[float64](parseFloat64),{{/required}}{{/defaultValue}}{{#minimum}}
212+
WithMinimum[float64]({{minimum}}),{{/minimum}}{{#maximum}}
213+
WithMaximum[float64]({{maximum}}),{{/maximum}}
214+
)
159215
if err != nil {
160216
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
161217
return
162218
}
163219
{{/isDouble}}
164220
{{#isLong}}
165-
{{paramName}}Param, err := parseInt64Parameter(query.Get("{{baseName}}"), {{required}})
221+
{{paramName}}Param, err := parseNumericParameter[int64](
222+
query.Get("{{baseName}}"),{{#defaultValue}}
223+
WithDefaultOrParse[int64]({{defaultValue}}, parseInt64),{{/defaultValue}}{{^defaultValue}}{{#required}}
224+
WithRequire[int64](parseInt64),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
225+
WithParse[int64](parseInt64),{{/required}}{{/defaultValue}}{{#minimum}}
226+
WithMinimum[int64]({{minimum}}),{{/minimum}}{{#maximum}}
227+
WithMaximum[int64]({{maximum}}),{{/maximum}}
228+
)
166229
if err != nil {
167230
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
168231
return
169232
}
170233
{{/isLong}}
171234
{{#isInteger}}
172-
{{paramName}}Param, err := parseInt32Parameter(query.Get("{{baseName}}"), {{required}})
235+
{{paramName}}Param, err := parseNumericParameter[int32](
236+
query.Get("{{baseName}}"),{{#defaultValue}}
237+
WithDefaultOrParse[int32]({{defaultValue}}, parseInt32),{{/defaultValue}}{{^defaultValue}}{{#required}}
238+
WithRequire[int32](parseInt32),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
239+
WithParse[int32](parseInt32),{{/required}}{{/defaultValue}}{{#minimum}}
240+
WithMinimum[int32]({{minimum}}),{{/minimum}}{{#maximum}}
241+
WithMaximum[int32]({{maximum}}),{{/maximum}}
242+
)
173243
if err != nil {
174244
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
175245
return
176246
}
177247
{{/isInteger}}
178248
{{#isBoolean}}
179-
{{paramName}}Param, err := parseBoolParameter(query.Get("{{baseName}}"), {{required}})
249+
{{paramName}}Param, err := parseBoolParameter(
250+
query.Get("{{baseName}}"),{{#defaultValue}}
251+
WithDefaultOrParse[bool]({{defaultValue}}, parseBool),{{/defaultValue}}{{^defaultValue}}{{#required}}
252+
WithRequire[bool](parseBool),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
253+
WithParse[float32](parseBool),{{/required}}{{/defaultValue}}
254+
)
180255
if err != nil {
181256
w.WriteHeader(500)
182257
return
183258
}
184259
{{/isBoolean}}
185260
{{#isArray}}
186261
{{#items.isNumber}}
187-
{{paramName}}Param, err := parseFloat32ArrayParameter(query.Get("{{baseName}}"), {{required}})
262+
{{paramName}}Param, err := parseNumericArrayParameter[float32](
263+
query.Get("{{baseName}}"), ",", {{required}},
264+
WithParse[float32](parseFloat32),{{#minimum}}
265+
WithMinimum[float32]({{minimum}}),{{/minimum}}{{#maximum}}
266+
WithMaximum[float32]({{maximum}}),{{/maximum}}
267+
)
188268
if err != nil {
189269
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
190270
return
191271
}
192272
{{/items.isNumber}}
193273
{{#items.isFloat}}
194-
{{paramName}}Param, err := parseFloat32ArrayParameter(query.Get("{{baseName}}"), {{required}})
274+
{{paramName}}Param, err := parseNumericArrayParameter[float32](
275+
query.Get("{{baseName}}"), ",", {{required}},
276+
WithParse[float32](parseFloat32),{{#minimum}}
277+
WithMinimum[float32]({{minimum}}),{{/minimum}}{{#maximum}}
278+
WithMaximum[float32]({{maximum}}),{{/maximum}}
279+
)
195280
if err != nil {
196281
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
197282
return
198283
}
199284
{{/items.isFloat}}
200285
{{#items.isDouble}}
201-
{{paramName}}Param, err := parseFloat64ArrayParameter(query.Get("{{baseName}}"), {{required}})
286+
{{paramName}}Param, err := parseNumericArrayParameter[float64](
287+
query.Get("{{baseName}}"), ",", {{required}},
288+
WithParse[float64](parseFloat64),{{#minimum}}
289+
WithMinimum[float64]({{minimum}}),{{/minimum}}{{#maximum}}
290+
WithMaximum[float64]({{maximum}}),{{/maximum}}
291+
)
202292
if err != nil {
203293
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
204294
return
205295
}
206296
{{/items.isDouble}}
207297
{{#items.isLong}}
208-
{{paramName}}Param, err := parseInt64ArrayParameter(query.Get("{{baseName}}"), ",", {{required}})
298+
{{paramName}}Param, err := parseNumericArrayParameter[int64](
299+
query.Get("{{baseName}}"), ",", {{required}},
300+
WithParse[int64](parseInt64),{{#minimum}}
301+
WithMinimum[int64]({{minimum}}),{{/minimum}}{{#maximum}}
302+
WithMaximum[int64]({{maximum}}),{{/maximum}}
303+
)
209304
if err != nil {
210305
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
211306
return
212307
}
213308
{{/items.isLong}}
214309
{{#items.isInteger}}
215-
{{paramName}}Param, err := parseInt32ArrayParameter(query.Get("{{baseName}}"), ",", {{required}})
310+
{{paramName}}Param, err := parseNumericArrayParameter[int32](
311+
query.Get("{{baseName}}"), ",", {{required}},
312+
WithParse[int32](parseInt32),{{#minimum}}
313+
WithMinimum[int32]({{minimum}}),{{/minimum}}{{#maximum}}
314+
WithMaximum[int32]({{maximum}}),{{/maximum}}
315+
)
216316
if err != nil {
217317
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
218318
return
@@ -237,7 +337,15 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re
237337
{{^isInteger}}
238338
{{^isBoolean}}
239339
{{^isArray}}
340+
{{#defaultValue}}
341+
{{paramName}}Param := "{{defaultValue}}"
342+
if query.Has("{{baseName}}") {
343+
{{paramName}}Param = query.Get("{{baseName}}")
344+
}
345+
{{/defaultValue}}
346+
{{^defaultValue}}
240347
{{paramName}}Param := query.Get("{{baseName}}")
348+
{{/defaultValue}}
241349
{{/isArray}}
242350
{{/isBoolean}}
243351
{{/isInteger}}
@@ -257,21 +365,29 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re
257365
}
258366
{{/isFile}}
259367
{{#isLong}}{{#isArray}}
260-
{{paramName}}Param, err := parseInt64ArrayParameter(r.FormValue("{{baseName}}"), ",", {{required}}){{/isArray}}{{^isArray}}
261-
{{paramName}}Param, err := parseInt64Parameter(r.FormValue("{{baseName}}"), {{required}}){{/isArray}}
368+
{{paramName}}Param, err := parseNumericArrayParameter[int64](
369+
r.FormValue("{{baseName}}"), ",", {{required}},
370+
WithParse[int64](parseInt64),{{#minimum}}
371+
WithMinimum[int64]({{minimum}}),{{/minimum}}{{#maximum}}
372+
WithMaximum[int64]({{maximum}}),{{/maximum}}
373+
)
262374
if err != nil {
263375
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
264376
return
265377
}
266-
{{/isLong}}
378+
{{/isArray}}{{/isLong}}
267379
{{#isInteger}}{{#isArray}}
268-
{{paramName}}Param, err := parseInt32ArrayParameter(r.FormValue("{{baseName}}"), ",", {{required}}){{/isArray}}{{^isArray}}
269-
{{paramName}}Param, err := parseInt32Parameter(r.FormValue("{{baseName}}"), {{required}}){{/isArray}}
380+
{{paramName}}Param, err := parseNumericArrayParameter[int32](
381+
r.FormValue("{{baseName}}"), ",", {{required}},
382+
WithParse[int32](parseInt32),{{#minimum}}
383+
WithMinimum[int32]({{minimum}}),{{/minimum}}{{#maximum}}
384+
WithMaximum[int32]({{maximum}}),{{/maximum}}
385+
)
270386
if err != nil {
271387
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
272388
return
273389
}
274-
{{/isInteger}}
390+
{{/isArray}}{{/isInteger}}
275391
{{^isFile}}
276392
{{^isLong}}
277393
{{paramName}}Param := r.FormValue("{{baseName}}")
@@ -306,6 +422,10 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re
306422
if err := Assert{{baseType}}Required({{paramName}}Param); err != nil {
307423
c.errorHandler(w, r, err, nil)
308424
return
425+
}
426+
if err := Assert{{baseType}}Constraints({{paramName}}Param); err != nil {
427+
c.errorHandler(w, r, err, nil)
428+
return
309429
}
310430
{{/isModel}}
311431
{{/isArray}}

0 commit comments

Comments
 (0)