diff --git a/modules/openapi-generator/src/main/resources/go/api.mustache b/modules/openapi-generator/src/main/resources/go/api.mustache index c2c977178bb..44fbbcf4f95 100644 --- a/modules/openapi-generator/src/main/resources/go/api.mustache +++ b/modules/openapi-generator/src/main/resources/go/api.mustache @@ -385,7 +385,8 @@ func (a *{{{classname}}}Service) {{nickname}}Execute(r {{#structPrefix}}{{&class newErr.error = err.Error() return {{#returnType}}localVarReturnValue, {{/returnType}}localVarHTTPResponse, newErr } - newErr.model = v + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v {{^-last}} return {{#returnType}}localVarReturnValue, {{/returnType}}localVarHTTPResponse, newErr {{/-last}} diff --git a/modules/openapi-generator/src/main/resources/go/client.mustache b/modules/openapi-generator/src/main/resources/go/client.mustache index 7b0fcefca66..d5e45dfb03c 100644 --- a/modules/openapi-generator/src/main/resources/go/client.mustache +++ b/modules/openapi-generator/src/main/resources/go/client.mustache @@ -616,3 +616,23 @@ func (e GenericOpenAPIError) Body() []byte { func (e GenericOpenAPIError) Model() interface{} { return e.model } + +// format error message using title and detail when model implements rfc7807 +func formatErrorMessage(status string, v interface{}) string { + + str := "" + metaValue := reflect.ValueOf(v).Elem() + + field := metaValue.FieldByName("Title") + if field != (reflect.Value{}) { + str = fmt.Sprintf("%s", field.Interface()) + } + + field = metaValue.FieldByName("Detail") + if field != (reflect.Value{}) { + str = fmt.Sprintf("%s (%s)", str, field.Interface()) + } + + // status title (detail) + return fmt.Sprintf("%s %s", status, str) +} diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/go/GoClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/go/GoClientCodegenTest.java index 894a105fb45..b55967fdaf9 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/go/GoClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/go/GoClientCodegenTest.java @@ -222,4 +222,22 @@ public class GoClientCodegenTest { "func Test_openapi_PetApiService(t *testing.T) {"); } + @Test + public void verifyFormatErrorMessageInUse() throws IOException { + File output = Files.createTempDirectory("test").toFile(); + output.deleteOnExit(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("go") + .setInputSpec("src/test/resources/3_0/go/petstore-with-problem-details.yaml") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + + DefaultGenerator generator = new DefaultGenerator(); + List files = generator.opts(configurator.toClientOptInput()).generate(); + files.forEach(File::deleteOnExit); + + TestUtils.assertFileExists(Paths.get(output + "/api_pet.go")); + TestUtils.assertFileContains(Paths.get(output + "/api_pet.go"), + "newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v)"); + } } diff --git a/modules/openapi-generator/src/test/resources/3_0/go/petstore-with-problem-details.yaml b/modules/openapi-generator/src/test/resources/3_0/go/petstore-with-problem-details.yaml new file mode 100644 index 00000000000..c4385355570 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/go/petstore-with-problem-details.yaml @@ -0,0 +1,61 @@ +openapi: 3.0.0 +info: + description: >- + This spec is mainly for testing Petstore server and contains fake endpoints, + models. Please do not use this for any other purpose. Special characters: " + \ + version: 1.0.0 + title: OpenAPI Petstore + license: + name: Apache-2.0 + url: 'https://www.apache.org/licenses/LICENSE-2.0.html' +tags: + - name: pet + description: Everything about your Pets +paths: + /foo: + get: + tags: + - pet + responses: + "200": + description: response + content: + application/json: + schema: + $ref: '#/components/schemas/Foo' + "404": + description: not found + content: + application/json: + schema: + $ref: '#/components/schemas/RestServiceError' + "422": + description: validation error + content: + application/json: + schema: + $ref: '#/components/schemas/RestServiceError' +components: + schemas: + Foo: + type: string + default: foo + # RFC7807 Problem Detail + RestServiceError: + properties: + type: + description: " A URI reference that identifies the problem type" + type: string + title: + description: "A short, human-readable summary of the problem type." + type: string + status: + description: "The HTTP Status Code" + type: integer + detail: + description: "A human-readable explanation specific to this occurrence of the problem." + type: string + instance: + description: "A unique URI that identifies the specific occurrence of the problem." + type: string diff --git a/samples/client/petstore/go/go-petstore/client.go b/samples/client/petstore/go/go-petstore/client.go index 233c9ae5f6a..b48d903b06a 100644 --- a/samples/client/petstore/go/go-petstore/client.go +++ b/samples/client/petstore/go/go-petstore/client.go @@ -576,3 +576,23 @@ func (e GenericOpenAPIError) Body() []byte { func (e GenericOpenAPIError) Model() interface{} { return e.model } + +// format error message using title and detail when model implements rfc7807 +func formatErrorMessage(status string, v interface{}) string { + + str := "" + metaValue := reflect.ValueOf(v).Elem() + + field := metaValue.FieldByName("Title") + if field != (reflect.Value{}) { + str = fmt.Sprintf("%s", field.Interface()) + } + + field = metaValue.FieldByName("Detail") + if field != (reflect.Value{}) { + str = fmt.Sprintf("%s (%s)", str, field.Interface()) + } + + // status title (detail) + return fmt.Sprintf("%s %s", status, str) +} diff --git a/samples/openapi3/client/extensions/x-auth-id-alias/go-experimental/client.go b/samples/openapi3/client/extensions/x-auth-id-alias/go-experimental/client.go index d9197c7bdb2..7501f465647 100644 --- a/samples/openapi3/client/extensions/x-auth-id-alias/go-experimental/client.go +++ b/samples/openapi3/client/extensions/x-auth-id-alias/go-experimental/client.go @@ -561,3 +561,23 @@ func (e GenericOpenAPIError) Body() []byte { func (e GenericOpenAPIError) Model() interface{} { return e.model } + +// format error message using title and detail when model implements rfc7807 +func formatErrorMessage(status string, v interface{}) string { + + str := "" + metaValue := reflect.ValueOf(v).Elem() + + field := metaValue.FieldByName("Title") + if field != (reflect.Value{}) { + str = fmt.Sprintf("%s", field.Interface()) + } + + field = metaValue.FieldByName("Detail") + if field != (reflect.Value{}) { + str = fmt.Sprintf("%s (%s)", str, field.Interface()) + } + + // status title (detail) + return fmt.Sprintf("%s %s", status, str) +} diff --git a/samples/openapi3/client/petstore/go/go-petstore/api_default.go b/samples/openapi3/client/petstore/go/go-petstore/api_default.go index a025e553800..0a54d9522fa 100644 --- a/samples/openapi3/client/petstore/go/go-petstore/api_default.go +++ b/samples/openapi3/client/petstore/go/go-petstore/api_default.go @@ -126,7 +126,8 @@ func (a *DefaultApiService) FooGetExecute(r ApiFooGetRequest) (*FooGetDefaultRes newErr.error = err.Error() return localVarReturnValue, localVarHTTPResponse, newErr } - newErr.model = v + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v return localVarReturnValue, localVarHTTPResponse, newErr } if localVarHTTPResponse.StatusCode >= 400 && localVarHTTPResponse.StatusCode < 500 { @@ -136,7 +137,8 @@ func (a *DefaultApiService) FooGetExecute(r ApiFooGetRequest) (*FooGetDefaultRes newErr.error = err.Error() return localVarReturnValue, localVarHTTPResponse, newErr } - newErr.model = v + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v return localVarReturnValue, localVarHTTPResponse, newErr } var v FooGetDefaultResponse @@ -145,7 +147,8 @@ func (a *DefaultApiService) FooGetExecute(r ApiFooGetRequest) (*FooGetDefaultRes newErr.error = err.Error() return localVarReturnValue, localVarHTTPResponse, newErr } - newErr.model = v + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v return localVarReturnValue, localVarHTTPResponse, newErr } diff --git a/samples/openapi3/client/petstore/go/go-petstore/api_fake.go b/samples/openapi3/client/petstore/go/go-petstore/api_fake.go index 516497d5996..4594645964c 100644 --- a/samples/openapi3/client/petstore/go/go-petstore/api_fake.go +++ b/samples/openapi3/client/petstore/go/go-petstore/api_fake.go @@ -1666,7 +1666,8 @@ func (a *FakeApiService) TestGroupParametersExecute(r ApiTestGroupParametersRequ newErr.error = err.Error() return localVarHTTPResponse, newErr } - newErr.model = v + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v } return localVarHTTPResponse, newErr } diff --git a/samples/openapi3/client/petstore/go/go-petstore/client.go b/samples/openapi3/client/petstore/go/go-petstore/client.go index 271e9df22d0..a573bd4fa89 100644 --- a/samples/openapi3/client/petstore/go/go-petstore/client.go +++ b/samples/openapi3/client/petstore/go/go-petstore/client.go @@ -589,3 +589,23 @@ func (e GenericOpenAPIError) Body() []byte { func (e GenericOpenAPIError) Model() interface{} { return e.model } + +// format error message using title and detail when model implements rfc7807 +func formatErrorMessage(status string, v interface{}) string { + + str := "" + metaValue := reflect.ValueOf(v).Elem() + + field := metaValue.FieldByName("Title") + if field != (reflect.Value{}) { + str = fmt.Sprintf("%s", field.Interface()) + } + + field = metaValue.FieldByName("Detail") + if field != (reflect.Value{}) { + str = fmt.Sprintf("%s (%s)", str, field.Interface()) + } + + // status title (detail) + return fmt.Sprintf("%s %s", status, str) +}