oapi-codegen icon indicating copy to clipboard operation
oapi-codegen copied to clipboard

Inconsistent response struct generation with refs

Open HeroSizy opened this issue 6 months ago • 0 comments

Version

v2.1.0

Issue

When using same reference in $ref for responses, the first response referencing the scheme will have different behavior. It will embed the referenced struct while other subsequent will just replace the struct.

Example

command used to generate

oapi-codegen -config .oapicodegenconf.yaml openapi.yaml > oapi.gen.go

.oapicodegenconf.yaml

package: specs
generate:
  models: true
  strict-server: true
  chi-server: true
  client: false
  embedded-spec: true
compatibility:
  apply-chi-middleware-first-to-last: true

openapi.yaml

# ...
paths:
  /user:
    get:
      responses:
        # ...
        400:
          $ref: "#/components/responses/ErrorResponse"
        401:
          $ref: "#/components/responses/ErrorResponse"
        403:
          $ref: "#/components/responses/ErrorResponse"
        500:
          $ref: "#/components/responses/ErrorResponse"
        502:
          $ref: "#/components/responses/ErrorResponse"
        504:
          $ref: "#/components/responses/ErrorResponse"

components:
  # ...
  responses:
    ErrorResponse:
      description: Error response
      content:
        application/json:
          schema:
            type: object
            required:
              - message
            properties:
              message:
                type: string
                example: "Invalid Request"
#...

Generated Code

// ...
type ErrorResponseJSONResponse struct {
	Message string `json:"message"`
}
type GetUserRequestObject struct {
}

// ...
type GetUser200JSONResponse User

func (response GetUser200JSONResponse) VisitGetUserResponse(w http.ResponseWriter) error {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(200)

	return json.NewEncoder(w).Encode(response)
}

type GetUser400JSONResponse struct{ ErrorResponseJSONResponse }

func (response GetUser400JSONResponse) VisitGetUserResponse(w http.ResponseWriter) error {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(400)

	return json.NewEncoder(w).Encode(response)
}

type GetUser401JSONResponse struct {
	Message string `json:"message"`
}

func (response GetUser401JSONResponse) VisitGetUserResponse(w http.ResponseWriter) error {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(401)

	return json.NewEncoder(w).Encode(response)
}

type GetUser403JSONResponse struct {
	Message string `json:"message"`
}

func (response GetUser403JSONResponse) VisitGetUserResponse(w http.ResponseWriter) error {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(403)

	return json.NewEncoder(w).Encode(response)
}

type GetUser500JSONResponse struct {
	Message string `json:"message"`
}

func (response GetUser500JSONResponse) VisitGetUserResponse(w http.ResponseWriter) error {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(500)

	return json.NewEncoder(w).Encode(response)
}

type GetUser502JSONResponse struct {
	Message string `json:"message"`
}

func (response GetUser502JSONResponse) VisitGetUserResponse(w http.ResponseWriter) error {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(502)

	return json.NewEncoder(w).Encode(response)
}

type GetUser504JSONResponse struct {
	Message string `json:"message"`
}

func (response GetUser504JSONResponse) VisitGetUserResponse(w http.ResponseWriter) error {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(504)

	return json.NewEncoder(w).Encode(response)
}
// ...

Also Wondering if there is any option that can combine all the error response to a single struct in case they should share the same fields.

HeroSizy avatar Feb 15 '24 04:02 HeroSizy