Allow to specify response headers (needed for redirecting clients) (#9170)

* Allow to specify response headers (needed for redirecting clients) (#8148)

Co-authored-by: Bernardo Pastorelli <13519917+randomswdev@users.noreply.github.com>

* add addResponseHeaders option

* enable addResponseHeaders

* fix comma

Co-authored-by: randomswdev <randomswdev@users.noreply.github.com>
Co-authored-by: Bernardo Pastorelli <13519917+randomswdev@users.noreply.github.com>
This commit is contained in:
William Cheng 2021-04-05 16:27:41 +08:00 committed by GitHub
parent 226a8b5f77
commit c79d056935
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 113 additions and 48 deletions

View File

@ -5,3 +5,4 @@ templateDir: modules/openapi-generator/src/main/resources/go-server
additionalProperties: additionalProperties:
hideGenerationTimestamp: "true" hideGenerationTimestamp: "true"
packageName: petstoreserver packageName: petstoreserver
addResponseHeaders: true

View File

@ -7,6 +7,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| Option | Description | Values | Default | | Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- | | ------ | ----------- | ------ | ------- |
|addResponseHeaders|To include response headers in ImplResponse| |false|
|enumClassPrefix|Prefix enum with class name| |false| |enumClassPrefix|Prefix enum with class name| |false|
|featureCORS|Enable Cross-Origin Resource Sharing middleware| |false| |featureCORS|Enable Cross-Origin Resource Sharing middleware| |false|
|hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |true| |hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |true|

View File

@ -37,6 +37,7 @@ public class GoServerCodegen extends AbstractGoCodegen {
protected String projectName = "openapi-server"; protected String projectName = "openapi-server";
protected String sourceFolder = "go"; protected String sourceFolder = "go";
protected Boolean corsFeatureEnabled = false; protected Boolean corsFeatureEnabled = false;
protected Boolean addResponseHeaders = false;
public GoServerCodegen() { public GoServerCodegen() {
@ -80,6 +81,12 @@ public class GoServerCodegen extends AbstractGoCodegen {
cliOptions.add(CliOption.newBoolean(CodegenConstants.ENUM_CLASS_PREFIX, CodegenConstants.ENUM_CLASS_PREFIX_DESC)); cliOptions.add(CliOption.newBoolean(CodegenConstants.ENUM_CLASS_PREFIX, CodegenConstants.ENUM_CLASS_PREFIX_DESC));
// option to include headers in the response
CliOption optAddResponseHeaders = new CliOption("addResponseHeaders", "To include response headers in ImplResponse");
optAddResponseHeaders.setType("bool");
optAddResponseHeaders.defaultValue(addResponseHeaders.toString());
cliOptions.add(optAddResponseHeaders);
/* /*
* Models. You can write model files using the modelTemplateFiles map. * Models. You can write model files using the modelTemplateFiles map.
* if you want to create one template for file, you can do so here. * if you want to create one template for file, you can do so here.
@ -172,12 +179,19 @@ public class GoServerCodegen extends AbstractGoCodegen {
} else { } else {
additionalProperties.put("serverPort", serverPort); additionalProperties.put("serverPort", serverPort);
} }
if (additionalProperties.containsKey("featureCORS")) { if (additionalProperties.containsKey("featureCORS")) {
this.setFeatureCORS(convertPropertyToBooleanAndWriteBack("featureCORS")); this.setFeatureCORS(convertPropertyToBooleanAndWriteBack("featureCORS"));
} else { } else {
additionalProperties.put("featureCORS", corsFeatureEnabled); additionalProperties.put("featureCORS", corsFeatureEnabled);
} }
if (additionalProperties.containsKey("addResponseHeaders")) {
this.setAddResponseHeaders(convertPropertyToBooleanAndWriteBack("addResponseHeaders"));
} else {
additionalProperties.put("addResponseHeaders", addResponseHeaders);
}
if (additionalProperties.containsKey(CodegenConstants.ENUM_CLASS_PREFIX)) { if (additionalProperties.containsKey(CodegenConstants.ENUM_CLASS_PREFIX)) {
setEnumClassPrefix(Boolean.parseBoolean(additionalProperties.get(CodegenConstants.ENUM_CLASS_PREFIX).toString())); setEnumClassPrefix(Boolean.parseBoolean(additionalProperties.get(CodegenConstants.ENUM_CLASS_PREFIX).toString()));
if (enumClassPrefix) { if (enumClassPrefix) {
@ -314,4 +328,8 @@ public class GoServerCodegen extends AbstractGoCodegen {
public void setFeatureCORS(Boolean featureCORS) { public void setFeatureCORS(Boolean featureCORS) {
this.corsFeatureEnabled = featureCORS; this.corsFeatureEnabled = featureCORS;
} }
public void setAddResponseHeaders(Boolean addResponseHeaders) {
this.addResponseHeaders = addResponseHeaders;
}
} }

View File

@ -95,10 +95,10 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re
result, err := c.service.{{nickname}}(r.Context(){{#allParams}}, {{#isBodyParam}}*{{/isBodyParam}}{{paramName}}{{/allParams}}) result, err := c.service.{{nickname}}(r.Context(){{#allParams}}, {{#isBodyParam}}*{{/isBodyParam}}{{paramName}}{{/allParams}})
//If an error occured, encode the error with the status code //If an error occured, encode the error with the status code
if err != nil { if err != nil {
EncodeJSONResponse(err.Error(), &result.Code, w) EncodeJSONResponse(err.Error(), &result.Code,{{#addResponseHeaders}} result.Headers,{{/addResponseHeaders}} w)
return return
} }
//If no error, encode the body and the result code //If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w) EncodeJSONResponse(result.Body, &result.Code,{{#addResponseHeaders}} result.Headers,{{/addResponseHeaders}} w)
}{{/operation}}{{/operations}} }{{/operation}}{{/operations}}

View File

@ -3,6 +3,22 @@ package {{packageName}}
//Response return a ImplResponse struct filled //Response return a ImplResponse struct filled
func Response(code int, body interface{}) ImplResponse { func Response(code int, body interface{}) ImplResponse {
return ImplResponse{Code: code, Body: body} return ImplResponse {
Code: code,
{{#addResponseHeaders}}
Headers: nil,
{{/addResponseHeaders}}
Body: body,
}
} }
{{#addResponseHeaders}}
//ResponseWithHeaders return a ImplResponse struct filled, including headers
func ResponseWithHeaders(code int, headers map[string][]string, body interface{}) ImplResponse {
return ImplResponse {
Code: code,
Headers: headers,
Body: body,
}
}
{{/addResponseHeaders}}

View File

@ -4,5 +4,8 @@ package {{packageName}}
//Implementation response defines an error code with the associated body //Implementation response defines an error code with the associated body
type ImplResponse struct { type ImplResponse struct {
Code int Code int
{{#addResponseHeaders}}
Headers map[string][]string
{{/addResponseHeaders}}
Body interface{} Body interface{}
} }

View File

@ -54,8 +54,21 @@ func NewRouter(routers ...Router) *mux.Router {
} }
// EncodeJSONResponse uses the json encoder to write an interface to the http response with an optional status code // EncodeJSONResponse uses the json encoder to write an interface to the http response with an optional status code
func EncodeJSONResponse(i interface{}, status *int, w http.ResponseWriter) error { func EncodeJSONResponse(i interface{}, status *int,{{#addResponseHeaders}} headers map[string][]string,{{/addResponseHeaders}} w http.ResponseWriter) error {
{{#addResponseHeader}}
wHeader := w.Header()
if headers != nil {
for key, values := range headers {
for _, value := range values {
wHeader.Add(key, value)
}
}
}
wHeader.Set("Content-Type", "application/json; charset=UTF-8")
{{/addResponseHeader}}
{{^addResponseHeader}}
w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.Header().Set("Content-Type", "application/json; charset=UTF-8")
{{/addResponseHeader}}
if status != nil { if status != nil {
w.WriteHeader(*status) w.WriteHeader(*status)
} else { } else {

View File

@ -92,11 +92,11 @@ func (c *PetApiController) AddPet(w http.ResponseWriter, r *http.Request) {
result, err := c.service.AddPet(r.Context(), *pet) result, err := c.service.AddPet(r.Context(), *pet)
//If an error occured, encode the error with the status code //If an error occured, encode the error with the status code
if err != nil { if err != nil {
EncodeJSONResponse(err.Error(), &result.Code, w) EncodeJSONResponse(err.Error(), &result.Code, result.Headers, w)
return return
} }
//If no error, encode the body and the result code //If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w) EncodeJSONResponse(result.Body, &result.Code, result.Headers, w)
} }
@ -112,11 +112,11 @@ func (c *PetApiController) DeletePet(w http.ResponseWriter, r *http.Request) {
result, err := c.service.DeletePet(r.Context(), petId, apiKey) result, err := c.service.DeletePet(r.Context(), petId, apiKey)
//If an error occured, encode the error with the status code //If an error occured, encode the error with the status code
if err != nil { if err != nil {
EncodeJSONResponse(err.Error(), &result.Code, w) EncodeJSONResponse(err.Error(), &result.Code, result.Headers, w)
return return
} }
//If no error, encode the body and the result code //If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w) EncodeJSONResponse(result.Body, &result.Code, result.Headers, w)
} }
@ -127,11 +127,11 @@ func (c *PetApiController) FindPetsByStatus(w http.ResponseWriter, r *http.Reque
result, err := c.service.FindPetsByStatus(r.Context(), status) result, err := c.service.FindPetsByStatus(r.Context(), status)
//If an error occured, encode the error with the status code //If an error occured, encode the error with the status code
if err != nil { if err != nil {
EncodeJSONResponse(err.Error(), &result.Code, w) EncodeJSONResponse(err.Error(), &result.Code, result.Headers, w)
return return
} }
//If no error, encode the body and the result code //If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w) EncodeJSONResponse(result.Body, &result.Code, result.Headers, w)
} }
@ -142,11 +142,11 @@ func (c *PetApiController) FindPetsByTags(w http.ResponseWriter, r *http.Request
result, err := c.service.FindPetsByTags(r.Context(), tags) result, err := c.service.FindPetsByTags(r.Context(), tags)
//If an error occured, encode the error with the status code //If an error occured, encode the error with the status code
if err != nil { if err != nil {
EncodeJSONResponse(err.Error(), &result.Code, w) EncodeJSONResponse(err.Error(), &result.Code, result.Headers, w)
return return
} }
//If no error, encode the body and the result code //If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w) EncodeJSONResponse(result.Body, &result.Code, result.Headers, w)
} }
@ -161,11 +161,11 @@ func (c *PetApiController) GetPetById(w http.ResponseWriter, r *http.Request) {
result, err := c.service.GetPetById(r.Context(), petId) result, err := c.service.GetPetById(r.Context(), petId)
//If an error occured, encode the error with the status code //If an error occured, encode the error with the status code
if err != nil { if err != nil {
EncodeJSONResponse(err.Error(), &result.Code, w) EncodeJSONResponse(err.Error(), &result.Code, result.Headers, w)
return return
} }
//If no error, encode the body and the result code //If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w) EncodeJSONResponse(result.Body, &result.Code, result.Headers, w)
} }
@ -180,11 +180,11 @@ func (c *PetApiController) UpdatePet(w http.ResponseWriter, r *http.Request) {
result, err := c.service.UpdatePet(r.Context(), *pet) result, err := c.service.UpdatePet(r.Context(), *pet)
//If an error occured, encode the error with the status code //If an error occured, encode the error with the status code
if err != nil { if err != nil {
EncodeJSONResponse(err.Error(), &result.Code, w) EncodeJSONResponse(err.Error(), &result.Code, result.Headers, w)
return return
} }
//If no error, encode the body and the result code //If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w) EncodeJSONResponse(result.Body, &result.Code, result.Headers, w)
} }
@ -207,11 +207,11 @@ func (c *PetApiController) UpdatePetWithForm(w http.ResponseWriter, r *http.Requ
result, err := c.service.UpdatePetWithForm(r.Context(), petId, name, status) result, err := c.service.UpdatePetWithForm(r.Context(), petId, name, status)
//If an error occured, encode the error with the status code //If an error occured, encode the error with the status code
if err != nil { if err != nil {
EncodeJSONResponse(err.Error(), &result.Code, w) EncodeJSONResponse(err.Error(), &result.Code, result.Headers, w)
return return
} }
//If no error, encode the body and the result code //If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w) EncodeJSONResponse(result.Body, &result.Code, result.Headers, w)
} }
@ -239,10 +239,10 @@ func (c *PetApiController) UploadFile(w http.ResponseWriter, r *http.Request) {
result, err := c.service.UploadFile(r.Context(), petId, additionalMetadata, file) result, err := c.service.UploadFile(r.Context(), petId, additionalMetadata, file)
//If an error occured, encode the error with the status code //If an error occured, encode the error with the status code
if err != nil { if err != nil {
EncodeJSONResponse(err.Error(), &result.Code, w) EncodeJSONResponse(err.Error(), &result.Code, result.Headers, w)
return return
} }
//If no error, encode the body and the result code //If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w) EncodeJSONResponse(result.Body, &result.Code, result.Headers, w)
} }

View File

@ -64,11 +64,11 @@ func (c *StoreApiController) DeleteOrder(w http.ResponseWriter, r *http.Request)
result, err := c.service.DeleteOrder(r.Context(), orderId) result, err := c.service.DeleteOrder(r.Context(), orderId)
//If an error occured, encode the error with the status code //If an error occured, encode the error with the status code
if err != nil { if err != nil {
EncodeJSONResponse(err.Error(), &result.Code, w) EncodeJSONResponse(err.Error(), &result.Code, result.Headers, w)
return return
} }
//If no error, encode the body and the result code //If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w) EncodeJSONResponse(result.Body, &result.Code, result.Headers, w)
} }
@ -77,11 +77,11 @@ func (c *StoreApiController) GetInventory(w http.ResponseWriter, r *http.Request
result, err := c.service.GetInventory(r.Context()) result, err := c.service.GetInventory(r.Context())
//If an error occured, encode the error with the status code //If an error occured, encode the error with the status code
if err != nil { if err != nil {
EncodeJSONResponse(err.Error(), &result.Code, w) EncodeJSONResponse(err.Error(), &result.Code, result.Headers, w)
return return
} }
//If no error, encode the body and the result code //If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w) EncodeJSONResponse(result.Body, &result.Code, result.Headers, w)
} }
@ -96,11 +96,11 @@ func (c *StoreApiController) GetOrderById(w http.ResponseWriter, r *http.Request
result, err := c.service.GetOrderById(r.Context(), orderId) result, err := c.service.GetOrderById(r.Context(), orderId)
//If an error occured, encode the error with the status code //If an error occured, encode the error with the status code
if err != nil { if err != nil {
EncodeJSONResponse(err.Error(), &result.Code, w) EncodeJSONResponse(err.Error(), &result.Code, result.Headers, w)
return return
} }
//If no error, encode the body and the result code //If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w) EncodeJSONResponse(result.Body, &result.Code, result.Headers, w)
} }
@ -115,10 +115,10 @@ func (c *StoreApiController) PlaceOrder(w http.ResponseWriter, r *http.Request)
result, err := c.service.PlaceOrder(r.Context(), *order) result, err := c.service.PlaceOrder(r.Context(), *order)
//If an error occured, encode the error with the status code //If an error occured, encode the error with the status code
if err != nil { if err != nil {
EncodeJSONResponse(err.Error(), &result.Code, w) EncodeJSONResponse(err.Error(), &result.Code, result.Headers, w)
return return
} }
//If no error, encode the body and the result code //If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w) EncodeJSONResponse(result.Body, &result.Code, result.Headers, w)
} }

View File

@ -92,11 +92,11 @@ func (c *UserApiController) CreateUser(w http.ResponseWriter, r *http.Request) {
result, err := c.service.CreateUser(r.Context(), *user) result, err := c.service.CreateUser(r.Context(), *user)
//If an error occured, encode the error with the status code //If an error occured, encode the error with the status code
if err != nil { if err != nil {
EncodeJSONResponse(err.Error(), &result.Code, w) EncodeJSONResponse(err.Error(), &result.Code, result.Headers, w)
return return
} }
//If no error, encode the body and the result code //If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w) EncodeJSONResponse(result.Body, &result.Code, result.Headers, w)
} }
@ -111,11 +111,11 @@ func (c *UserApiController) CreateUsersWithArrayInput(w http.ResponseWriter, r *
result, err := c.service.CreateUsersWithArrayInput(r.Context(), *user) result, err := c.service.CreateUsersWithArrayInput(r.Context(), *user)
//If an error occured, encode the error with the status code //If an error occured, encode the error with the status code
if err != nil { if err != nil {
EncodeJSONResponse(err.Error(), &result.Code, w) EncodeJSONResponse(err.Error(), &result.Code, result.Headers, w)
return return
} }
//If no error, encode the body and the result code //If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w) EncodeJSONResponse(result.Body, &result.Code, result.Headers, w)
} }
@ -130,11 +130,11 @@ func (c *UserApiController) CreateUsersWithListInput(w http.ResponseWriter, r *h
result, err := c.service.CreateUsersWithListInput(r.Context(), *user) result, err := c.service.CreateUsersWithListInput(r.Context(), *user)
//If an error occured, encode the error with the status code //If an error occured, encode the error with the status code
if err != nil { if err != nil {
EncodeJSONResponse(err.Error(), &result.Code, w) EncodeJSONResponse(err.Error(), &result.Code, result.Headers, w)
return return
} }
//If no error, encode the body and the result code //If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w) EncodeJSONResponse(result.Body, &result.Code, result.Headers, w)
} }
@ -145,11 +145,11 @@ func (c *UserApiController) DeleteUser(w http.ResponseWriter, r *http.Request) {
result, err := c.service.DeleteUser(r.Context(), username) result, err := c.service.DeleteUser(r.Context(), username)
//If an error occured, encode the error with the status code //If an error occured, encode the error with the status code
if err != nil { if err != nil {
EncodeJSONResponse(err.Error(), &result.Code, w) EncodeJSONResponse(err.Error(), &result.Code, result.Headers, w)
return return
} }
//If no error, encode the body and the result code //If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w) EncodeJSONResponse(result.Body, &result.Code, result.Headers, w)
} }
@ -160,11 +160,11 @@ func (c *UserApiController) GetUserByName(w http.ResponseWriter, r *http.Request
result, err := c.service.GetUserByName(r.Context(), username) result, err := c.service.GetUserByName(r.Context(), username)
//If an error occured, encode the error with the status code //If an error occured, encode the error with the status code
if err != nil { if err != nil {
EncodeJSONResponse(err.Error(), &result.Code, w) EncodeJSONResponse(err.Error(), &result.Code, result.Headers, w)
return return
} }
//If no error, encode the body and the result code //If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w) EncodeJSONResponse(result.Body, &result.Code, result.Headers, w)
} }
@ -176,11 +176,11 @@ func (c *UserApiController) LoginUser(w http.ResponseWriter, r *http.Request) {
result, err := c.service.LoginUser(r.Context(), username, password) result, err := c.service.LoginUser(r.Context(), username, password)
//If an error occured, encode the error with the status code //If an error occured, encode the error with the status code
if err != nil { if err != nil {
EncodeJSONResponse(err.Error(), &result.Code, w) EncodeJSONResponse(err.Error(), &result.Code, result.Headers, w)
return return
} }
//If no error, encode the body and the result code //If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w) EncodeJSONResponse(result.Body, &result.Code, result.Headers, w)
} }
@ -189,11 +189,11 @@ func (c *UserApiController) LogoutUser(w http.ResponseWriter, r *http.Request) {
result, err := c.service.LogoutUser(r.Context()) result, err := c.service.LogoutUser(r.Context())
//If an error occured, encode the error with the status code //If an error occured, encode the error with the status code
if err != nil { if err != nil {
EncodeJSONResponse(err.Error(), &result.Code, w) EncodeJSONResponse(err.Error(), &result.Code, result.Headers, w)
return return
} }
//If no error, encode the body and the result code //If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w) EncodeJSONResponse(result.Body, &result.Code, result.Headers, w)
} }
@ -210,10 +210,10 @@ func (c *UserApiController) UpdateUser(w http.ResponseWriter, r *http.Request) {
result, err := c.service.UpdateUser(r.Context(), username, *user) result, err := c.service.UpdateUser(r.Context(), username, *user)
//If an error occured, encode the error with the status code //If an error occured, encode the error with the status code
if err != nil { if err != nil {
EncodeJSONResponse(err.Error(), &result.Code, w) EncodeJSONResponse(err.Error(), &result.Code, result.Headers, w)
return return
} }
//If no error, encode the body and the result code //If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w) EncodeJSONResponse(result.Body, &result.Code, result.Headers, w)
} }

View File

@ -11,6 +11,18 @@ package petstoreserver
//Response return a ImplResponse struct filled //Response return a ImplResponse struct filled
func Response(code int, body interface{}) ImplResponse { func Response(code int, body interface{}) ImplResponse {
return ImplResponse{Code: code, Body: body} return ImplResponse {
Code: code,
Headers: nil,
Body: body,
}
} }
//ResponseWithHeaders return a ImplResponse struct filled, including headers
func ResponseWithHeaders(code int, headers map[string][]string, body interface{}) ImplResponse {
return ImplResponse {
Code: code,
Headers: headers,
Body: body,
}
}

View File

@ -12,5 +12,6 @@ package petstoreserver
//Implementation response defines an error code with the associated body //Implementation response defines an error code with the associated body
type ImplResponse struct { type ImplResponse struct {
Code int Code int
Headers map[string][]string
Body interface{} Body interface{}
} }

View File

@ -56,7 +56,7 @@ func NewRouter(routers ...Router) *mux.Router {
} }
// EncodeJSONResponse uses the json encoder to write an interface to the http response with an optional status code // EncodeJSONResponse uses the json encoder to write an interface to the http response with an optional status code
func EncodeJSONResponse(i interface{}, status *int, w http.ResponseWriter) error { func EncodeJSONResponse(i interface{}, status *int, headers map[string][]string, w http.ResponseWriter) error {
w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.Header().Set("Content-Type", "application/json; charset=UTF-8")
if status != nil { if status != nil {
w.WriteHeader(*status) w.WriteHeader(*status)