Skip to content

Commit 53e5986

Browse files
authored
[Go] Parse int arrays and respect the 'required' property (#9120)
* Added int arrays parsing in parameters. Respect the 'required' property. * Replaced spaces with tabs * Generate samples with new spacing * Removed unused import * Merged with latest master
1 parent 63fdd3e commit 53e5986

File tree

8 files changed

+272
-125
lines changed

8 files changed

+272
-125
lines changed

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

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -311,16 +311,17 @@ public String toModel(String name, boolean doUnderscore) {
311311

312312
@Override
313313
public String toApiFilename(String name) {
314+
final String apiName;
314315
// replace - with _ e.g. created-at => created_at
315-
name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
316-
316+
String api = name.replaceAll("-", "_");
317317
// e.g. PetApi.go => pet_api.go
318-
name = "api_" + underscore(name);
319-
if (isReservedFilename(name)) {
320-
LOGGER.warn(name + ".go with suffix (reserved word) cannot be used as filename. Renamed to " + name + "_.go");
321-
name += "_";
318+
api = "api_" + underscore(api);
319+
if (isReservedFilename(api)) {
320+
LOGGER.warn(name + ".go with suffix (reserved word) cannot be used as filename. Renamed to " + api + "_.go");
321+
api += "_";
322322
}
323-
return name;
323+
apiName = api;
324+
return apiName;
324325
}
325326

326327
/**
@@ -807,7 +808,7 @@ public void postProcessFile(File file, String fileType) {
807808
return; // skip if GO_POST_PROCESS_FILE env variable is not defined
808809
}
809810

810-
// only procees the following type (or we can simply rely on the file extension to check if it's a Go file)
811+
// only process the following type (or we can simply rely on the file extension to check if it's a Go file)
811812
Set<String> supportedFileType = new HashSet<String>(
812813
Arrays.asList(
813814
"supporting-mustache",

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,10 +235,8 @@ public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> o
235235
// override imports to only include packages for interface parameters
236236
imports.clear();
237237

238-
boolean addedOptionalImport = false;
239238
boolean addedTimeImport = false;
240239
boolean addedOSImport = false;
241-
boolean addedReflectImport = false;
242240
for (CodegenOperation operation : operations) {
243241
for (CodegenParameter param : operation.allParams) {
244242
// import "os" if the operation uses files
@@ -247,7 +245,7 @@ public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> o
247245
addedOSImport = true;
248246
}
249247

250-
// import "time" if the operation has a required time parameter.
248+
// import "time" if the operation has a required time parameter
251249
if (param.required) {
252250
if (!addedTimeImport && "time.Time".equals(param.dataType)) {
253251
imports.add(createMapping("import", "time"));

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

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ type {{classname}}Controller struct {
1616

1717
// New{{classname}}Controller creates a default api controller
1818
func New{{classname}}Controller(s {{classname}}Servicer) Router {
19-
return &{{classname}}Controller{ service: s }
19+
return &{{classname}}Controller{service: s}
2020
}
2121

2222
// Routes returns all of the api route for the {{classname}}Controller
@@ -34,11 +34,18 @@ func (c *{{classname}}Controller) Routes() Routes {
3434
// {{nickname}} - {{{summary}}}
3535
func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Request) {
3636
{{#hasFormParams}}
37-
err := r.ParseForm()
38-
if err != nil {
37+
{{#isMultipart}}
38+
if err := r.ParseMultipartForm(32 << 20); err != nil {
39+
w.WriteHeader(http.StatusBadRequest)
40+
return
41+
}
42+
{{/isMultipart}}
43+
{{^isMultipart}}
44+
if err := r.ParseForm(); err != nil {
3945
w.WriteHeader(http.StatusBadRequest)
4046
return
4147
}
48+
{{/isMultipart}}
4249
{{/hasFormParams}}
4350
{{#hasPathParams}}
4451
params := mux.Vars(r)
@@ -49,14 +56,14 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re
4956
{{#allParams}}
5057
{{#isPathParam}}
5158
{{#isLong}}
52-
{{paramName}}, err := parseInt64Parameter(params["{{baseName}}"])
59+
{{paramName}}, err := parseInt64Parameter(params["{{baseName}}"], {{required}})
5360
if err != nil {
5461
w.WriteHeader(http.StatusBadRequest)
5562
return
5663
}
57-
{{/isLong}}
64+
{{/isLong}}
5865
{{#isInteger}}
59-
{{paramName}}, err := parseInt32Parameter(params["{{baseName}}"])
66+
{{paramName}}, err := parseInt32Parameter(params["{{baseName}}"], {{required}})
6067
if err != nil {
6168
w.WriteHeader(http.StatusBadRequest)
6269
return
@@ -69,14 +76,14 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re
6976
{{/isPathParam}}
7077
{{#isQueryParam}}
7178
{{#isLong}}
72-
{{paramName}}, err := parseInt64Parameter(query.Get("{{baseName}}"))
79+
{{paramName}}, err := parseInt64Parameter(query.Get("{{baseName}}"), {{required}})
7380
if err != nil {
7481
w.WriteHeader(http.StatusBadRequest)
7582
return
7683
}
7784
{{/isLong}}
7885
{{#isInteger}}
79-
{{paramName}}, err := parseInt32Parameter(query.Get("{{baseName}}"))
86+
{{paramName}}, err := parseInt32Parameter(query.Get("{{baseName}}"), {{required}})
8087
if err != nil {
8188
w.WriteHeader(http.StatusBadRequest)
8289
return
@@ -98,24 +105,26 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re
98105
{{/isLong}}
99106
{{/isQueryParam}}
100107
{{#isFormParam}}
101-
{{#isFile}}
102-
{{#isArray}}
103-
{{paramName}}, err := ReadFormFilesToTempFiles(r, "{{baseName}}"){{/isArray}}{{^isArray}}{{paramName}}, err := ReadFormFileToTempFile(r, "{{baseName}}")
108+
{{#isFile}}{{#isArray}}
109+
{{paramName}}, err := ReadFormFilesToTempFiles(r, "{{baseName}}"){{/isArray}}{{^isArray}}
110+
{{paramName}}, err := ReadFormFileToTempFile(r, "{{baseName}}")
104111
{{/isArray}}
105112
if err != nil {
106113
w.WriteHeader(http.StatusBadRequest)
107114
return
108115
}
109116
{{/isFile}}
110-
{{#isLong}}
111-
{{paramName}}, err := parseInt64Parameter( r.FormValue("{{baseName}}"))
117+
{{#isLong}}{{#isArray}}
118+
{{paramName}}, err := parseInt64ArrayParameter(r.FormValue("{{baseName}}"), ",", {{required}}){{/isArray}}{{^isArray}}
119+
{{paramName}}, err := parseInt64Parameter(r.FormValue("{{baseName}}"), {{required}}){{/isArray}}
112120
if err != nil {
113121
w.WriteHeader(http.StatusBadRequest)
114122
return
115123
}
116124
{{/isLong}}
117-
{{#isInteger}}
118-
{{paramName}}, err := parseInt32Parameter( r.FormValue("{{baseName}}"))
125+
{{#isInteger}}{{#isArray}}
126+
{{paramName}}, err := parseInt32ArrayParameter(r.FormValue("{{baseName}}"), ",", {{required}}){{/isArray}}{{^isArray}}
127+
{{paramName}}, err := parseInt32Parameter(r.FormValue("{{baseName}}"), {{required}}){{/isArray}}
119128
if err != nil {
120129
w.WriteHeader(http.StatusBadRequest)
121130
return
@@ -139,12 +148,12 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re
139148
{{/isBodyParam}}
140149
{{/allParams}}
141150
result, err := c.service.{{nickname}}(r.Context(){{#allParams}}, {{#isBodyParam}}*{{/isBodyParam}}{{paramName}}{{/allParams}})
142-
//If an error occured, encode the error with the status code
151+
// If an error occurred, encode the error with the status code
143152
if err != nil {
144153
EncodeJSONResponse(err.Error(), &result.Code,{{#addResponseHeaders}} result.Headers,{{/addResponseHeaders}} w)
145154
return
146155
}
147-
//If no error, encode the body and the result code
156+
// If no error, encode the body and the result code
148157
EncodeJSONResponse(result.Body, &result.Code,{{#addResponseHeaders}} result.Headers,{{/addResponseHeaders}} w)
149-
158+
150159
}{{/operation}}{{/operations}}

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

Lines changed: 81 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,24 @@ package {{packageName}}
33

44
import (
55
"encoding/json"
6+
"errors"
7+
"github.com/gorilla/mux"
8+
{{#featureCORS}}
9+
"github.com/gorilla/handlers"
10+
{{/featureCORS}}
611
"io/ioutil"
712
"mime/multipart"
813
"net/http"
914
"os"
1015
"strconv"
11-
{{#featureCORS}}
12-
"github.com/gorilla/handlers"
13-
{{/featureCORS}}
14-
"github.com/gorilla/mux"
16+
"strings"
1517
)
1618

1719
// A Route defines the parameters for an api endpoint
1820
type Route struct {
19-
Name string
20-
Method string
21-
Pattern string
21+
Name string
22+
Method string
23+
Pattern string
2224
HandlerFunc http.HandlerFunc
2325
}
2426

@@ -30,6 +32,8 @@ type Router interface {
3032
Routes() Routes
3133
}
3234

35+
const errMsgRequiredMissing = "required parameter is missing"
36+
3337
// NewRouter creates a new router for any number of api routers
3438
func NewRouter(routers ...Router) *mux.Router {
3539
router := mux.NewRouter().StrictSlash(true)
@@ -134,17 +138,34 @@ func readFileHeaderToTempFile(fileHeader *multipart.FileHeader) (*os.File, error
134138
return file, nil
135139
}
136140

137-
// parseInt64Parameter parses a string parameter to an int64
138-
func parseInt64Parameter(param string) (int64, error) {
141+
// parseInt64Parameter parses a string parameter to an int64.
142+
func parseInt64Parameter(param string, required bool) (int64, error) {
143+
if param == "" {
144+
if required {
145+
return 0, errors.New(errMsgRequiredMissing)
146+
}
147+
148+
return 0, nil
149+
}
150+
139151
return strconv.ParseInt(param, 10, 64)
140152
}
141153

142-
// parseInt32Parameter parses a string parameter to an int32
143-
func parseInt32Parameter(param string) (int32, error) {
154+
// parseInt32Parameter parses a string parameter to an int32.
155+
func parseInt32Parameter(param string, required bool) (int32, error) {
156+
if param == "" {
157+
if required {
158+
return 0, errors.New(errMsgRequiredMissing)
159+
}
160+
161+
return 0, nil
162+
}
163+
144164
val, err := strconv.ParseInt(param, 10, 32)
145165
if err != nil {
146166
return -1, err
147167
}
168+
148169
return int32(val), nil
149170
}
150171

@@ -154,5 +175,54 @@ func parseBoolParameter(param string) (bool, error) {
154175
if err != nil {
155176
return false, err
156177
}
178+
157179
return bool(val), nil
158180
}
181+
182+
// parseInt64ArrayParameter parses a string parameter containing array of values to []int64.
183+
func parseInt64ArrayParameter(param, delim string, required bool) ([]int64, error) {
184+
if param == "" {
185+
if required {
186+
return nil, errors.New(errMsgRequiredMissing)
187+
}
188+
189+
return nil, nil
190+
}
191+
192+
str := strings.Split(param, delim)
193+
ints := make([]int64, len(str))
194+
195+
for i, s := range str {
196+
if v, err := strconv.ParseInt(s, 10, 64); err != nil {
197+
return nil, err
198+
} else {
199+
ints[i] = v
200+
}
201+
}
202+
203+
return ints, nil
204+
}
205+
206+
// parseInt32ArrayParameter parses a string parameter containing array of values to []int32.
207+
func parseInt32ArrayParameter(param, delim string, required bool) ([]int32, error) {
208+
if param == "" {
209+
if required {
210+
return nil, errors.New(errMsgRequiredMissing)
211+
}
212+
213+
return nil, nil
214+
}
215+
216+
str := strings.Split(param, delim)
217+
ints := make([]int32, len(str))
218+
219+
for i, s := range str {
220+
if v, err := strconv.ParseInt(s, 10, 32); err != nil {
221+
return nil, err
222+
} else {
223+
ints[i] = int32(v)
224+
}
225+
}
226+
227+
return ints, nil
228+
}

0 commit comments

Comments
 (0)