Skip to content

Commit 93488f4

Browse files
aeneasrjirikuncar
andauthored
Resolve several issues in generated Go code (#8491)
* [go] use regular stdlib import names * [go] support primitive oneOf types See #8489 * [go] improve pbv/pbr handling Improves the way pass-by-value and pass-by-reference variables are used. Closes #8489 * [go] improve generated documentation * [go] adopt pointer changes in interface * [go] regenerate sample * [go] resolve pointer issues * [go] regenerate clients and avoid pointers on primitive return values * [go] improve Exec() return value handling * [go] regernate files * [go] use go modules * [go] properly handle polymorph decode If polymorphism without discriminator was used, the previous code was unable to properly decode the vaules. By using a strict decoder, which rejects unknown fields, type guessing now works. * [go] make GetActualInstance not panic on nil * [go] return GenericOpenAPIError as pointer * [go] clarify helper function godoc * [go] address test regression error type * [go] regenerate go samples * [go] resolve go mod issues and test regressions * [go] resolve merge conflicts and regenerate * [go] resolve merge conflicts * [go] Replace spaces with tabs Co-authored-by: Jiri Kuncar <[email protected]> * [go] Replace spaces with tabs Co-authored-by: Jiri Kuncar <[email protected]> Co-authored-by: Jiri Kuncar <[email protected]>
1 parent 55ffdb7 commit 93488f4

File tree

91 files changed

+2705
-1898
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+2705
-1898
lines changed

modules/openapi-generator/src/main/resources/go/README.mustache

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ go get golang.org/x/net/context
3030
Put the package under your project folder and add the following in import:
3131

3232
```golang
33-
import sw "./{{packageName}}"
33+
import {{packageName}} "{{gitHost}}/{{gitUserId}}/{{gitRepoId}}{{#isGoSubmodule}}/{{packageName}}{{/isGoSubmodule}}"
3434
```
3535

3636
To use a proxy, set the environment variable `HTTP_PROXY`:
@@ -48,15 +48,15 @@ Default configuration comes with `Servers` field that contains server objects as
4848
For using other server than the one defined on index 0 set context value `sw.ContextServerIndex` of type `int`.
4949

5050
```golang
51-
ctx := context.WithValue(context.Background(), sw.ContextServerIndex, 1)
51+
ctx := context.WithValue(context.Background(), {{packageName}}.ContextServerIndex, 1)
5252
```
5353

5454
### Templated Server URL
5555

5656
Templated server URL is formatted using default variables from configuration or from context value `sw.ContextServerVariables` of type `map[string]string`.
5757

5858
```golang
59-
ctx := context.WithValue(context.Background(), sw.ContextServerVariables, map[string]string{
59+
ctx := context.WithValue(context.Background(), {{packageName}}.ContextServerVariables, map[string]string{
6060
"basePath": "v2",
6161
})
6262
```
@@ -70,10 +70,10 @@ An operation is uniquely identified by `"{classname}Service.{nickname}"` string.
7070
Similar rules for overriding default operation server index and variables applies by using `sw.ContextOperationServerIndices` and `sw.ContextOperationServerVariables` context maps.
7171

7272
```
73-
ctx := context.WithValue(context.Background(), sw.ContextOperationServerIndices, map[string]int{
73+
ctx := context.WithValue(context.Background(), {{packageName}}.ContextOperationServerIndices, map[string]int{
7474
"{classname}Service.{nickname}": 2,
7575
})
76-
ctx = context.WithValue(context.Background(), sw.ContextOperationServerVariables, map[string]map[string]string{
76+
ctx = context.WithValue(context.Background(), {{packageName}}.ContextOperationServerVariables, map[string]map[string]string{
7777
"{classname}Service.{nickname}": {
7878
"port": "8443",
7979
},
@@ -117,7 +117,7 @@ Note, each API key must be added to a map of `map[string]APIKey` where the key i
117117
Example
118118

119119
```golang
120-
auth := context.WithValue(context.Background(), sw.ContextAccessToken, "BEARERTOKENSTRING")
120+
auth := context.WithValue(context.Background(), sw.ContextAccessToken, "BEARER_TOKEN_STRING")
121121
r, err := client.Service.Operation(auth, args)
122122
```
123123

@@ -142,7 +142,7 @@ r, err := client.Service.Operation(auth, args)
142142
Example
143143

144144
```golang
145-
authConfig := sw.HttpSignatureAuth{
145+
authConfig := client.HttpSignatureAuth{
146146
KeyId: "my-key-id",
147147
PrivateKeyPath: "rsa.pem",
148148
Passphrase: "my-passphrase",

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

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@ package {{packageName}}
44
{{#operations}}
55
import (
66
"bytes"
7-
_context "context"
8-
_ioutil "io/ioutil"
9-
_nethttp "net/http"
10-
_neturl "net/url"
7+
"context"
8+
"io/ioutil"
9+
"net/http"
10+
"net/url"
1111
{{#imports}} "{{import}}"
1212
{{/imports}}
1313
)
1414

1515
// Linger please
1616
var (
17-
_ _context.Context
17+
_ context.Context
1818
)
1919
{{#generateInterfaces}}
2020

@@ -28,22 +28,22 @@ type {{classname}} interface {
2828
{{{unescapedNotes}}}
2929
{{/notes}}
3030

31-
@param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().{{#pathParams}}
31+
@param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().{{#pathParams}}
3232
@param {{paramName}}{{#description}} {{{.}}}{{/description}}{{/pathParams}}
3333
@return {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request
3434
{{#isDeprecated}}
3535

3636
Deprecated
3737
{{/isDeprecated}}
3838
*/
39-
{{{nickname}}}(ctx _context.Context{{#pathParams}}, {{paramName}} {{{dataType}}}{{/pathParams}}) {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request
39+
{{{nickname}}}(ctx context.Context{{#pathParams}}, {{paramName}} {{{dataType}}}{{/pathParams}}) {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request
4040

4141
// {{nickname}}Execute executes the request{{#returnType}}
4242
// @return {{{.}}}{{/returnType}}
4343
{{#isDeprecated}}
4444
// Deprecated
4545
{{/isDeprecated}}
46-
{{nickname}}Execute(r {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request) ({{#returnType}}{{{.}}}, {{/returnType}}*_nethttp.Response, error)
46+
{{nickname}}Execute(r {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request) ({{#returnType}}{{^isArray}}{{^returnTypeIsPrimitive}}*{{/returnTypeIsPrimitive}}{{/isArray}}{{{.}}}, {{/returnType}}*http.Response, error)
4747
{{/operation}}
4848
}
4949
{{/generateInterfaces}}
@@ -53,8 +53,11 @@ type {{classname}}Service service
5353
{{#operation}}
5454

5555
type {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request struct {
56-
ctx _context.Context
57-
ApiService {{#generateInterfaces}}{{classname}}{{/generateInterfaces}}{{^generateInterfaces}}*{{classname}}Service{{/generateInterfaces}}
56+
ctx context.Context{{#generateInterfaces}}
57+
ApiService {{classname}}
58+
{{/generateInterfaces}}{{^generateInterfaces}}
59+
ApiService *{{classname}}Service
60+
{{/generateInterfaces}}
5861
{{#allParams}}
5962
{{paramName}} {{^isPathParam}}*{{/isPathParam}}{{{dataType}}}
6063
{{/allParams}}
@@ -71,7 +74,7 @@ func (r {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Reques
7174
return r
7275
}{{/isPathParam}}{{/allParams}}
7376

74-
func (r {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request) Execute() ({{#returnType}}{{{.}}}, {{/returnType}}*_nethttp.Response, error) {
77+
func (r {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request) Execute() ({{#returnType}}{{^isArray}}{{^returnTypeIsPrimitive}}*{{/returnTypeIsPrimitive}}{{/isArray}}{{{.}}}, {{/returnType}}*http.Response, error) {
7578
return r.ApiService.{{nickname}}Execute(r)
7679
}
7780

@@ -82,15 +85,15 @@ func (r {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Reques
8285
{{{unescapedNotes}}}
8386
{{/notes}}
8487

85-
@param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().{{#pathParams}}
88+
@param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().{{#pathParams}}
8689
@param {{paramName}}{{#description}} {{{.}}}{{/description}}{{/pathParams}}
8790
@return {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request
8891
{{#isDeprecated}}
8992

9093
Deprecated
9194
{{/isDeprecated}}
9295
*/
93-
func (a *{{{classname}}}Service) {{{nickname}}}(ctx _context.Context{{#pathParams}}, {{paramName}} {{{dataType}}}{{/pathParams}}) {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request {
96+
func (a *{{{classname}}}Service) {{{nickname}}}(ctx context.Context{{#pathParams}}, {{paramName}} {{{dataType}}}{{/pathParams}}) {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request {
9497
return {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request{
9598
ApiService: a,
9699
ctx: ctx,
@@ -105,27 +108,27 @@ func (a *{{{classname}}}Service) {{{nickname}}}(ctx _context.Context{{#pathParam
105108
{{#isDeprecated}}
106109
// Deprecated
107110
{{/isDeprecated}}
108-
func (a *{{{classname}}}Service) {{nickname}}Execute(r {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request) ({{#returnType}}{{{.}}}, {{/returnType}}*_nethttp.Response, error) {
111+
func (a *{{{classname}}}Service) {{nickname}}Execute(r {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request) ({{#returnType}}{{^isArray}}{{^returnTypeIsPrimitive}}*{{/returnTypeIsPrimitive}}{{/isArray}}{{{.}}}, {{/returnType}}*http.Response, error) {
109112
var (
110-
localVarHTTPMethod = _nethttp.Method{{httpMethod}}
113+
localVarHTTPMethod = http.Method{{httpMethod}}
111114
localVarPostBody interface{}
112115
formFiles []formFile
113116
{{#returnType}}
114-
localVarReturnValue {{{.}}}
117+
localVarReturnValue {{^isArray}}{{^returnTypeIsPrimitive}}*{{/returnTypeIsPrimitive}}{{/isArray}}{{{.}}}
115118
{{/returnType}}
116119
)
117120

118121
localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "{{{classname}}}Service.{{{nickname}}}")
119122
if err != nil {
120-
return {{#returnType}}localVarReturnValue, {{/returnType}}nil, GenericOpenAPIError{error: err.Error()}
123+
return {{#returnType}}localVarReturnValue, {{/returnType}}nil, &GenericOpenAPIError{error: err.Error()}
121124
}
122125

123126
localVarPath := localBasePath + "{{{path}}}"{{#pathParams}}
124-
localVarPath = strings.Replace(localVarPath, "{"+"{{baseName}}"+"}", _neturl.PathEscape(parameterToString(r.{{paramName}}, "{{collectionFormat}}")), -1){{/pathParams}}
127+
localVarPath = strings.Replace(localVarPath, "{"+"{{baseName}}"+"}", url.PathEscape(parameterToString(r.{{paramName}}, "{{collectionFormat}}")), -1){{/pathParams}}
125128

126129
localVarHeaderParams := make(map[string]string)
127-
localVarQueryParams := _neturl.Values{}
128-
localVarFormParams := _neturl.Values{}
130+
localVarQueryParams := url.Values{}
131+
localVarFormParams := url.Values{}
129132
{{#allParams}}
130133
{{#required}}
131134
{{^isPathParam}}
@@ -265,7 +268,7 @@ func (a *{{{classname}}}Service) {{nickname}}Execute(r {{#structPrefix}}{{&class
265268
}
266269
{{/required}}
267270
if {{paramName}}LocalVarFile != nil {
268-
fbs, _ := _ioutil.ReadAll({{paramName}}LocalVarFile)
271+
fbs, _ := ioutil.ReadAll({{paramName}}LocalVarFile)
269272
{{paramName}}LocalVarFileBytes = fbs
270273
{{paramName}}LocalVarFileName = {{paramName}}LocalVarFile.Name()
271274
{{paramName}}LocalVarFile.Close()
@@ -344,15 +347,15 @@ func (a *{{{classname}}}Service) {{nickname}}Execute(r {{#structPrefix}}{{&class
344347
return {{#returnType}}localVarReturnValue, {{/returnType}}localVarHTTPResponse, err
345348
}
346349

347-
localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body)
350+
localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body)
348351
localVarHTTPResponse.Body.Close()
349-
localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody))
352+
localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody))
350353
if err != nil {
351354
return {{#returnType}}localVarReturnValue, {{/returnType}}localVarHTTPResponse, err
352355
}
353356

354357
if localVarHTTPResponse.StatusCode >= 300 {
355-
newErr := GenericOpenAPIError{
358+
newErr := &GenericOpenAPIError{
356359
body: localVarBody,
357360
error: localVarHTTPResponse.Status,
358361
}
@@ -399,7 +402,7 @@ func (a *{{{classname}}}Service) {{nickname}}Execute(r {{#structPrefix}}{{&class
399402
{{#returnType}}
400403
err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
401404
if err != nil {
402-
newErr := GenericOpenAPIError{
405+
newErr := &GenericOpenAPIError{
403406
body: localVarBody,
404407
error: err.Error(),
405408
}

modules/openapi-generator/src/main/resources/go/api_doc.mustache

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ func main() {
4141
{{/allParams}}
4242

4343
configuration := {{goImportAlias}}.NewConfiguration()
44-
api_client := {{goImportAlias}}.NewAPIClient(configuration)
45-
resp, r, err := api_client.{{classname}}.{{operationId}}(context.Background(){{#pathParams}}, {{paramName}}{{/pathParams}}){{#allParams}}{{^isPathParam}}.{{vendorExtensions.x-export-param-name}}({{paramName}}){{/isPathParam}}{{/allParams}}.Execute()
44+
apiClient := {{goImportAlias}}.NewAPIClient(configuration)
45+
resp, r, err := apiClient.{{classname}}.{{operationId}}(context.Background(){{#pathParams}}, {{paramName}}{{/pathParams}}){{#allParams}}{{^isPathParam}}.{{vendorExtensions.x-export-param-name}}({{paramName}}){{/isPathParam}}{{/allParams}}.Execute()
4646
if err != nil {
4747
fmt.Fprintf(os.Stderr, "Error when calling `{{classname}}.{{operationId}}``: %v\n", err)
4848
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)

modules/openapi-generator/src/main/resources/go/client.mustache

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,13 @@ func reportError(format string, a ...interface{}) error {
477477
return fmt.Errorf(format, a...)
478478
}
479479

480+
// A wrapper for strict JSON decoding
481+
func newStrictDecoder(data []byte) *json.Decoder {
482+
dec := json.NewDecoder(bytes.NewBuffer(data))
483+
dec.DisallowUnknownFields()
484+
return dec
485+
}
486+
480487
// Set request body from an interface{}
481488
func setBody(body interface{}, contentType string) (bodyBuf *bytes.Buffer, err error) {
482489
if bodyBuf == nil {

modules/openapi-generator/src/main/resources/go/go.mod.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module {{gitHost}}/{{gitUserId}}/{{gitRepoId}}{{#isGoSubmodule}}/{{packageName}}
33
go 1.13
44

55
require (
6-
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99
6+
golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558
77
{{#withAWSV4Signature}}
88
github.com/aws/aws-sdk-go v1.34.14
99
{{/withAWSV4Signature}}

modules/openapi-generator/src/main/resources/go/model_oneof.mustache

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
// {{classname}} - {{{description}}}{{^description}}struct for {{{classname}}}{{/description}}
22
type {{classname}} struct {
33
{{#oneOf}}
4-
{{{.}}} *{{{.}}}
4+
{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}} *{{{.}}}
55
{{/oneOf}}
66
}
77

88
{{#oneOf}}
99
// {{{.}}}As{{classname}} is a convenience function that returns {{{.}}} wrapped in {{classname}}
10-
func {{{.}}}As{{classname}}(v *{{{.}}}) {{classname}} {
11-
return {{classname}}{ {{{.}}}: v}
10+
func {{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}}As{{classname}}(v *{{{.}}}) {{classname}} {
11+
return {{classname}}{
12+
{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}}: v,
13+
}
1214
}
1315

1416
{{/oneOf}}
@@ -29,7 +31,7 @@ func (dst *{{classname}}) UnmarshalJSON(data []byte) error {
2931
{{#-first}}
3032
// use discriminator value to speed up the lookup
3133
var jsonDict map[string]interface{}
32-
err = json.Unmarshal(data, &jsonDict)
34+
err = newStrictDecoder(data).Decode(&jsonDict)
3335
if err != nil {
3436
return fmt.Errorf("Failed to unmarshal JSON into map for the discriminator lookup.")
3537
}
@@ -84,24 +86,24 @@ func (dst *{{classname}}) UnmarshalJSON(data []byte) error {
8486
{{^useOneOfDiscriminatorLookup}}
8587
match := 0
8688
{{#oneOf}}
87-
// try to unmarshal data into {{{.}}}
88-
err = json.Unmarshal(data, &dst.{{{.}}})
89+
// try to unmarshal data into {{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}}
90+
err = newStrictDecoder(data).Decode(&dst.{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}})
8991
if err == nil {
90-
json{{{.}}}, _ := json.Marshal(dst.{{{.}}})
91-
if string(json{{{.}}}) == "{}" { // empty struct
92-
dst.{{{.}}} = nil
92+
json{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}}, _ := json.Marshal(dst.{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}})
93+
if string(json{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}}) == "{}" { // empty struct
94+
dst.{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}} = nil
9395
} else {
9496
match++
9597
}
9698
} else {
97-
dst.{{{.}}} = nil
99+
dst.{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}} = nil
98100
}
99101

100102
{{/oneOf}}
101103
if match > 1 { // more than 1 match
102104
// reset to nil
103105
{{#oneOf}}
104-
dst.{{{.}}} = nil
106+
dst.{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}} = nil
105107
{{/oneOf}}
106108

107109
return fmt.Errorf("Data matches more than one schema in oneOf({{classname}})")
@@ -116,8 +118,8 @@ func (dst *{{classname}}) UnmarshalJSON(data []byte) error {
116118
// Marshal data from the first non-nil pointers in the struct to JSON
117119
func (src {{classname}}) MarshalJSON() ([]byte, error) {
118120
{{#oneOf}}
119-
if src.{{{.}}} != nil {
120-
return json.Marshal(&src.{{{.}}})
121+
if src.{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}} != nil {
122+
return json.Marshal(&src.{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}})
121123
}
122124

123125
{{/oneOf}}
@@ -126,9 +128,12 @@ func (src {{classname}}) MarshalJSON() ([]byte, error) {
126128

127129
// Get the actual instance
128130
func (obj *{{classname}}) GetActualInstance() (interface{}) {
131+
if obj == nil {
132+
return nil
133+
}
129134
{{#oneOf}}
130-
if obj.{{{.}}} != nil {
131-
return obj.{{{.}}}
135+
if obj.{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}} != nil {
136+
return obj.{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}}
132137
}
133138

134139
{{/oneOf}}

0 commit comments

Comments
 (0)