Repository: deepmap/oapi-codegen
Pull request #701 (2022-07-30 11:52:05)

Strongly typed responses for strict server
Before this, the methods of strict server would return empty interface, like so:
`FindPets(ctx context.Context, request FindPetsRequestObject) interface{}`
With this PR, methods will return an interface unique to each method and an error, like so:
`FindPets(ctx context.Context, request FindPetsRequestObject) (FindPetsResponseObject, error)`

This method-specific interface contains a single method `Visit%METHOD_NAME%Response`, that will marshal the response into `http.ResponseWriter`:
```
type FindPetsResponseObject interface {
	VisitFindPetsResponse(w http.ResponseWriter) error
}
```

This has several advantages:
- Compile-time type checking of response type. Before, you would only get an error in runtime, if you passed an unsupported response object.
- Complicated response marshalling code moved from sever-specific code into common code, making it less error-prone
- Making it clear for user that he can return errors from strict server methods
- It is now simpler to break the strictness by making your own type that satisfies the interface. Before, you would have to use a middleware to access response writer.

The disadvantages are:
- More code is being generated (additional interfaces and methods)
- Breaking change of interface. Not that big of a deal since there was no official release with strict server. Existing user would have to change their code though.
- Harder to do middleware tricks, like redirects. Before you could return anything, catch it in a middleware and execute your own logic. Now, you would have to make separate structs for each method, or use errors (from my expirience most reusable stuff are errors anyway).

@deepmap-marcinr, can you look at this before you make a public release?

This PR is a result of discussion in #669, which this PR should close.

deefdragon: @deepmap-marcinr any chance we can get a review/merge on this?

I've started implementing it on a fork of some of my more "production" code as a test, and I think its worth adding.

Patch:
diff --git a/README.md b/README.md
index 0e19e73..a9ca0e4 100644
--- a/README.md
+++ b/README.md
@@ -275,17 +275,16 @@ function to bind the form to a struct. All other content types are represented b
 
 To form a response simply return one of the generated structs with corresponding status code and content type. For example,
 to return a status code 200 JSON response for a AddPet use the `AddPet200JSONResponse` struct which will set the correct
-Content-Type header, status code and will marshal the response data. You can also return an `error` interface, that will be
-cause an `Internal Server Error` response. If you return a response that is not supported by this method, you will get an error.
-Unfortunately go does not support union types outside generic code, so we can't type check in compile time.
+Content-Type header, status code and will marshal the response data. You can also return an error, that will
+cause an `Internal Server Error` response.
 
 Short example:
 ```go
 type PetStoreImpl struct {}
-func (*PetStoreImpl) GetPets(ctx context.Context, request GetPetsRequestObject) interface{} {
+func (*PetStoreImpl) GetPets(ctx context.Context, request GetPetsRequestObject) (GetPetsResponseObject, error) {
     var result []Pet
 	// Implement me
-    return GetPets200JSONResponse(result)
+    return GetPets200JSONResponse(result), nil
 }
 ```
 For a complete example see `/examples/petstore-expanded/strict`.
diff --git a/examples/authenticated-api/echo/api/api.gen.go b/examples/authenticated-api/echo/api/api.gen.go
index 64689fd..1433f2d 100644
--- a/examples/authenticated-api/echo/api/api.gen.go
+++ b/examples/authenticated-api/echo/api/api.gen.go
@@ -11,7 +11,6 @@ import (
 	"encoding/json"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net/http"
 	"net/url"
 	"path"
@@ -357,7 +356,7 @@ func (c *ClientWithResponses) AddThingWithResponse(ctx context.Context, body Add
 
 // ParseListThingsResponse parses an HTTP response from a ListThingsWithResponse call
 func ParseListThingsResponse(rsp *http.Response) (*ListThingsResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -383,7 +382,7 @@ func ParseListThingsResponse(rsp *http.Response) (*ListThingsResponse, error) {
 
 // ParseAddThingResponse parses an HTTP response from a AddThingWithResponse call
 func ParseAddThingResponse(rsp *http.Response) (*AddThingResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
diff --git a/examples/petstore-expanded/petstore-client.gen.go b/examples/petstore-expanded/petstore-client.gen.go
index 03435d2..0929a64 100644
--- a/examples/petstore-expanded/petstore-client.gen.go
+++ b/examples/petstore-expanded/petstore-client.gen.go
@@ -9,7 +9,6 @@ import (
 	"encoding/json"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net/http"
 	"net/url"
 	"strings"
@@ -573,7 +572,7 @@ func (c *ClientWithResponses) FindPetByIDWithResponse(ctx context.Context, id in
 
 // ParseFindPetsResponse parses an HTTP response from a FindPetsWithResponse call
 func ParseFindPetsResponse(rsp *http.Response) (*FindPetsResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -606,7 +605,7 @@ func ParseFindPetsResponse(rsp *http.Response) (*FindPetsResponse, error) {
 
 // ParseAddPetResponse parses an HTTP response from a AddPetWithResponse call
 func ParseAddPetResponse(rsp *http.Response) (*AddPetResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -639,7 +638,7 @@ func ParseAddPetResponse(rsp *http.Response) (*AddPetResponse, error) {
 
 // ParseDeletePetResponse parses an HTTP response from a DeletePetWithResponse call
 func ParseDeletePetResponse(rsp *http.Response) (*DeletePetResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -665,7 +664,7 @@ func ParseDeletePetResponse(rsp *http.Response) (*DeletePetResponse, error) {
 
 // ParseFindPetByIDResponse parses an HTTP response from a FindPetByIDWithResponse call
 func ParseFindPetByIDResponse(rsp *http.Response) (*FindPetByIDResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
diff --git a/examples/petstore-expanded/strict/api/petstore-server.gen.go b/examples/petstore-expanded/strict/api/petstore-server.gen.go
index 21959a7..7164d5d 100644
--- a/examples/petstore-expanded/strict/api/petstore-server.gen.go
+++ b/examples/petstore-expanded/strict/api/petstore-server.gen.go
@@ -281,10 +281,17 @@ type FindPetsRequestObject struct {
 	Params FindPetsParams
 }
 
+type FindPetsResponseObject interface {
+	VisitFindPetsResponse(w http.ResponseWriter) error
+}
+
 type FindPets200JSONResponse []Pet
 
-func (t FindPets200JSONResponse) MarshalJSON() ([]byte, error) {
-	return json.Marshal(([]Pet)(t))
+func (response FindPets200JSONResponse) VisitFindPetsResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "application/json")
+	w.WriteHeader(200)
+
+	return json.NewEncoder(w).Encode(response)
 }
 
 type FindPetsdefaultJSONResponse struct {
@@ -292,18 +299,28 @@ type FindPetsdefaultJSONResponse struct {
 	StatusCode int
 }
 
-func (t FindPetsdefaultJSONResponse) MarshalJSON() ([]byte, error) {
-	return json.Marshal(t.Body)
+func (response FindPetsdefaultJSONResponse) VisitFindPetsResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "application/json")
+	w.WriteHeader(response.StatusCode)
+
+	return json.NewEncoder(w).Encode(response.Body)
 }
 
 type AddPetRequestObject struct {
 	Body *AddPetJSONRequestBody
 }
 
+type AddPetResponseObject interface {
+	VisitAddPetResponse(w http.ResponseWriter) error
+}
+
 type AddPet200JSONResponse Pet
 
-func (t AddPet200JSONResponse) MarshalJSON() ([]byte, error) {
-	return json.Marshal((Pet)(t))
+func (response AddPet200JSONResponse) VisitAddPetResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "application/json")
+	w.WriteHeader(200)
+
+	return json.NewEncoder(w).Encode(response)
 }
 
 type AddPetdefaultJSONResponse struct {
@@ -311,34 +328,56 @@ type AddPetdefaultJSONResponse struct {
 	StatusCode int
 }
 
-func (t AddPetdefaultJSONResponse) MarshalJSON() ([]byte, error) {
-	return json.Marshal(t.Body)
+func (response AddPetdefaultJSONResponse) VisitAddPetResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "application/json")
+	w.WriteHeader(response.StatusCode)
+
+	return json.NewEncoder(w).Encode(response.Body)
 }
 
 type DeletePetRequestObject struct {
 	Id int64 `json:"id"`
 }
 
+type DeletePetResponseObject interface {
+	VisitDeletePetResponse(w http.ResponseWriter) error
+}
+
 type DeletePet204Response struct {
 }
 
+func (response DeletePet204Response) VisitDeletePetResponse(w http.ResponseWriter) error {
+	w.WriteHeader(204)
+	return nil
+}
+
 type DeletePetdefaultJSONResponse struct {
 	Body       Error
 	StatusCode int
 }
 
-func (t DeletePetdefaultJSONResponse) MarshalJSON() ([]byte, error) {
-	return json.Marshal(t.Body)
+func (response DeletePetdefaultJSONResponse) VisitDeletePetResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "application/json")
+	w.WriteHeader(response.StatusCode)
+
+	return json.NewEncoder(w).Encode(response.Body)
 }
 
 type FindPetByIDRequestObject struct {
 	Id int64 `json:"id"`
 }
 
+type FindPetByIDResponseObject interface {
+	VisitFindPetByIDResponse(w http.ResponseWriter) error
+}
+
 type FindPetByID200JSONResponse Pet
 
-func (t FindPetByID200JSONResponse) MarshalJSON() ([]byte, error) {
-	return json.Marshal((Pet)(t))
+func (response FindPetByID200JSONResponse) VisitFindPetByIDResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "application/json")
+	w.WriteHeader(200)
+
+	return json.NewEncoder(w).Encode(response)
 }
 
 type FindPetByIDdefaultJSONResponse struct {
@@ -346,27 +385,30 @@ type FindPetByIDdefaultJSONResponse struct {
 	StatusCode int
 }
 
-func (t FindPetByIDdefaultJSONResponse) MarshalJSON() ([]byte, error) {
-	return json.Marshal(t.Body)
+func (response FindPetByIDdefaultJSONResponse) VisitFindPetByIDResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "application/json")
+	w.WriteHeader(response.StatusCode)
+
+	return json.NewEncoder(w).Encode(response.Body)
 }
 
 // StrictServerInterface represents all server handlers.
 type StrictServerInterface interface {
 	// Returns all pets
 	// (GET /pets)
-	FindPets(ctx context.Context, request FindPetsRequestObject) interface{}
+	FindPets(ctx context.Context, request FindPetsRequestObject) (FindPetsResponseObject, error)
 	// Creates a new pet
 	// (POST /pets)
-	AddPet(ctx context.Context, request AddPetRequestObject) interface{}
+	AddPet(ctx context.Context, request AddPetRequestObject) (AddPetResponseObject, error)
 	// Deletes a pet by ID
 	// (DELETE /pets/{id})
-	DeletePet(ctx context.Context, request DeletePetRequestObject) interface{}
+	DeletePet(ctx context.Context, request DeletePetRequestObject) (DeletePetResponseObject, error)
 	// Returns a pet by ID
 	// (GET /pets/{id})
-	FindPetByID(ctx context.Context, request FindPetByIDRequestObject) interface{}
+	FindPetByID(ctx context.Context, request FindPetByIDRequestObject) (FindPetByIDResponseObject, error)
 }
 
-type StrictHandlerFunc func(ctx context.Context, w http.ResponseWriter, r *http.Request, args interface{}) interface{}
+type StrictHandlerFunc func(ctx context.Context, w http.ResponseWriter, r *http.Request, args interface{}) (interface{}, error)
 
 type StrictMiddlewareFunc func(f StrictHandlerFunc, operationID string) StrictHandlerFunc
 
@@ -402,29 +444,23 @@ func (sh *strictHandler) FindPets(w http.ResponseWriter, r *http.Request, params
 
 	request.Params = params
 
-	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) interface{} {
+	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
 		return sh.ssi.FindPets(ctx, request.(FindPetsRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "FindPets")
 	}
 
-	response := handler(r.Context(), w, r, request)
+	response, err := handler(r.Context(), w, r, request)
 
-	switch v := response.(type) {
-	case FindPets200JSONResponse:
-		w.Header().Set("Content-Type", "application/json")
-		w.WriteHeader(200)
-		writeJSON(w, v)
-	case FindPetsdefaultJSONResponse:
-		w.Header().Set("Content-Type", "application/json")
-		w.WriteHeader(v.StatusCode)
-		writeJSON(w, v)
-	case error:
-		sh.options.ResponseErrorHandlerFunc(w, r, v)
-	case nil:
-	default:
-		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", v))
+	if err != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, err)
+	} else if validResponse, ok := response.(FindPetsResponseObject); ok {
+		if err := validResponse.VisitFindPetsResponse(w); err != nil {
+			sh.options.ResponseErrorHandlerFunc(w, r, err)
+		}
+	} else if response != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response))
 	}
 }
 
@@ -439,29 +475,23 @@ func (sh *strictHandler) AddPet(w http.ResponseWriter, r *http.Request) {
 	}
 	request.Body = &body
 
-	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) interface{} {
+	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
 		return sh.ssi.AddPet(ctx, request.(AddPetRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "AddPet")
 	}
 
-	response := handler(r.Context(), w, r, request)
+	response, err := handler(r.Context(), w, r, request)
 
-	switch v := response.(type) {
-	case AddPet200JSONResponse:
-		w.Header().Set("Content-Type", "application/json")
-		w.WriteHeader(200)
-		writeJSON(w, v)
-	case AddPetdefaultJSONResponse:
-		w.Header().Set("Content-Type", "application/json")
-		w.WriteHeader(v.StatusCode)
-		writeJSON(w, v)
-	case error:
-		sh.options.ResponseErrorHandlerFunc(w, r, v)
-	case nil:
-	default:
-		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", v))
+	if err != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, err)
+	} else if validResponse, ok := response.(AddPetResponseObject); ok {
+		if err := validResponse.VisitAddPetResponse(w); err != nil {
+			sh.options.ResponseErrorHandlerFunc(w, r, err)
+		}
+	} else if response != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response))
 	}
 }
 
@@ -471,27 +501,23 @@ func (sh *strictHandler) DeletePet(w http.ResponseWriter, r *http.Request, id in
 
 	request.Id = id
 
-	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) interface{} {
+	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
 		return sh.ssi.DeletePet(ctx, request.(DeletePetRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "DeletePet")
 	}
 
-	response := handler(r.Context(), w, r, request)
+	response, err := handler(r.Context(), w, r, request)
 
-	switch v := response.(type) {
-	case DeletePet204Response:
-		w.WriteHeader(204)
-	case DeletePetdefaultJSONResponse:
-		w.Header().Set("Content-Type", "application/json")
-		w.WriteHeader(v.StatusCode)
-		writeJSON(w, v)
-	case error:
-		sh.options.ResponseErrorHandlerFunc(w, r, v)
-	case nil:
-	default:
-		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", v))
+	if err != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, err)
+	} else if validResponse, ok := response.(DeletePetResponseObject); ok {
+		if err := validResponse.VisitDeletePetResponse(w); err != nil {
+			sh.options.ResponseErrorHandlerFunc(w, r, err)
+		}
+	} else if response != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response))
 	}
 }
 
@@ -501,41 +527,23 @@ func (sh *strictHandler) FindPetByID(w http.ResponseWriter, r *http.Request, id
 
 	request.Id = id
 
-	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) interface{} {
+	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
 		return sh.ssi.FindPetByID(ctx, request.(FindPetByIDRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "FindPetByID")
 	}
 
-	response := handler(r.Context(), w, r, request)
+	response, err := handler(r.Context(), w, r, request)
 
-	switch v := response.(type) {
-	case FindPetByID200JSONResponse:
-		w.Header().Set("Content-Type", "application/json")
-		w.WriteHeader(200)
-		writeJSON(w, v)
-	case FindPetByIDdefaultJSONResponse:
-		w.Header().Set("Content-Type", "application/json")
-		w.WriteHeader(v.StatusCode)
-		writeJSON(w, v)
-	case error:
-		sh.options.ResponseErrorHandlerFunc(w, r, v)
-	case nil:
-	default:
-		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", v))
-	}
-}
-
-func writeJSON(w http.ResponseWriter, v interface{}) {
-	if err := json.NewEncoder(w).Encode(v); err != nil {
-		fmt.Fprintln(w, err)
-	}
-}
-
-func writeRaw(w http.ResponseWriter, b []byte) {
-	if _, err := w.Write(b); err != nil {
-		fmt.Fprintln(w, err)
+	if err != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, err)
+	} else if validResponse, ok := response.(FindPetByIDResponseObject); ok {
+		if err := validResponse.VisitFindPetByIDResponse(w); err != nil {
+			sh.options.ResponseErrorHandlerFunc(w, r, err)
+		}
+	} else if response != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response))
 	}
 }
 
diff --git a/examples/petstore-expanded/strict/api/petstore.go b/examples/petstore-expanded/strict/api/petstore.go
index 316425a..3973bf5 100644
--- a/examples/petstore-expanded/strict/api/petstore.go
+++ b/examples/petstore-expanded/strict/api/petstore.go
@@ -28,7 +28,7 @@ func NewPetStore() *PetStore {
 }
 
 // Here, we implement all of the handlers in the ServerInterface
-func (p *PetStore) FindPets(ctx context.Context, request FindPetsRequestObject) interface{} {
+func (p *PetStore) FindPets(ctx context.Context, request FindPetsRequestObject) (FindPetsResponseObject, error) {
 	p.Lock.Lock()
 	defer p.Lock.Unlock()
 
@@ -56,10 +56,10 @@ func (p *PetStore) FindPets(ctx context.Context, request FindPetsRequestObject)
 		}
 	}
 
-	return FindPets200JSONResponse(result)
+	return FindPets200JSONResponse(result), nil
 }
 
-func (p *PetStore) AddPet(ctx context.Context, request AddPetRequestObject) interface{} {
+func (p *PetStore) AddPet(ctx context.Context, request AddPetRequestObject) (AddPetResponseObject, error) {
 	// We now have a pet, let's add it to our "database".
 	// We're always asynchronous, so lock unsafe operations below
 	p.Lock.Lock()
@@ -76,30 +76,30 @@ func (p *PetStore) AddPet(ctx context.Context, request AddPetRequestObject) inte
 	p.Pets[pet.Id] = pet
 
 	// Now, we have to return the NewPet
-	return AddPet200JSONResponse(pet)
+	return AddPet200JSONResponse(pet), nil
 }
 
-func (p *PetStore) FindPetByID(ctx context.Context, request FindPetByIDRequestObject) interface{} {
+func (p *PetStore) FindPetByID(ctx context.Context, request FindPetByIDRequestObject) (FindPetByIDResponseObject, error) {
 	p.Lock.Lock()
 	defer p.Lock.Unlock()
 
 	pet, found := p.Pets[request.Id]
 	if !found {
-		return FindPetByIDdefaultJSONResponse{StatusCode: http.StatusNotFound, Body: Error{Code: http.StatusNotFound, Message: fmt.Sprintf("Could not find pet with ID %d", request.Id)}}
+		return FindPetByIDdefaultJSONResponse{StatusCode: http.StatusNotFound, Body: Error{Code: http.StatusNotFound, Message: fmt.Sprintf("Could not find pet with ID %d", request.Id)}}, nil
 	}
 
-	return FindPetByID200JSONResponse(pet)
+	return FindPetByID200JSONResponse(pet), nil
 }
 
-func (p *PetStore) DeletePet(ctx context.Context, request DeletePetRequestObject) interface{} {
+func (p *PetStore) DeletePet(ctx context.Context, request DeletePetRequestObject) (DeletePetResponseObject, error) {
 	p.Lock.Lock()
 	defer p.Lock.Unlock()
 
 	_, found := p.Pets[request.Id]
 	if !found {
-		return DeletePetdefaultJSONResponse{StatusCode: http.StatusNotFound, Body: Error{Code: http.StatusNotFound, Message: fmt.Sprintf("Could not find pet with ID %d", request.Id)}}
+		return DeletePetdefaultJSONResponse{StatusCode: http.StatusNotFound, Body: Error{Code: http.StatusNotFound, Message: fmt.Sprintf("Could not find pet with ID %d", request.Id)}}, nil
 	}
 	delete(p.Pets, request.Id)
 
-	return DeletePet204Response{}
+	return DeletePet204Response{}, nil
 }
diff --git a/pkg/codegen/operations.go b/pkg/codegen/operations.go
index f881b14..3aa64ac 100644
--- a/pkg/codegen/operations.go
+++ b/pkg/codegen/operations.go
@@ -751,7 +751,7 @@ func GenerateResponseDefinitions(operationID string, responses openapi3.Response
 			if err != nil {
 				return nil, fmt.Errorf("error generating response header definition: %w", err)
 			}
-			headerDefinition := ResponseHeaderDefinition{Name: headerName, GoName: ToCamelCase(headerName), Schema: contentSchema}
+			headerDefinition := ResponseHeaderDefinition{Name: headerName, GoName: SchemaNameToTypeName(headerName), Schema: contentSchema}
 			responseHeaderDefinitions = append(responseHeaderDefinitions, headerDefinition)
 		}
 
diff --git a/pkg/codegen/templates/client-with-responses.tmpl b/pkg/codegen/templates/client-with-responses.tmpl
index 2b5b7ff..4cb85f0 100644
--- a/pkg/codegen/templates/client-with-responses.tmpl
+++ b/pkg/codegen/templates/client-with-responses.tmpl
@@ -103,7 +103,7 @@ func (c *ClientWithResponses) {{$opid}}{{.Suffix}}WithResponse(ctx context.Conte
 
 // Parse{{genResponseTypeName $opid | ucFirst}} parses an HTTP response from a {{$opid}}WithResponse call
 func Parse{{genResponseTypeName $opid | ucFirst}}(rsp *http.Response) (*{{genResponseTypeName $opid}}, error) {
-    bodyBytes, err := ioutil.ReadAll(rsp.Body)
+    bodyBytes, err := io.ReadAll(rsp.Body)
     defer func() { _ = rsp.Body.Close() }()
     if err != nil {
         return nil, err
@@ -116,4 +116,3 @@ func Parse{{genResponseTypeName $opid | ucFirst}}(rsp *http.Response) (*{{genRes
     return response, nil
 }
 {{end}}{{/* range . $opid := .OperationId */}}
-
diff --git a/pkg/codegen/templates/imports.tmpl b/pkg/codegen/templates/imports.tmpl
index aa7c790..376e1f9 100644
--- a/pkg/codegen/templates/imports.tmpl
+++ b/pkg/codegen/templates/imports.tmpl
@@ -14,7 +14,7 @@ import (
 	"fmt"
 	"gopkg.in/yaml.v2"
 	"io"
-	"io/ioutil"
+	"os"
 	"net/http"
 	"net/url"
 	"path"
diff --git a/pkg/codegen/templates/strict/strict-echo.tmpl b/pkg/codegen/templates/strict/strict-echo.tmpl
index 245f3e5..c858c09 100644
--- a/pkg/codegen/templates/strict/strict-echo.tmpl
+++ b/pkg/codegen/templates/strict/strict-echo.tmpl
@@ -1,4 +1,4 @@
-type StrictHandlerFunc func(ctx echo.Context, args interface{}) interface{}
+type StrictHandlerFunc func(ctx echo.Context, args interface{}) (interface{}, error)
 
 type StrictMiddlewareFunc func(f StrictHandlerFunc, operationID string) StrictHandlerFunc
 
@@ -56,7 +56,7 @@ type strictHandler struct {
                         request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = reader
                     }
                 {{else if eq .NameTag "Text" -}}
-                    data, err := ioutil.ReadAll(ctx.Request().Body)
+                    data, err := io.ReadAll(ctx.Request().Body)
                     if err != nil {
                         return err
                     }
@@ -68,65 +68,21 @@ type strictHandler struct {
             {{if $multipleBodies}}}{{end}}
         {{end}}{{/* range .Bodies */}}
 
-        handler := func(ctx echo.Context, request interface{}) interface{}{
+        handler := func(ctx echo.Context, request interface{}) (interface{}, error){
             return sh.ssi.{{.OperationId}}(ctx.Request().Context(), request.({{$opid | ucFirst}}RequestObject))
         }
         for _, middleware := range sh.middlewares {
             handler = middleware(handler, "{{.OperationId}}")
         }
 
-        response := handler(ctx, request)
+        response, err := handler(ctx, request)
 
-        switch v := response.(type) {
-            {{range .Responses -}}
-                {{$statusCode := .StatusCode -}}
-                {{$fixedStatusCode := .HasFixedStatusCode -}}
-                {{$headers := .Headers -}}
-                {{range .Contents -}}
-                    case {{$opid}}{{$statusCode}}{{.NameTagOrContentType}}Response:
-                    {{range $headers -}}
-                        ctx.Response().Header().Set("{{.Name}}", fmt.Sprint(v.Headers.{{.GoName}}))
-                    {{end -}}
-                    {{if eq .NameTag "JSON" -}}
-                        return ctx.JSON({{if $fixedStatusCode}}{{$statusCode}}{{else}}v.StatusCode{{end}}, v)
-                    {{else if eq .NameTag "Text" -}}
-                        return ctx.Blob({{if $fixedStatusCode}}{{$statusCode}}{{else}}v.StatusCode{{end}}, "{{.ContentType}}", []byte(v))
-                    {{else if eq .NameTag "Formdata" -}}
-                        if form, err := runtime.MarshalForm(v, nil); err != nil {
-                            return err
-                        } else {
-                            return ctx.Blob({{if $fixedStatusCode}}{{$statusCode}}{{else}}v.StatusCode{{end}}, "{{.ContentType}}", []byte(form.Encode()))
-                        }
-                    {{else if eq .NameTag "Multipart" -}}
-                        writer := multipart.NewWriter(ctx.Response())
-                        ctx.Response().Header().Set("Content-Type", writer.FormDataContentType())
-                        defer writer.Close()
-                        if err := v(writer); err != nil {
-                            return err
-                        }
-                    {{else -}}
-                        if v.ContentLength != 0 {
-                            ctx.Response().Header().Set("Content-Length", fmt.Sprint(v.ContentLength))
-                        }
-                        if closer, ok := v.Body.(io.ReadCloser); ok {
-                            defer closer.Close()
-                        }
-                        return ctx.Stream({{if $fixedStatusCode}}{{$statusCode}}{{else}}v.StatusCode{{end}}, {{if .HasFixedContentType }}"{{.ContentType}}"{{else}}v.ContentType{{end}}, v.Body)
-                    {{end}}{{/* if eq .NameTag "JSON" */ -}}
-                {{end}}{{/* range .Contents */ -}}
-                {{if eq 0 (len .Contents) -}}
-                    case {{$opid}}{{$statusCode}}Response:
-                    {{range $headers -}}
-                        ctx.Response().Header().Set("{{.Name}}", fmt.Sprint(v.Headers.{{.GoName}}))
-                    {{end -}}
-                    return ctx.NoContent({{if $fixedStatusCode}}{{$statusCode}}{{else}}v.StatusCode{{end}})
-                {{end}}{{/* if eq 0 (len .Contents) */ -}}
-            {{end}}{{/* range .Responses */ -}}
-            case error:
-                return v
-            case nil:
-            default:
-                return fmt.Errorf("Unexpected response type: %T", v)
+        if err != nil {
+            return err
+        } else if validResponse, ok := response.({{$opid | ucFirst}}ResponseObject); ok {
+            return validResponse.Visit{{$opid}}Response(ctx.Response())
+        } else if response != nil {
+            return fmt.Errorf("Unexpected response type: %T", response)
         }
         return nil
     }
diff --git a/pkg/codegen/templates/strict/strict-gin.tmpl b/pkg/codegen/templates/strict/strict-gin.tmpl
index f1f7e89..c6e93cb 100644
--- a/pkg/codegen/templates/strict/strict-gin.tmpl
+++ b/pkg/codegen/templates/strict/strict-gin.tmpl
@@ -1,4 +1,4 @@
-type StrictHandlerFunc func(ctx *gin.Context, args interface{}) interface{}
+type StrictHandlerFunc func(ctx *gin.Context, args interface{}) (interface{}, error)
 
 type StrictMiddlewareFunc func(f StrictHandlerFunc, operationID string) StrictHandlerFunc
 
@@ -59,7 +59,7 @@ type strictHandler struct {
                         return
                     }
                 {{else if eq .NameTag "Text" -}}
-                    data, err := ioutil.ReadAll(ctx.Request.Body)
+                    data, err := io.ReadAll(ctx.Request.Body)
                     if err != nil {
                         ctx.Error(err)
                         return
@@ -72,62 +72,23 @@ type strictHandler struct {
             {{if $multipleBodies}}}{{end}}
         {{end}}{{/* range .Bodies */}}
 
-        handler := func(ctx *gin.Context, request interface{}) interface{}{
+        handler := func(ctx *gin.Context, request interface{}) (interface{}, error) {
             return sh.ssi.{{.OperationId}}(ctx, request.({{$opid | ucFirst}}RequestObject))
         }
         for _, middleware := range sh.middlewares {
             handler = middleware(handler, "{{.OperationId}}")
         }
 
-        response := handler(ctx, request)
+        response, err := handler(ctx, request)
 
-        switch v := response.(type) {
-            {{range .Responses -}}
-                {{$statusCode := .StatusCode -}}
-                {{$fixedStatusCode := .HasFixedStatusCode -}}
-                {{$headers := .Headers -}}
-                {{range .Contents -}}
-                    case {{$opid}}{{$statusCode}}{{.NameTagOrContentType}}Response:
-                    {{range $headers -}}
-                        ctx.Header("{{.Name}}", fmt.Sprint(v.Headers.{{.GoName}}))
-                    {{end -}}
-                    {{if eq .NameTag "JSON" -}}
-                        ctx.JSON({{if $fixedStatusCode}}{{$statusCode}}{{else}}v.StatusCode{{end}}, v)
-                    {{else if eq .NameTag "Text" -}}
-                        ctx.Data({{if $fixedStatusCode}}{{$statusCode}}{{else}}v.StatusCode{{end}}, "{{.ContentType}}", []byte(v))
-                    {{else if eq .NameTag "Formdata" -}}
-                        if form, err := runtime.MarshalForm(v, nil); err != nil {
-                            ctx.Error(err)
-                        } else {
-                            ctx.Data({{if $fixedStatusCode}}{{$statusCode}}{{else}}v.StatusCode{{end}}, "{{.ContentType}}", []byte(form.Encode()))
-                        }
-                    {{else if eq .NameTag "Multipart" -}}
-                        writer := multipart.NewWriter(ctx.Writer)
-                        ctx.Writer.Header().Set("Content-Type", writer.FormDataContentType())
-                        defer writer.Close()
-                        if err := v(writer); err != nil {
-                            ctx.Error(err)
-                        }
-                    {{else -}}
-                        if closer, ok := v.Body.(io.ReadCloser); ok {
-                            defer closer.Close()
-                        }
-                        ctx.DataFromReader({{if $fixedStatusCode}}{{$statusCode}}{{else}}v.StatusCode{{end}}, v.ContentLength, {{if .HasFixedContentType }}"{{.ContentType}}"{{else}}v.ContentType{{end}}, v.Body, nil)
-                    {{end}}{{/* if eq .NameTag "JSON" */ -}}
-                {{end}}{{/* range .Contents */ -}}
-                {{if eq 0 (len .Contents) -}}
-                    case {{$opid}}{{$statusCode}}Response:
-                    {{range $headers -}}
-                        ctx.Header("{{.Name}}", fmt.Sprint(v.Headers.{{.GoName}}))
-                    {{end -}}
-                    ctx.Status({{if $fixedStatusCode}}{{$statusCode}}{{else}}v.StatusCode{{end}})
-                {{end}}{{/* if eq 0 (len .Contents) */ -}}
-            {{end}}{{/* range .Responses */ -}}
-            case error:
-                ctx.Error(v)
-            case nil:
-            default:
-                ctx.Error(fmt.Errorf("Unexpected response type: %T", v))
+        if err != nil {
+            ctx.Error(err)
+        } else if validResponse, ok := response.({{$opid | ucFirst}}ResponseObject); ok {
+            if err := validResponse.Visit{{$opid}}Response(ctx.Writer); err != nil {
+                ctx.Error(err)
+            }
+        } else if response != nil {
+            ctx.Error(fmt.Errorf("Unexpected response type: %T", response))
         }
     }
 {{end}}
diff --git a/pkg/codegen/templates/strict/strict-http.tmpl b/pkg/codegen/templates/strict/strict-http.tmpl
index c6269aa..b1d2e9d 100644
--- a/pkg/codegen/templates/strict/strict-http.tmpl
+++ b/pkg/codegen/templates/strict/strict-http.tmpl
@@ -1,4 +1,4 @@
-type StrictHandlerFunc func(ctx context.Context, w http.ResponseWriter, r *http.Request, args interface{}) interface{}
+type StrictHandlerFunc func(ctx context.Context, w http.ResponseWriter, r *http.Request, args interface{}) (interface{}, error)
 
 type StrictMiddlewareFunc func(f StrictHandlerFunc, operationID string) StrictHandlerFunc
 
@@ -76,7 +76,7 @@ type strictHandler struct {
                         request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = reader
                     }
                 {{else if eq .NameTag "Text" -}}
-                    data, err := ioutil.ReadAll(r.Body)
+                    data, err := io.ReadAll(r.Body)
                     if err != nil {
                         sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't read body: %w", err))
                         return
@@ -89,82 +89,23 @@ type strictHandler struct {
             {{if $multipleBodies}}}{{end}}
         {{end}}{{/* range .Bodies */}}
 
-        handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) interface{}{
+        handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
             return sh.ssi.{{.OperationId}}(ctx, request.({{$opid | ucFirst}}RequestObject))
         }
         for _, middleware := range sh.middlewares {
             handler = middleware(handler, "{{.OperationId}}")
         }
 
-        response := handler(r.Context(), w, r, request)
+        response, err := handler(r.Context(), w, r, request)
 
-        switch v := response.(type) {
-            {{range .Responses -}}
-                {{$statusCode := .StatusCode -}}
-                {{$fixedStatusCode := .HasFixedStatusCode -}}
-                {{$headers := .Headers -}}
-                {{range .Contents -}}
-                    case {{$opid}}{{$statusCode}}{{.NameTagOrContentType}}Response:
-                    {{range $headers -}}
-                        w.Header().Set("{{.Name}}", fmt.Sprint(v.Headers.{{.GoName}}))
-                    {{end -}}
-                    {{if eq .NameTag "Multipart" -}}
-                        writer := multipart.NewWriter(w)
-                    {{end -}}
-                    w.Header().Set("Content-Type", {{if eq .NameTag "Multipart"}}writer.FormDataContentType(){{else if .HasFixedContentType }}"{{.ContentType}}"{{else}}v.ContentType{{end}})
-                    {{if not .IsSupported -}}
-                        if v.ContentLength != 0 {
-                            w.Header().Set("Content-Length", fmt.Sprint(v.ContentLength))
-                        }
-                    {{end -}}
-                    w.WriteHeader({{if $fixedStatusCode}}{{$statusCode}}{{else}}v.StatusCode{{end}})
-                    {{if eq .NameTag "JSON" -}}
-                        writeJSON(w, v)
-                    {{else if eq .NameTag "Text" -}}
-                        writeRaw(w, ([]byte)(v))
-                    {{else if eq .NameTag "Formdata" -}}
-                        if form, err := runtime.MarshalForm(v, nil); err != nil {
-                            fmt.Fprintln(w, err)
-                        } else {
-                            writeRaw(w, []byte(form.Encode()))
-                        }
-                    {{else if eq .NameTag "Multipart" -}}
-                        defer writer.Close()
-                        if err := v(writer); err != nil {
-                            sh.options.ResponseErrorHandlerFunc(w, r, err)
-                        }
-                    {{else -}}
-                        if closer, ok := v.Body.(io.ReadCloser); ok {
-                            defer closer.Close()
-                        }
-                        _, _ = io.Copy(w, v.Body)
-                    {{end}}{{/* if eq .NameTag "JSON" */ -}}
-                {{end}}{{/* range .Contents */ -}}
-                {{if eq 0 (len .Contents) -}}
-                    case {{$opid}}{{$statusCode}}Response:
-                    {{range $headers -}}
-                        w.Header().Set("{{.Name}}", fmt.Sprint(v.Headers.{{.GoName}}))
-                    {{end -}}
-                    w.WriteHeader({{if $fixedStatusCode}}{{$statusCode}}{{else}}v.StatusCode{{end}})
-                {{end}}{{/* if eq 0 (len .Contents) */ -}}
-            {{end}}{{/* range .Responses */ -}}
-            case error:
-                sh.options.ResponseErrorHandlerFunc(w, r, v)
-            case nil:
-            default:
-                sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", v))
+        if err != nil {
+            sh.options.ResponseErrorHandlerFunc(w, r, err)
+        } else if validResponse, ok := response.({{$opid | ucFirst}}ResponseObject); ok {
+            if err := validResponse.Visit{{$opid}}Response(w); err != nil {
+                sh.options.ResponseErrorHandlerFunc(w, r, err)
+            }
+        } else if response != nil {
+            sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response))
         }
     }
-{{end}}
-
-func writeJSON(w http.ResponseWriter, v interface{}) {
-    if err := json.NewEncoder(w).Encode(v); err != nil {
-        fmt.Fprintln(w, err)
-    }
-}
-
-func writeRaw(w http.ResponseWriter, b []byte) {
-    if _, err := w.Write(b); err != nil {
-        fmt.Fprintln(w, err)
-    }
-}
+{{end}}
\ No newline at end of file
diff --git a/pkg/codegen/templates/strict/strict-interface.tmpl b/pkg/codegen/templates/strict/strict-interface.tmpl
index 91994d5..8a435ba 100644
--- a/pkg/codegen/templates/strict/strict-interface.tmpl
+++ b/pkg/codegen/templates/strict/strict-interface.tmpl
@@ -16,12 +16,17 @@
         {{end -}}
     }
 
+    type {{$opid | ucFirst}}ResponseObject interface {
+        Visit{{$opid}}Response(w http.ResponseWriter) error
+    }
+
     {{range .Responses}}
         {{$statusCode := .StatusCode -}}
         {{$hasHeaders := ne 0 (len .Headers) -}}
         {{$fixedStatusCode := .HasFixedStatusCode -}}
         {{$isRef := .IsRef -}}
         {{$ref := .Ref  | ucFirst -}}
+        {{$headers := .Headers -}}
 
         {{if (and $hasHeaders (not $isRef)) -}}
             type {{$opid}}{{$statusCode}}ResponseHeaders struct {
@@ -36,12 +41,6 @@
                 type {{$opid}}{{$statusCode}}{{.NameTagOrContentType}}Response = {{$ref}}{{.NameTagOrContentType}}Response
             {{else if and (not $hasHeaders) ($fixedStatusCode) (.IsSupported) -}}
                 type {{$opid}}{{$statusCode}}{{.NameTagOrContentType}}Response {{if eq .NameTag "Multipart"}}func(writer *multipart.Writer)error{{else if .IsSupported}}{{if .Schema.IsRef}}={{end}} {{.Schema.TypeDecl}}{{else}}io.Reader{{end}}
-
-                {{if and (not .Schema.IsRef) (eq .NameTag "JSON")}}
-                    func (t {{$opid}}{{$statusCode}}{{.NameTagOrContentType}}Response) MarshalJSON() ([]byte, error) {
-                        return json.Marshal(({{.Schema.GoType}})(t))
-                    }
-                {{end}}
             {{else -}}
                 type {{$opid}}{{$statusCode}}{{.NameTagOrContentType}}Response struct {
                     Body {{if eq .NameTag "Multipart"}}func(writer *multipart.Writer)error{{else if .IsSupported}}{{.Schema.TypeDecl}}{{else}}io.Reader{{end}}
@@ -61,12 +60,46 @@
                         ContentLength int64
                     {{end -}}
                 }
-                {{if eq .NameTag "JSON"}}
-                    func (t {{$opid}}{{$statusCode}}{{.NameTagOrContentType}}Response) MarshalJSON() ([]byte, error) {
-                        return json.Marshal(t.Body)
-                    }
-                {{end}}
             {{end}}
+
+            func (response {{$opid}}{{$statusCode}}{{.NameTagOrContentType}}Response) Visit{{$opid}}Response(w http.ResponseWriter) error {
+                {{range $headers -}}
+                    w.Header().Set("{{.Name}}", fmt.Sprint(response.Headers.{{.GoName}}))
+                {{end -}}
+                {{if eq .NameTag "Multipart" -}}
+                    writer := multipart.NewWriter(w)
+                {{end -}}
+                w.Header().Set("Content-Type", {{if eq .NameTag "Multipart"}}writer.FormDataContentType(){{else if .HasFixedContentType }}"{{.ContentType}}"{{else}}response.ContentType{{end}})
+                {{if not .IsSupported -}}
+                    if response.ContentLength != 0 {
+                        w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength))
+                    }
+                {{end -}}
+                w.WriteHeader({{if $fixedStatusCode}}{{$statusCode}}{{else}}response.StatusCode{{end}})
+                {{$hasBodyVar := or ($hasHeaders) (not $fixedStatusCode) (not .IsSupported)}}
+                {{if eq .NameTag "JSON" -}}
+                    return json.NewEncoder(w).Encode({{if $hasBodyVar}}response.Body{{else}}response{{end}})
+                {{else if eq .NameTag "Text" -}}
+                    _, err := w.Write([]byte({{if $hasBodyVar}}response.Body{{else}}response{{end}}))
+                    return err
+                {{else if eq .NameTag "Formdata" -}}
+                    if form, err := runtime.MarshalForm({{if $hasBodyVar}}response.Body{{else}}response{{end}}, nil); err != nil {
+                        return err
+                    } else {
+                        _, err := w.Write([]byte(form.Encode()))
+                        return err
+                    }
+                {{else if eq .NameTag "Multipart" -}}
+                    defer writer.Close()
+                    return {{if $hasBodyVar}}response.Body{{else}}response{{end}}(writer);
+                {{else -}}
+                    if closer, ok := response.Body.(io.ReadCloser); ok {
+                        defer closer.Close()
+                    }
+                    _, err := io.Copy(w, response.Body)
+                    return err
+                {{end}}{{/* if eq .NameTag "JSON" */ -}}
+            }
         {{end}}
 
         {{if eq 0 (len .Contents) -}}
@@ -82,6 +115,13 @@
                     {{end -}}
                 }
             {{end -}}
+            func (response {{$opid}}{{$statusCode}}Response) Visit{{$opid}}Response(w http.ResponseWriter) error {
+                {{range $headers -}}
+                    w.Header().Set("{{.Name}}", fmt.Sprint(response.Headers.{{.GoName}}))
+                {{end -}}
+                w.WriteHeader({{if $fixedStatusCode}}{{$statusCode}}{{else}}response.StatusCode{{end}})
+                return nil
+            }
         {{end}}
     {{end}}
 {{end}}
@@ -91,6 +131,6 @@ type StrictServerInterface interface {
 {{range .}}{{.SummaryAsComment }}
 // ({{.Method}} {{.Path}})
 {{$opid := .OperationId -}}
-{{$opid}}(ctx context.Context, request {{$opid | ucFirst}}RequestObject) interface{}
+{{$opid}}(ctx context.Context, request {{$opid | ucFirst}}RequestObject) ({{$opid | ucFirst}}ResponseObject, error)
 {{end}}{{/* range . */ -}}
 }
diff --git a/pkg/codegen/templates/strict/strict-responses.tmpl b/pkg/codegen/templates/strict/strict-responses.tmpl
index 6034d8f..d04cbd7 100644
--- a/pkg/codegen/templates/strict/strict-responses.tmpl
+++ b/pkg/codegen/templates/strict/strict-responses.tmpl
@@ -12,12 +12,6 @@
     {{range .Contents -}}
         {{if and (not $hasHeaders) (.IsSupported) -}}
             type {{$name}}{{.NameTagOrContentType}}Response {{if eq .NameTag "Multipart"}}func(writer *multipart.Writer)error{{else if .IsSupported}}{{if .Schema.IsRef}}={{end}} {{.Schema.TypeDecl}}{{else}}io.Reader{{end}}
-
-            {{if and (not (and .Schema.IsRef)) (eq .NameTag "JSON")}}
-                func (t {{$name}}{{.NameTagOrContentType}}Response) MarshalJSON() ([]byte, error) {
-                    return json.Marshal(({{.Schema.GoType}})(t))
-                }
-            {{end}}
         {{else -}}
             type {{$name}}{{.NameTagOrContentType}}Response struct {
                 Body {{if eq .NameTag "Multipart"}}func(writer *multipart.Writer)error{{else if .IsSupported}}{{.Schema.TypeDecl}}{{else}}io.Reader{{end}}
@@ -34,11 +28,6 @@
                     ContentLength int64
                 {{end -}}
             }
-            {{if eq .NameTag "JSON"}}
-                func (t {{$name}}{{.NameTagOrContentType}}Response) MarshalJSON() ([]byte, error) {
-                    return json.Marshal(t.Body)
-                }
-            {{end}}
         {{end -}}
     {{end -}}
 
diff --git a/pkg/runtime/bindstring.go b/pkg/runtime/bindstring.go
index 19ca08b..f597dab 100644
--- a/pkg/runtime/bindstring.go
+++ b/pkg/runtime/bindstring.go
@@ -63,12 +63,20 @@ func BindStringToObject(src string, dst interface{}) error {
 		var val int64
 		val, err = strconv.ParseInt(src, 10, 64)
 		if err == nil {
-			v.SetInt(val)
+			if v.OverflowInt(val) {
+				err = fmt.Errorf("value '%s' overflows destination of type: %s", src, t.Kind())
+			}
+			if err == nil {
+				v.SetInt(val)
+			}
 		}
 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
 		var val uint64
 		val, err = strconv.ParseUint(src, 10, 64)
 		if err == nil {
+			if v.OverflowUint(val) {
+				err = fmt.Errorf("value '%s' overflows destination of type: %s", src, t.Kind())
+			}
 			v.SetUint(val)
 		}
 	case reflect.String:
@@ -78,6 +86,9 @@ func BindStringToObject(src string, dst interface{}) error {
 		var val float64
 		val, err = strconv.ParseFloat(src, 64)
 		if err == nil {
+			if v.OverflowFloat(val) {
+				err = fmt.Errorf("value '%s' overflows destination of type: %s", src, t.Kind())
+			}
 			v.SetFloat(val)
 		}
 	case reflect.Bool:


Test patch:
diff --git a/internal/test/client/client.gen.go b/internal/test/client/client.gen.go
index c5e78ba..75bbb2b 100644
--- a/internal/test/client/client.gen.go
+++ b/internal/test/client/client.gen.go
@@ -11,7 +11,6 @@ import (
 	"encoding/json"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net/http"
 	"net/url"
 	"path"
@@ -876,7 +875,7 @@ func (c *ClientWithResponses) PostVendorJsonWithResponse(ctx context.Context, bo
 
 // ParsePostBothResponse parses an HTTP response from a PostBothWithResponse call
 func ParsePostBothResponse(rsp *http.Response) (*PostBothResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -892,7 +891,7 @@ func ParsePostBothResponse(rsp *http.Response) (*PostBothResponse, error) {
 
 // ParseGetBothResponse parses an HTTP response from a GetBothWithResponse call
 func ParseGetBothResponse(rsp *http.Response) (*GetBothResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -908,7 +907,7 @@ func ParseGetBothResponse(rsp *http.Response) (*GetBothResponse, error) {
 
 // ParsePostJsonResponse parses an HTTP response from a PostJsonWithResponse call
 func ParsePostJsonResponse(rsp *http.Response) (*PostJsonResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -924,7 +923,7 @@ func ParsePostJsonResponse(rsp *http.Response) (*PostJsonResponse, error) {
 
 // ParseGetJsonResponse parses an HTTP response from a GetJsonWithResponse call
 func ParseGetJsonResponse(rsp *http.Response) (*GetJsonResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -940,7 +939,7 @@ func ParseGetJsonResponse(rsp *http.Response) (*GetJsonResponse, error) {
 
 // ParsePostOtherResponse parses an HTTP response from a PostOtherWithResponse call
 func ParsePostOtherResponse(rsp *http.Response) (*PostOtherResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -956,7 +955,7 @@ func ParsePostOtherResponse(rsp *http.Response) (*PostOtherResponse, error) {
 
 // ParseGetOtherResponse parses an HTTP response from a GetOtherWithResponse call
 func ParseGetOtherResponse(rsp *http.Response) (*GetOtherResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -972,7 +971,7 @@ func ParseGetOtherResponse(rsp *http.Response) (*GetOtherResponse, error) {
 
 // ParseGetJsonWithTrailingSlashResponse parses an HTTP response from a GetJsonWithTrailingSlashWithResponse call
 func ParseGetJsonWithTrailingSlashResponse(rsp *http.Response) (*GetJsonWithTrailingSlashResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -988,7 +987,7 @@ func ParseGetJsonWithTrailingSlashResponse(rsp *http.Response) (*GetJsonWithTrai
 
 // ParsePostVendorJsonResponse parses an HTTP response from a PostVendorJsonWithResponse call
 func ParsePostVendorJsonResponse(rsp *http.Response) (*PostVendorJsonResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
diff --git a/internal/test/issues/issue-312/issue.gen.go b/internal/test/issues/issue-312/issue.gen.go
index a2553a1..0285217 100644
--- a/internal/test/issues/issue-312/issue.gen.go
+++ b/internal/test/issues/issue-312/issue.gen.go
@@ -11,7 +11,6 @@ import (
 	"encoding/json"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net/http"
 	"net/url"
 	"path"
@@ -363,7 +362,7 @@ func (c *ClientWithResponses) ValidatePetsWithResponse(ctx context.Context, body
 
 // ParseGetPetResponse parses an HTTP response from a GetPetWithResponse call
 func ParseGetPetResponse(rsp *http.Response) (*GetPetResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -389,7 +388,7 @@ func ParseGetPetResponse(rsp *http.Response) (*GetPetResponse, error) {
 
 // ParseValidatePetsResponse parses an HTTP response from a ValidatePetsWithResponse call
 func ParseValidatePetsResponse(rsp *http.Response) (*ValidatePetsResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
diff --git a/internal/test/issues/issue-52/issue.gen.go b/internal/test/issues/issue-52/issue.gen.go
index 6cede7e..fde84ba 100644
--- a/internal/test/issues/issue-52/issue.gen.go
+++ b/internal/test/issues/issue-52/issue.gen.go
@@ -10,7 +10,7 @@ import (
 	"encoding/base64"
 	"encoding/json"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"net/url"
 	"path"
@@ -230,7 +230,7 @@ func (c *ClientWithResponses) ExampleGetWithResponse(ctx context.Context, reqEdi
 
 // ParseExampleGetResponse parses an HTTP response from a ExampleGetWithResponse call
 func ParseExampleGetResponse(rsp *http.Response) (*ExampleGetResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
diff --git a/internal/test/issues/issue-grab_import_names/issue.gen.go b/internal/test/issues/issue-grab_import_names/issue.gen.go
index 0f0d27f..e7fba84 100644
--- a/internal/test/issues/issue-grab_import_names/issue.gen.go
+++ b/internal/test/issues/issue-grab_import_names/issue.gen.go
@@ -10,7 +10,7 @@ import (
 	"encoding/base64"
 	"encoding/json"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"net/url"
 	"path"
@@ -248,7 +248,7 @@ func (c *ClientWithResponses) GetFooWithResponse(ctx context.Context, params *Ge
 
 // ParseGetFooResponse parses an HTTP response from a GetFooWithResponse call
 func ParseGetFooResponse(rsp *http.Response) (*GetFooResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
diff --git a/internal/test/issues/issue-head-digit-of-httpheader/config.yaml b/internal/test/issues/issue-head-digit-of-httpheader/config.yaml
new file mode 100644
index 0000000..f3709ac
--- /dev/null
+++ b/internal/test/issues/issue-head-digit-of-httpheader/config.yaml
@@ -0,0 +1,7 @@
+---
+package: head_digit_of_httpheader
+generate:
+  strict-server: true
+output: issue.gen.go
+output-options:
+  skip-prune: true
diff --git a/internal/test/issues/issue-head-digit-of-httpheader/doc.go b/internal/test/issues/issue-head-digit-of-httpheader/doc.go
new file mode 100644
index 0000000..4a2cdf8
--- /dev/null
+++ b/internal/test/issues/issue-head-digit-of-httpheader/doc.go
@@ -0,0 +1,3 @@
+package head_digit_of_httpheader
+
+//go:generate go run github.com/deepmap/oapi-codegen/cmd/oapi-codegen --config=config.yaml spec.yaml
diff --git a/internal/test/issues/issue-head-digit-of-httpheader/issue.gen.go b/internal/test/issues/issue-head-digit-of-httpheader/issue.gen.go
new file mode 100644
index 0000000..0ac470b
--- /dev/null
+++ b/internal/test/issues/issue-head-digit-of-httpheader/issue.gen.go
@@ -0,0 +1,27 @@
+// Package head_digit_of_httpheader provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/deepmap/oapi-codegen version (devel) DO NOT EDIT.
+package head_digit_of_httpheader
+
+import (
+	"context"
+)
+
+type N200ResponseHeaders struct {
+	N000Foo string
+}
+type N200Response struct {
+	Headers N200ResponseHeaders
+}
+
+type GetFooRequestObject struct {
+}
+
+type GetFoo200Response = N200Response
+
+// StrictServerInterface represents all server handlers.
+type StrictServerInterface interface {
+
+	// (GET /foo)
+	GetFoo(ctx context.Context, request GetFooRequestObject) interface{}
+}
diff --git a/internal/test/issues/issue-head-digit-of-httpheader/spec.yaml b/internal/test/issues/issue-head-digit-of-httpheader/spec.yaml
new file mode 100644
index 0000000..b6a960a
--- /dev/null
+++ b/internal/test/issues/issue-head-digit-of-httpheader/spec.yaml
@@ -0,0 +1,16 @@
+openapi: 3.0.2
+info:
+  version: "0.0.1"
+paths:
+  /foo:
+    get:
+      responses:
+        200:
+          $ref: "#/components/responses/200"
+components:
+  responses:
+    "200":
+      headers:
+        "000-foo":
+          schema:
+            type: string
diff --git a/internal/test/issues/issue-illegal_enum_names/issue.gen.go b/internal/test/issues/issue-illegal_enum_names/issue.gen.go
index 35dcbe1..6a81336 100644
--- a/internal/test/issues/issue-illegal_enum_names/issue.gen.go
+++ b/internal/test/issues/issue-illegal_enum_names/issue.gen.go
@@ -10,7 +10,7 @@ import (
 	"encoding/base64"
 	"encoding/json"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"net/url"
 	"path"
@@ -233,7 +233,7 @@ func (c *ClientWithResponses) GetFooWithResponse(ctx context.Context, reqEditors
 
 // ParseGetFooResponse parses an HTTP response from a GetFooWithResponse call
 func ParseGetFooResponse(rsp *http.Response) (*GetFooResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
diff --git a/internal/test/parameters/parameters.gen.go b/internal/test/parameters/parameters.gen.go
index 9be420d..9d0fc0e 100644
--- a/internal/test/parameters/parameters.gen.go
+++ b/internal/test/parameters/parameters.gen.go
@@ -10,7 +10,7 @@ import (
 	"encoding/base64"
 	"encoding/json"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"net/url"
 	"path"
@@ -2332,7 +2332,7 @@ func (c *ClientWithResponses) GetStartingWithNumberWithResponse(ctx context.Cont
 
 // ParseGetContentObjectResponse parses an HTTP response from a GetContentObjectWithResponse call
 func ParseGetContentObjectResponse(rsp *http.Response) (*GetContentObjectResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -2348,7 +2348,7 @@ func ParseGetContentObjectResponse(rsp *http.Response) (*GetContentObjectRespons
 
 // ParseGetCookieResponse parses an HTTP response from a GetCookieWithResponse call
 func ParseGetCookieResponse(rsp *http.Response) (*GetCookieResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -2364,7 +2364,7 @@ func ParseGetCookieResponse(rsp *http.Response) (*GetCookieResponse, error) {
 
 // ParseEnumParamsResponse parses an HTTP response from a EnumParamsWithResponse call
 func ParseEnumParamsResponse(rsp *http.Response) (*EnumParamsResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -2380,7 +2380,7 @@ func ParseEnumParamsResponse(rsp *http.Response) (*EnumParamsResponse, error) {
 
 // ParseGetHeaderResponse parses an HTTP response from a GetHeaderWithResponse call
 func ParseGetHeaderResponse(rsp *http.Response) (*GetHeaderResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -2396,7 +2396,7 @@ func ParseGetHeaderResponse(rsp *http.Response) (*GetHeaderResponse, error) {
 
 // ParseGetLabelExplodeArrayResponse parses an HTTP response from a GetLabelExplodeArrayWithResponse call
 func ParseGetLabelExplodeArrayResponse(rsp *http.Response) (*GetLabelExplodeArrayResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -2412,7 +2412,7 @@ func ParseGetLabelExplodeArrayResponse(rsp *http.Response) (*GetLabelExplodeArra
 
 // ParseGetLabelExplodeObjectResponse parses an HTTP response from a GetLabelExplodeObjectWithResponse call
 func ParseGetLabelExplodeObjectResponse(rsp *http.Response) (*GetLabelExplodeObjectResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -2428,7 +2428,7 @@ func ParseGetLabelExplodeObjectResponse(rsp *http.Response) (*GetLabelExplodeObj
 
 // ParseGetLabelNoExplodeArrayResponse parses an HTTP response from a GetLabelNoExplodeArrayWithResponse call
 func ParseGetLabelNoExplodeArrayResponse(rsp *http.Response) (*GetLabelNoExplodeArrayResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -2444,7 +2444,7 @@ func ParseGetLabelNoExplodeArrayResponse(rsp *http.Response) (*GetLabelNoExplode
 
 // ParseGetLabelNoExplodeObjectResponse parses an HTTP response from a GetLabelNoExplodeObjectWithResponse call
 func ParseGetLabelNoExplodeObjectResponse(rsp *http.Response) (*GetLabelNoExplodeObjectResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -2460,7 +2460,7 @@ func ParseGetLabelNoExplodeObjectResponse(rsp *http.Response) (*GetLabelNoExplod
 
 // ParseGetMatrixExplodeArrayResponse parses an HTTP response from a GetMatrixExplodeArrayWithResponse call
 func ParseGetMatrixExplodeArrayResponse(rsp *http.Response) (*GetMatrixExplodeArrayResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -2476,7 +2476,7 @@ func ParseGetMatrixExplodeArrayResponse(rsp *http.Response) (*GetMatrixExplodeAr
 
 // ParseGetMatrixExplodeObjectResponse parses an HTTP response from a GetMatrixExplodeObjectWithResponse call
 func ParseGetMatrixExplodeObjectResponse(rsp *http.Response) (*GetMatrixExplodeObjectResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -2492,7 +2492,7 @@ func ParseGetMatrixExplodeObjectResponse(rsp *http.Response) (*GetMatrixExplodeO
 
 // ParseGetMatrixNoExplodeArrayResponse parses an HTTP response from a GetMatrixNoExplodeArrayWithResponse call
 func ParseGetMatrixNoExplodeArrayResponse(rsp *http.Response) (*GetMatrixNoExplodeArrayResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -2508,7 +2508,7 @@ func ParseGetMatrixNoExplodeArrayResponse(rsp *http.Response) (*GetMatrixNoExplo
 
 // ParseGetMatrixNoExplodeObjectResponse parses an HTTP response from a GetMatrixNoExplodeObjectWithResponse call
 func ParseGetMatrixNoExplodeObjectResponse(rsp *http.Response) (*GetMatrixNoExplodeObjectResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -2524,7 +2524,7 @@ func ParseGetMatrixNoExplodeObjectResponse(rsp *http.Response) (*GetMatrixNoExpl
 
 // ParseGetPassThroughResponse parses an HTTP response from a GetPassThroughWithResponse call
 func ParseGetPassThroughResponse(rsp *http.Response) (*GetPassThroughResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -2540,7 +2540,7 @@ func ParseGetPassThroughResponse(rsp *http.Response) (*GetPassThroughResponse, e
 
 // ParseGetDeepObjectResponse parses an HTTP response from a GetDeepObjectWithResponse call
 func ParseGetDeepObjectResponse(rsp *http.Response) (*GetDeepObjectResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -2556,7 +2556,7 @@ func ParseGetDeepObjectResponse(rsp *http.Response) (*GetDeepObjectResponse, err
 
 // ParseGetQueryFormResponse parses an HTTP response from a GetQueryFormWithResponse call
 func ParseGetQueryFormResponse(rsp *http.Response) (*GetQueryFormResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -2572,7 +2572,7 @@ func ParseGetQueryFormResponse(rsp *http.Response) (*GetQueryFormResponse, error
 
 // ParseGetSimpleExplodeArrayResponse parses an HTTP response from a GetSimpleExplodeArrayWithResponse call
 func ParseGetSimpleExplodeArrayResponse(rsp *http.Response) (*GetSimpleExplodeArrayResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -2588,7 +2588,7 @@ func ParseGetSimpleExplodeArrayResponse(rsp *http.Response) (*GetSimpleExplodeAr
 
 // ParseGetSimpleExplodeObjectResponse parses an HTTP response from a GetSimpleExplodeObjectWithResponse call
 func ParseGetSimpleExplodeObjectResponse(rsp *http.Response) (*GetSimpleExplodeObjectResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -2604,7 +2604,7 @@ func ParseGetSimpleExplodeObjectResponse(rsp *http.Response) (*GetSimpleExplodeO
 
 // ParseGetSimpleNoExplodeArrayResponse parses an HTTP response from a GetSimpleNoExplodeArrayWithResponse call
 func ParseGetSimpleNoExplodeArrayResponse(rsp *http.Response) (*GetSimpleNoExplodeArrayResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -2620,7 +2620,7 @@ func ParseGetSimpleNoExplodeArrayResponse(rsp *http.Response) (*GetSimpleNoExplo
 
 // ParseGetSimpleNoExplodeObjectResponse parses an HTTP response from a GetSimpleNoExplodeObjectWithResponse call
 func ParseGetSimpleNoExplodeObjectResponse(rsp *http.Response) (*GetSimpleNoExplodeObjectResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -2636,7 +2636,7 @@ func ParseGetSimpleNoExplodeObjectResponse(rsp *http.Response) (*GetSimpleNoExpl
 
 // ParseGetSimplePrimitiveResponse parses an HTTP response from a GetSimplePrimitiveWithResponse call
 func ParseGetSimplePrimitiveResponse(rsp *http.Response) (*GetSimplePrimitiveResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -2652,7 +2652,7 @@ func ParseGetSimplePrimitiveResponse(rsp *http.Response) (*GetSimplePrimitiveRes
 
 // ParseGetStartingWithNumberResponse parses an HTTP response from a GetStartingWithNumberWithResponse call
 func ParseGetStartingWithNumberResponse(rsp *http.Response) (*GetStartingWithNumberResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
diff --git a/internal/test/schemas/schemas.gen.go b/internal/test/schemas/schemas.gen.go
index 774512e..b6a9f20 100644
--- a/internal/test/schemas/schemas.gen.go
+++ b/internal/test/schemas/schemas.gen.go
@@ -12,7 +12,6 @@ import (
 	"encoding/xml"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net/http"
 	"net/url"
 	"path"
@@ -930,7 +929,7 @@ func (c *ClientWithResponses) Issue9WithResponse(ctx context.Context, params *Is
 
 // ParseEnsureEverythingIsReferencedResponse parses an HTTP response from a EnsureEverythingIsReferencedWithResponse call
 func ParseEnsureEverythingIsReferencedResponse(rsp *http.Response) (*EnsureEverythingIsReferencedResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -964,7 +963,7 @@ func ParseEnsureEverythingIsReferencedResponse(rsp *http.Response) (*EnsureEvery
 
 // ParseIssue127Response parses an HTTP response from a Issue127WithResponse call
 func ParseIssue127Response(rsp *http.Response) (*Issue127Response, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -1017,7 +1016,7 @@ func ParseIssue127Response(rsp *http.Response) (*Issue127Response, error) {
 
 // ParseIssue185Response parses an HTTP response from a Issue185WithResponse call
 func ParseIssue185Response(rsp *http.Response) (*Issue185Response, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -1033,7 +1032,7 @@ func ParseIssue185Response(rsp *http.Response) (*Issue185Response, error) {
 
 // ParseIssue209Response parses an HTTP response from a Issue209WithResponse call
 func ParseIssue209Response(rsp *http.Response) (*Issue209Response, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -1049,7 +1048,7 @@ func ParseIssue209Response(rsp *http.Response) (*Issue209Response, error) {
 
 // ParseIssue30Response parses an HTTP response from a Issue30WithResponse call
 func ParseIssue30Response(rsp *http.Response) (*Issue30Response, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -1065,7 +1064,7 @@ func ParseIssue30Response(rsp *http.Response) (*Issue30Response, error) {
 
 // ParseGetIssues375Response parses an HTTP response from a GetIssues375WithResponse call
 func ParseGetIssues375Response(rsp *http.Response) (*GetIssues375Response, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -1091,7 +1090,7 @@ func ParseGetIssues375Response(rsp *http.Response) (*GetIssues375Response, error
 
 // ParseIssue41Response parses an HTTP response from a Issue41WithResponse call
 func ParseIssue41Response(rsp *http.Response) (*Issue41Response, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -1107,7 +1106,7 @@ func ParseIssue41Response(rsp *http.Response) (*Issue41Response, error) {
 
 // ParseIssue9Response parses an HTTP response from a Issue9WithResponse call
 func ParseIssue9Response(rsp *http.Response) (*Issue9Response, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
diff --git a/internal/test/strict-server/chi/server.gen.go b/internal/test/strict-server/chi/server.gen.go
index b2ddfac..06dbc6c 100644
--- a/internal/test/strict-server/chi/server.gen.go
+++ b/internal/test/strict-server/chi/server.gen.go
@@ -11,7 +11,6 @@ import (
 	"encoding/json"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"mime/multipart"
 	"net/http"
 	"net/url"
@@ -404,38 +403,74 @@ type ReusableresponseJSONResponse struct {
 	Headers ReusableresponseResponseHeaders
 }
 
-func (t ReusableresponseJSONResponse) MarshalJSON() ([]byte, error) {
-	return json.Marshal(t.Body)
-}
-
 type JSONExampleRequestObject struct {
 	Body *JSONExampleJSONRequestBody
 }
 
+type JSONExampleResponseObject interface {
+	VisitJSONExampleResponse(w http.ResponseWriter) error
+}
+
 type JSONExample200JSONResponse Example
 
-func (t JSONExample200JSONResponse) MarshalJSON() ([]byte, error) {
-	return json.Marshal((Example)(t))
+func (response JSONExample200JSONResponse) VisitJSONExampleResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "application/json")
+	w.WriteHeader(200)
+
+	return json.NewEncoder(w).Encode(response)
 }
 
 type JSONExample400Response = BadrequestResponse
 
+func (response JSONExample400Response) VisitJSONExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type JSONExampledefaultResponse struct {
 	StatusCode int
 }
 
+func (response JSONExampledefaultResponse) VisitJSONExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 type MultipartExampleRequestObject struct {
 	Body *multipart.Reader
 }
 
+type MultipartExampleResponseObject interface {
+	VisitMultipartExampleResponse(w http.ResponseWriter) error
+}
+
 type MultipartExample200MultipartResponse func(writer *multipart.Writer) error
 
+func (response MultipartExample200MultipartResponse) VisitMultipartExampleResponse(w http.ResponseWriter) error {
+	writer := multipart.NewWriter(w)
+	w.Header().Set("Content-Type", writer.FormDataContentType())
+	w.WriteHeader(200)
+
+	defer writer.Close()
+	return response(writer)
+}
+
 type MultipartExample400Response = BadrequestResponse
 
+func (response MultipartExample400Response) VisitMultipartExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type MultipartExampledefaultResponse struct {
 	StatusCode int
 }
 
+func (response MultipartExampledefaultResponse) VisitMultipartExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 type MultipleRequestAndResponseTypesRequestObject struct {
 	JSONBody      *MultipleRequestAndResponseTypesJSONRequestBody
 	FormdataBody  *MultipleRequestAndResponseTypesFormdataRequestBody
@@ -444,104 +479,300 @@ type MultipleRequestAndResponseTypesRequestObject struct {
 	TextBody      *MultipleRequestAndResponseTypesTextRequestBody
 }
 
+type MultipleRequestAndResponseTypesResponseObject interface {
+	VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error
+}
+
 type MultipleRequestAndResponseTypes200JSONResponse Example
 
-func (t MultipleRequestAndResponseTypes200JSONResponse) MarshalJSON() ([]byte, error) {
-	return json.Marshal((Example)(t))
+func (response MultipleRequestAndResponseTypes200JSONResponse) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "application/json")
+	w.WriteHeader(200)
+
+	return json.NewEncoder(w).Encode(response)
 }
 
 type MultipleRequestAndResponseTypes200FormdataResponse Example
 
+func (response MultipleRequestAndResponseTypes200FormdataResponse) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
+	w.WriteHeader(200)
+
+	if form, err := runtime.MarshalForm(response, nil); err != nil {
+		return err
+	} else {
+		_, err := w.Write([]byte(form.Encode()))
+		return err
+	}
+}
+
 type MultipleRequestAndResponseTypes200ImagepngResponse struct {
 	Body          io.Reader
 	ContentLength int64
 }
 
+func (response MultipleRequestAndResponseTypes200ImagepngResponse) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "image/png")
+	if response.ContentLength != 0 {
+		w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength))
+	}
+	w.WriteHeader(200)
+
+	if closer, ok := response.Body.(io.ReadCloser); ok {
+		defer closer.Close()
+	}
+	_, err := io.Copy(w, response.Body)
+	return err
+}
+
 type MultipleRequestAndResponseTypes200MultipartResponse func(writer *multipart.Writer) error
 
+func (response MultipleRequestAndResponseTypes200MultipartResponse) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+	writer := multipart.NewWriter(w)
+	w.Header().Set("Content-Type", writer.FormDataContentType())
+	w.WriteHeader(200)
+
+	defer writer.Close()
+	return response(writer)
+}
+
 type MultipleRequestAndResponseTypes200TextResponse string
 
+func (response MultipleRequestAndResponseTypes200TextResponse) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "text/plain")
+	w.WriteHeader(200)
+
+	_, err := w.Write([]byte(response))
+	return err
+}
+
 type MultipleRequestAndResponseTypes400Response = BadrequestResponse
 
+func (response MultipleRequestAndResponseTypes400Response) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type ReusableResponsesRequestObject struct {
 	Body *ReusableResponsesJSONRequestBody
 }
 
+type ReusableResponsesResponseObject interface {
+	VisitReusableResponsesResponse(w http.ResponseWriter) error
+}
+
 type ReusableResponses200JSONResponse = ReusableresponseJSONResponse
 
+func (response ReusableResponses200JSONResponse) VisitReusableResponsesResponse(w http.ResponseWriter) error {
+	w.Header().Set("header1", fmt.Sprint(response.Headers.Header1))
+	w.Header().Set("header2", fmt.Sprint(response.Headers.Header2))
+	w.Header().Set("Content-Type", "application/json")
+	w.WriteHeader(200)
+
+	return json.NewEncoder(w).Encode(response.Body)
+}
+
 type ReusableResponses400Response = BadrequestResponse
 
+func (response ReusableResponses400Response) VisitReusableResponsesResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type ReusableResponsesdefaultResponse struct {
 	StatusCode int
 }
 
+func (response ReusableResponsesdefaultResponse) VisitReusableResponsesResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 type TextExampleRequestObject struct {
 	Body *TextExampleTextRequestBody
 }
 
+type TextExampleResponseObject interface {
+	VisitTextExampleResponse(w http.ResponseWriter) error
+}
+
 type TextExample200TextResponse string
 
+func (response TextExample200TextResponse) VisitTextExampleResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "text/plain")
+	w.WriteHeader(200)
+
+	_, err := w.Write([]byte(response))
+	return err
+}
+
 type TextExample400Response = BadrequestResponse
 
+func (response TextExample400Response) VisitTextExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type TextExampledefaultResponse struct {
 	StatusCode int
 }
 
+func (response TextExampledefaultResponse) VisitTextExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 type UnknownExampleRequestObject struct {
 	Body io.Reader
 }
 
+type UnknownExampleResponseObject interface {
+	VisitUnknownExampleResponse(w http.ResponseWriter) error
+}
+
 type UnknownExample200Videomp4Response struct {
 	Body          io.Reader
 	ContentLength int64
 }
 
+func (response UnknownExample200Videomp4Response) VisitUnknownExampleResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "video/mp4")
+	if response.ContentLength != 0 {
+		w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength))
+	}
+	w.WriteHeader(200)
+
+	if closer, ok := response.Body.(io.ReadCloser); ok {
+		defer closer.Close()
+	}
+	_, err := io.Copy(w, response.Body)
+	return err
+}
+
 type UnknownExample400Response = BadrequestResponse
 
+func (response UnknownExample400Response) VisitUnknownExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type UnknownExampledefaultResponse struct {
 	StatusCode int
 }
 
+func (response UnknownExampledefaultResponse) VisitUnknownExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 type UnspecifiedContentTypeRequestObject struct {
 	ContentType string
 	Body        io.Reader
 }
 
+type UnspecifiedContentTypeResponseObject interface {
+	VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error
+}
+
 type UnspecifiedContentType200VideoResponse struct {
 	Body          io.Reader
 	ContentType   string
 	ContentLength int64
 }
 
+func (response UnspecifiedContentType200VideoResponse) VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", response.ContentType)
+	if response.ContentLength != 0 {
+		w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength))
+	}
+	w.WriteHeader(200)
+
+	if closer, ok := response.Body.(io.ReadCloser); ok {
+		defer closer.Close()
+	}
+	_, err := io.Copy(w, response.Body)
+	return err
+}
+
 type UnspecifiedContentType400Response = BadrequestResponse
 
+func (response UnspecifiedContentType400Response) VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type UnspecifiedContentType401Response struct {
 }
 
+func (response UnspecifiedContentType401Response) VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error {
+	w.WriteHeader(401)
+	return nil
+}
+
 type UnspecifiedContentType403Response struct {
 }
 
+func (response UnspecifiedContentType403Response) VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error {
+	w.WriteHeader(403)
+	return nil
+}
+
 type UnspecifiedContentTypedefaultResponse struct {
 	StatusCode int
 }
 
+func (response UnspecifiedContentTypedefaultResponse) VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 type URLEncodedExampleRequestObject struct {
 	Body *URLEncodedExampleFormdataRequestBody
 }
 
+type URLEncodedExampleResponseObject interface {
+	VisitURLEncodedExampleResponse(w http.ResponseWriter) error
+}
+
 type URLEncodedExample200FormdataResponse Example
 
+func (response URLEncodedExample200FormdataResponse) VisitURLEncodedExampleResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
+	w.WriteHeader(200)
+
+	if form, err := runtime.MarshalForm(response, nil); err != nil {
+		return err
+	} else {
+		_, err := w.Write([]byte(form.Encode()))
+		return err
+	}
+}
+
 type URLEncodedExample400Response = BadrequestResponse
 
+func (response URLEncodedExample400Response) VisitURLEncodedExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type URLEncodedExampledefaultResponse struct {
 	StatusCode int
 }
 
+func (response URLEncodedExampledefaultResponse) VisitURLEncodedExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 type HeadersExampleRequestObject struct {
 	Params HeadersExampleParams
 	Body   *HeadersExampleJSONRequestBody
 }
 
+type HeadersExampleResponseObject interface {
+	VisitHeadersExampleResponse(w http.ResponseWriter) error
+}
+
 type HeadersExample200ResponseHeaders struct {
 	Header1 string
 	Header2 int
@@ -552,48 +783,63 @@ type HeadersExample200JSONResponse struct {
 	Headers HeadersExample200ResponseHeaders
 }
 
-func (t HeadersExample200JSONResponse) MarshalJSON() ([]byte, error) {
-	return json.Marshal(t.Body)
+func (response HeadersExample200JSONResponse) VisitHeadersExampleResponse(w http.ResponseWriter) error {
+	w.Header().Set("header1", fmt.Sprint(response.Headers.Header1))
+	w.Header().Set("header2", fmt.Sprint(response.Headers.Header2))
+	w.Header().Set("Content-Type", "application/json")
+	w.WriteHeader(200)
+
+	return json.NewEncoder(w).Encode(response.Body)
 }
 
 type HeadersExample400Response = BadrequestResponse
 
+func (response HeadersExample400Response) VisitHeadersExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type HeadersExampledefaultResponse struct {
 	StatusCode int
 }
 
+func (response HeadersExampledefaultResponse) VisitHeadersExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 // StrictServerInterface represents all server handlers.
 type StrictServerInterface interface {
 
 	// (POST /json)
-	JSONExample(ctx context.Context, request JSONExampleRequestObject) interface{}
+	JSONExample(ctx context.Context, request JSONExampleRequestObject) (JSONExampleResponseObject, error)
 
 	// (POST /multipart)
-	MultipartExample(ctx context.Context, request MultipartExampleRequestObject) interface{}
+	MultipartExample(ctx context.Context, request MultipartExampleRequestObject) (MultipartExampleResponseObject, error)
 
 	// (POST /multiple)
-	MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) interface{}
+	MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) (MultipleRequestAndResponseTypesResponseObject, error)
 
 	// (POST /reusable-responses)
-	ReusableResponses(ctx context.Context, request ReusableResponsesRequestObject) interface{}
+	ReusableResponses(ctx context.Context, request ReusableResponsesRequestObject) (ReusableResponsesResponseObject, error)
 
 	// (POST /text)
-	TextExample(ctx context.Context, request TextExampleRequestObject) interface{}
+	TextExample(ctx context.Context, request TextExampleRequestObject) (TextExampleResponseObject, error)
 
 	// (POST /unknown)
-	UnknownExample(ctx context.Context, request UnknownExampleRequestObject) interface{}
+	UnknownExample(ctx context.Context, request UnknownExampleRequestObject) (UnknownExampleResponseObject, error)
 
 	// (POST /unspecified-content-type)
-	UnspecifiedContentType(ctx context.Context, request UnspecifiedContentTypeRequestObject) interface{}
+	UnspecifiedContentType(ctx context.Context, request UnspecifiedContentTypeRequestObject) (UnspecifiedContentTypeResponseObject, error)
 
 	// (POST /urlencoded)
-	URLEncodedExample(ctx context.Context, request URLEncodedExampleRequestObject) interface{}
+	URLEncodedExample(ctx context.Context, request URLEncodedExampleRequestObject) (URLEncodedExampleResponseObject, error)
 
 	// (POST /with-headers)
-	HeadersExample(ctx context.Context, request HeadersExampleRequestObject) interface{}
+	HeadersExample(ctx context.Context, request HeadersExampleRequestObject) (HeadersExampleResponseObject, error)
 }
 
-type StrictHandlerFunc func(ctx context.Context, w http.ResponseWriter, r *http.Request, args interface{}) interface{}
+type StrictHandlerFunc func(ctx context.Context, w http.ResponseWriter, r *http.Request, args interface{}) (interface{}, error)
 
 type StrictMiddlewareFunc func(f StrictHandlerFunc, operationID string) StrictHandlerFunc
 
@@ -634,29 +880,23 @@ func (sh *strictHandler) JSONExample(w http.ResponseWriter, r *http.Request) {
 	}
 	request.Body = &body
 
-	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) interface{} {
+	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
 		return sh.ssi.JSONExample(ctx, request.(JSONExampleRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "JSONExample")
 	}
 
-	response := handler(r.Context(), w, r, request)
+	response, err := handler(r.Context(), w, r, request)
 
-	switch v := response.(type) {
-	case JSONExample200JSONResponse:
-		w.Header().Set("Content-Type", "application/json")
-		w.WriteHeader(200)
-		writeJSON(w, v)
-	case JSONExample400Response:
-		w.WriteHeader(400)
-	case JSONExampledefaultResponse:
-		w.WriteHeader(v.StatusCode)
-	case error:
-		sh.options.ResponseErrorHandlerFunc(w, r, v)
-	case nil:
-	default:
-		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", v))
+	if err != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, err)
+	} else if validResponse, ok := response.(JSONExampleResponseObject); ok {
+		if err := validResponse.VisitJSONExampleResponse(w); err != nil {
+			sh.options.ResponseErrorHandlerFunc(w, r, err)
+		}
+	} else if response != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response))
 	}
 }
 
@@ -671,33 +911,23 @@ func (sh *strictHandler) MultipartExample(w http.ResponseWriter, r *http.Request
 		request.Body = reader
 	}
 
-	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) interface{} {
+	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
 		return sh.ssi.MultipartExample(ctx, request.(MultipartExampleRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "MultipartExample")
 	}
 
-	response := handler(r.Context(), w, r, request)
+	response, err := handler(r.Context(), w, r, request)
 
-	switch v := response.(type) {
-	case MultipartExample200MultipartResponse:
-		writer := multipart.NewWriter(w)
-		w.Header().Set("Content-Type", writer.FormDataContentType())
-		w.WriteHeader(200)
-		defer writer.Close()
-		if err := v(writer); err != nil {
+	if err != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, err)
+	} else if validResponse, ok := response.(MultipartExampleResponseObject); ok {
+		if err := validResponse.VisitMultipartExampleResponse(w); err != nil {
 			sh.options.ResponseErrorHandlerFunc(w, r, err)
 		}
-	case MultipartExample400Response:
-		w.WriteHeader(400)
-	case MultipartExampledefaultResponse:
-		w.WriteHeader(v.StatusCode)
-	case error:
-		sh.options.ResponseErrorHandlerFunc(w, r, v)
-	case nil:
-	default:
-		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", v))
+	} else if response != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response))
 	}
 }
 
@@ -737,7 +967,7 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(w http.ResponseWriter,
 		}
 	}
 	if strings.HasPrefix(r.Header.Get("Content-Type"), "text/plain") {
-		data, err := ioutil.ReadAll(r.Body)
+		data, err := io.ReadAll(r.Body)
 		if err != nil {
 			sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't read body: %w", err))
 			return
@@ -746,57 +976,23 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(w http.ResponseWriter,
 		request.TextBody = &body
 	}
 
-	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) interface{} {
+	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
 		return sh.ssi.MultipleRequestAndResponseTypes(ctx, request.(MultipleRequestAndResponseTypesRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "MultipleRequestAndResponseTypes")
 	}
 
-	response := handler(r.Context(), w, r, request)
+	response, err := handler(r.Context(), w, r, request)
 
-	switch v := response.(type) {
-	case MultipleRequestAndResponseTypes200JSONResponse:
-		w.Header().Set("Content-Type", "application/json")
-		w.WriteHeader(200)
-		writeJSON(w, v)
-	case MultipleRequestAndResponseTypes200FormdataResponse:
-		w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
-		w.WriteHeader(200)
-		if form, err := runtime.MarshalForm(v, nil); err != nil {
-			fmt.Fprintln(w, err)
-		} else {
-			writeRaw(w, []byte(form.Encode()))
-		}
-	case MultipleRequestAndResponseTypes200ImagepngResponse:
-		w.Header().Set("Content-Type", "image/png")
-		if v.ContentLength != 0 {
-			w.Header().Set("Content-Length", fmt.Sprint(v.ContentLength))
-		}
-		w.WriteHeader(200)
-		if closer, ok := v.Body.(io.ReadCloser); ok {
-			defer closer.Close()
-		}
-		_, _ = io.Copy(w, v.Body)
-	case MultipleRequestAndResponseTypes200MultipartResponse:
-		writer := multipart.NewWriter(w)
-		w.Header().Set("Content-Type", writer.FormDataContentType())
-		w.WriteHeader(200)
-		defer writer.Close()
-		if err := v(writer); err != nil {
+	if err != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, err)
+	} else if validResponse, ok := response.(MultipleRequestAndResponseTypesResponseObject); ok {
+		if err := validResponse.VisitMultipleRequestAndResponseTypesResponse(w); err != nil {
 			sh.options.ResponseErrorHandlerFunc(w, r, err)
 		}
-	case MultipleRequestAndResponseTypes200TextResponse:
-		w.Header().Set("Content-Type", "text/plain")
-		w.WriteHeader(200)
-		writeRaw(w, ([]byte)(v))
-	case MultipleRequestAndResponseTypes400Response:
-		w.WriteHeader(400)
-	case error:
-		sh.options.ResponseErrorHandlerFunc(w, r, v)
-	case nil:
-	default:
-		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", v))
+	} else if response != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response))
 	}
 }
 
@@ -811,31 +1007,23 @@ func (sh *strictHandler) ReusableResponses(w http.ResponseWriter, r *http.Reques
 	}
 	request.Body = &body
 
-	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) interface{} {
+	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
 		return sh.ssi.ReusableResponses(ctx, request.(ReusableResponsesRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "ReusableResponses")
 	}
 
-	response := handler(r.Context(), w, r, request)
+	response, err := handler(r.Context(), w, r, request)
 
-	switch v := response.(type) {
-	case ReusableResponses200JSONResponse:
-		w.Header().Set("header1", fmt.Sprint(v.Headers.Header1))
-		w.Header().Set("header2", fmt.Sprint(v.Headers.Header2))
-		w.Header().Set("Content-Type", "application/json")
-		w.WriteHeader(200)
-		writeJSON(w, v)
-	case ReusableResponses400Response:
-		w.WriteHeader(400)
-	case ReusableResponsesdefaultResponse:
-		w.WriteHeader(v.StatusCode)
-	case error:
-		sh.options.ResponseErrorHandlerFunc(w, r, v)
-	case nil:
-	default:
-		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", v))
+	if err != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, err)
+	} else if validResponse, ok := response.(ReusableResponsesResponseObject); ok {
+		if err := validResponse.VisitReusableResponsesResponse(w); err != nil {
+			sh.options.ResponseErrorHandlerFunc(w, r, err)
+		}
+	} else if response != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response))
 	}
 }
 
@@ -843,7 +1031,7 @@ func (sh *strictHandler) ReusableResponses(w http.ResponseWriter, r *http.Reques
 func (sh *strictHandler) TextExample(w http.ResponseWriter, r *http.Request) {
 	var request TextExampleRequestObject
 
-	data, err := ioutil.ReadAll(r.Body)
+	data, err := io.ReadAll(r.Body)
 	if err != nil {
 		sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't read body: %w", err))
 		return
@@ -851,29 +1039,23 @@ func (sh *strictHandler) TextExample(w http.ResponseWriter, r *http.Request) {
 	body := TextExampleTextRequestBody(data)
 	request.Body = &body
 
-	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) interface{} {
+	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
 		return sh.ssi.TextExample(ctx, request.(TextExampleRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "TextExample")
 	}
 
-	response := handler(r.Context(), w, r, request)
+	response, err := handler(r.Context(), w, r, request)
 
-	switch v := response.(type) {
-	case TextExample200TextResponse:
-		w.Header().Set("Content-Type", "text/plain")
-		w.WriteHeader(200)
-		writeRaw(w, ([]byte)(v))
-	case TextExample400Response:
-		w.WriteHeader(400)
-	case TextExampledefaultResponse:
-		w.WriteHeader(v.StatusCode)
-	case error:
-		sh.options.ResponseErrorHandlerFunc(w, r, v)
-	case nil:
-	default:
-		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", v))
+	if err != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, err)
+	} else if validResponse, ok := response.(TextExampleResponseObject); ok {
+		if err := validResponse.VisitTextExampleResponse(w); err != nil {
+			sh.options.ResponseErrorHandlerFunc(w, r, err)
+		}
+	} else if response != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response))
 	}
 }
 
@@ -883,35 +1065,23 @@ func (sh *strictHandler) UnknownExample(w http.ResponseWriter, r *http.Request)
 
 	request.Body = r.Body
 
-	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) interface{} {
+	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
 		return sh.ssi.UnknownExample(ctx, request.(UnknownExampleRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "UnknownExample")
 	}
 
-	response := handler(r.Context(), w, r, request)
+	response, err := handler(r.Context(), w, r, request)
 
-	switch v := response.(type) {
-	case UnknownExample200Videomp4Response:
-		w.Header().Set("Content-Type", "video/mp4")
-		if v.ContentLength != 0 {
-			w.Header().Set("Content-Length", fmt.Sprint(v.ContentLength))
-		}
-		w.WriteHeader(200)
-		if closer, ok := v.Body.(io.ReadCloser); ok {
-			defer closer.Close()
+	if err != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, err)
+	} else if validResponse, ok := response.(UnknownExampleResponseObject); ok {
+		if err := validResponse.VisitUnknownExampleResponse(w); err != nil {
+			sh.options.ResponseErrorHandlerFunc(w, r, err)
 		}
-		_, _ = io.Copy(w, v.Body)
-	case UnknownExample400Response:
-		w.WriteHeader(400)
-	case UnknownExampledefaultResponse:
-		w.WriteHeader(v.StatusCode)
-	case error:
-		sh.options.ResponseErrorHandlerFunc(w, r, v)
-	case nil:
-	default:
-		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", v))
+	} else if response != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response))
 	}
 }
 
@@ -923,39 +1093,23 @@ func (sh *strictHandler) UnspecifiedContentType(w http.ResponseWriter, r *http.R
 
 	request.Body = r.Body
 
-	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) interface{} {
+	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
 		return sh.ssi.UnspecifiedContentType(ctx, request.(UnspecifiedContentTypeRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "UnspecifiedContentType")
 	}
 
-	response := handler(r.Context(), w, r, request)
+	response, err := handler(r.Context(), w, r, request)
 
-	switch v := response.(type) {
-	case UnspecifiedContentType200VideoResponse:
-		w.Header().Set("Content-Type", v.ContentType)
-		if v.ContentLength != 0 {
-			w.Header().Set("Content-Length", fmt.Sprint(v.ContentLength))
-		}
-		w.WriteHeader(200)
-		if closer, ok := v.Body.(io.ReadCloser); ok {
-			defer closer.Close()
+	if err != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, err)
+	} else if validResponse, ok := response.(UnspecifiedContentTypeResponseObject); ok {
+		if err := validResponse.VisitUnspecifiedContentTypeResponse(w); err != nil {
+			sh.options.ResponseErrorHandlerFunc(w, r, err)
 		}
-		_, _ = io.Copy(w, v.Body)
-	case UnspecifiedContentType400Response:
-		w.WriteHeader(400)
-	case UnspecifiedContentType401Response:
-		w.WriteHeader(401)
-	case UnspecifiedContentType403Response:
-		w.WriteHeader(403)
-	case UnspecifiedContentTypedefaultResponse:
-		w.WriteHeader(v.StatusCode)
-	case error:
-		sh.options.ResponseErrorHandlerFunc(w, r, v)
-	case nil:
-	default:
-		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", v))
+	} else if response != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response))
 	}
 }
 
@@ -974,33 +1128,23 @@ func (sh *strictHandler) URLEncodedExample(w http.ResponseWriter, r *http.Reques
 	}
 	request.Body = &body
 
-	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) interface{} {
+	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
 		return sh.ssi.URLEncodedExample(ctx, request.(URLEncodedExampleRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "URLEncodedExample")
 	}
 
-	response := handler(r.Context(), w, r, request)
+	response, err := handler(r.Context(), w, r, request)
 
-	switch v := response.(type) {
-	case URLEncodedExample200FormdataResponse:
-		w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
-		w.WriteHeader(200)
-		if form, err := runtime.MarshalForm(v, nil); err != nil {
-			fmt.Fprintln(w, err)
-		} else {
-			writeRaw(w, []byte(form.Encode()))
+	if err != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, err)
+	} else if validResponse, ok := response.(URLEncodedExampleResponseObject); ok {
+		if err := validResponse.VisitURLEncodedExampleResponse(w); err != nil {
+			sh.options.ResponseErrorHandlerFunc(w, r, err)
 		}
-	case URLEncodedExample400Response:
-		w.WriteHeader(400)
-	case URLEncodedExampledefaultResponse:
-		w.WriteHeader(v.StatusCode)
-	case error:
-		sh.options.ResponseErrorHandlerFunc(w, r, v)
-	case nil:
-	default:
-		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", v))
+	} else if response != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response))
 	}
 }
 
@@ -1017,43 +1161,23 @@ func (sh *strictHandler) HeadersExample(w http.ResponseWriter, r *http.Request,
 	}
 	request.Body = &body
 
-	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) interface{} {
+	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
 		return sh.ssi.HeadersExample(ctx, request.(HeadersExampleRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "HeadersExample")
 	}
 
-	response := handler(r.Context(), w, r, request)
-
-	switch v := response.(type) {
-	case HeadersExample200JSONResponse:
-		w.Header().Set("header1", fmt.Sprint(v.Headers.Header1))
-		w.Header().Set("header2", fmt.Sprint(v.Headers.Header2))
-		w.Header().Set("Content-Type", "application/json")
-		w.WriteHeader(200)
-		writeJSON(w, v)
-	case HeadersExample400Response:
-		w.WriteHeader(400)
-	case HeadersExampledefaultResponse:
-		w.WriteHeader(v.StatusCode)
-	case error:
-		sh.options.ResponseErrorHandlerFunc(w, r, v)
-	case nil:
-	default:
-		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", v))
-	}
-}
-
-func writeJSON(w http.ResponseWriter, v interface{}) {
-	if err := json.NewEncoder(w).Encode(v); err != nil {
-		fmt.Fprintln(w, err)
-	}
-}
+	response, err := handler(r.Context(), w, r, request)
 
-func writeRaw(w http.ResponseWriter, b []byte) {
-	if _, err := w.Write(b); err != nil {
-		fmt.Fprintln(w, err)
+	if err != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, err)
+	} else if validResponse, ok := response.(HeadersExampleResponseObject); ok {
+		if err := validResponse.VisitHeadersExampleResponse(w); err != nil {
+			sh.options.ResponseErrorHandlerFunc(w, r, err)
+		}
+	} else if response != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response))
 	}
 }
 
diff --git a/internal/test/strict-server/chi/server.go b/internal/test/strict-server/chi/server.go
index 876850a..748fc7d 100644
--- a/internal/test/strict-server/chi/server.go
+++ b/internal/test/strict-server/chi/server.go
@@ -12,11 +12,11 @@ import (
 type StrictServer struct {
 }
 
-func (s StrictServer) JSONExample(ctx context.Context, request JSONExampleRequestObject) interface{} {
-	return JSONExample200JSONResponse(*request.Body)
+func (s StrictServer) JSONExample(ctx context.Context, request JSONExampleRequestObject) (JSONExampleResponseObject, error) {
+	return JSONExample200JSONResponse(*request.Body), nil
 }
 
-func (s StrictServer) MultipartExample(ctx context.Context, request MultipartExampleRequestObject) interface{} {
+func (s StrictServer) MultipartExample(ctx context.Context, request MultipartExampleRequestObject) (MultipartExampleResponseObject, error) {
 	return MultipartExample200MultipartResponse(func(writer *multipart.Writer) error {
 		for {
 			part, err := request.Body.NextPart()
@@ -37,19 +37,19 @@ func (s StrictServer) MultipartExample(ctx context.Context, request MultipartExa
 				return err
 			}
 		}
-	})
+	}), nil
 }
 
-func (s StrictServer) MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) interface{} {
+func (s StrictServer) MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) (MultipleRequestAndResponseTypesResponseObject, error) {
 	switch {
 	case request.Body != nil:
-		return MultipleRequestAndResponseTypes200ImagepngResponse{Body: request.Body}
+		return MultipleRequestAndResponseTypes200ImagepngResponse{Body: request.Body}, nil
 	case request.JSONBody != nil:
-		return MultipleRequestAndResponseTypes200JSONResponse(*request.JSONBody)
+		return MultipleRequestAndResponseTypes200JSONResponse(*request.JSONBody), nil
 	case request.FormdataBody != nil:
-		return MultipleRequestAndResponseTypes200FormdataResponse(*request.FormdataBody)
+		return MultipleRequestAndResponseTypes200FormdataResponse(*request.FormdataBody), nil
 	case request.TextBody != nil:
-		return MultipleRequestAndResponseTypes200TextResponse(*request.TextBody)
+		return MultipleRequestAndResponseTypes200TextResponse(*request.TextBody), nil
 	case request.MultipartBody != nil:
 		return MultipleRequestAndResponseTypes200MultipartResponse(func(writer *multipart.Writer) error {
 			for {
@@ -71,32 +71,32 @@ func (s StrictServer) MultipleRequestAndResponseTypes(ctx context.Context, reque
 					return err
 				}
 			}
-		})
+		}), nil
 	default:
-		return MultipleRequestAndResponseTypes400Response{}
+		return MultipleRequestAndResponseTypes400Response{}, nil
 	}
 }
 
-func (s StrictServer) TextExample(ctx context.Context, request TextExampleRequestObject) interface{} {
-	return TextExample200TextResponse(*request.Body)
+func (s StrictServer) TextExample(ctx context.Context, request TextExampleRequestObject) (TextExampleResponseObject, error) {
+	return TextExample200TextResponse(*request.Body), nil
 }
 
-func (s StrictServer) UnknownExample(ctx context.Context, request UnknownExampleRequestObject) interface{} {
-	return UnknownExample200Videomp4Response{Body: request.Body}
+func (s StrictServer) UnknownExample(ctx context.Context, request UnknownExampleRequestObject) (UnknownExampleResponseObject, error) {
+	return UnknownExample200Videomp4Response{Body: request.Body}, nil
 }
 
-func (s StrictServer) UnspecifiedContentType(ctx context.Context, request UnspecifiedContentTypeRequestObject) interface{} {
-	return UnspecifiedContentType200VideoResponse{Body: request.Body, ContentType: request.ContentType}
+func (s StrictServer) UnspecifiedContentType(ctx context.Context, request UnspecifiedContentTypeRequestObject) (UnspecifiedContentTypeResponseObject, error) {
+	return UnspecifiedContentType200VideoResponse{Body: request.Body, ContentType: request.ContentType}, nil
 }
 
-func (s StrictServer) URLEncodedExample(ctx context.Context, request URLEncodedExampleRequestObject) interface{} {
-	return URLEncodedExample200FormdataResponse(*request.Body)
+func (s StrictServer) URLEncodedExample(ctx context.Context, request URLEncodedExampleRequestObject) (URLEncodedExampleResponseObject, error) {
+	return URLEncodedExample200FormdataResponse(*request.Body), nil
 }
 
-func (s StrictServer) HeadersExample(ctx context.Context, request HeadersExampleRequestObject) interface{} {
-	return HeadersExample200JSONResponse{Body: Example(*request.Body), Headers: HeadersExample200ResponseHeaders{Header1: request.Params.Header1, Header2: *request.Params.Header2}}
+func (s StrictServer) HeadersExample(ctx context.Context, request HeadersExampleRequestObject) (HeadersExampleResponseObject, error) {
+	return HeadersExample200JSONResponse{Body: Example(*request.Body), Headers: HeadersExample200ResponseHeaders{Header1: request.Params.Header1, Header2: *request.Params.Header2}}, nil
 }
 
-func (s StrictServer) ReusableResponses(ctx context.Context, request ReusableResponsesRequestObject) interface{} {
-	return ReusableResponses200JSONResponse{Body: *request.Body}
+func (s StrictServer) ReusableResponses(ctx context.Context, request ReusableResponsesRequestObject) (ReusableResponsesResponseObject, error) {
+	return ReusableResponses200JSONResponse{Body: *request.Body}, nil
 }
diff --git a/internal/test/strict-server/client/client.gen.go b/internal/test/strict-server/client/client.gen.go
index 6c02ddf..68105f2 100644
--- a/internal/test/strict-server/client/client.gen.go
+++ b/internal/test/strict-server/client/client.gen.go
@@ -9,7 +9,6 @@ import (
 	"encoding/json"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net/http"
 	"net/url"
 	"strings"
@@ -1176,7 +1175,7 @@ func (c *ClientWithResponses) HeadersExampleWithResponse(ctx context.Context, pa
 
 // ParseJSONExampleResponse parses an HTTP response from a JSONExampleWithResponse call
 func ParseJSONExampleResponse(rsp *http.Response) (*JSONExampleResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -1202,7 +1201,7 @@ func ParseJSONExampleResponse(rsp *http.Response) (*JSONExampleResponse, error)
 
 // ParseMultipartExampleResponse parses an HTTP response from a MultipartExampleWithResponse call
 func ParseMultipartExampleResponse(rsp *http.Response) (*MultipartExampleResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -1218,7 +1217,7 @@ func ParseMultipartExampleResponse(rsp *http.Response) (*MultipartExampleRespons
 
 // ParseMultipleRequestAndResponseTypesResponse parses an HTTP response from a MultipleRequestAndResponseTypesWithResponse call
 func ParseMultipleRequestAndResponseTypesResponse(rsp *http.Response) (*MultipleRequestAndResponseTypesResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -1247,7 +1246,7 @@ func ParseMultipleRequestAndResponseTypesResponse(rsp *http.Response) (*Multiple
 
 // ParseReusableResponsesResponse parses an HTTP response from a ReusableResponsesWithResponse call
 func ParseReusableResponsesResponse(rsp *http.Response) (*ReusableResponsesResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -1273,7 +1272,7 @@ func ParseReusableResponsesResponse(rsp *http.Response) (*ReusableResponsesRespo
 
 // ParseTextExampleResponse parses an HTTP response from a TextExampleWithResponse call
 func ParseTextExampleResponse(rsp *http.Response) (*TextExampleResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -1289,7 +1288,7 @@ func ParseTextExampleResponse(rsp *http.Response) (*TextExampleResponse, error)
 
 // ParseUnknownExampleResponse parses an HTTP response from a UnknownExampleWithResponse call
 func ParseUnknownExampleResponse(rsp *http.Response) (*UnknownExampleResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -1305,7 +1304,7 @@ func ParseUnknownExampleResponse(rsp *http.Response) (*UnknownExampleResponse, e
 
 // ParseUnspecifiedContentTypeResponse parses an HTTP response from a UnspecifiedContentTypeWithResponse call
 func ParseUnspecifiedContentTypeResponse(rsp *http.Response) (*UnspecifiedContentTypeResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -1321,7 +1320,7 @@ func ParseUnspecifiedContentTypeResponse(rsp *http.Response) (*UnspecifiedConten
 
 // ParseURLEncodedExampleResponse parses an HTTP response from a URLEncodedExampleWithResponse call
 func ParseURLEncodedExampleResponse(rsp *http.Response) (*URLEncodedExampleResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
@@ -1337,7 +1336,7 @@ func ParseURLEncodedExampleResponse(rsp *http.Response) (*URLEncodedExampleRespo
 
 // ParseHeadersExampleResponse parses an HTTP response from a HeadersExampleWithResponse call
 func ParseHeadersExampleResponse(rsp *http.Response) (*HeadersExampleResponse, error) {
-	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	bodyBytes, err := io.ReadAll(rsp.Body)
 	defer func() { _ = rsp.Body.Close() }()
 	if err != nil {
 		return nil, err
diff --git a/internal/test/strict-server/echo/server.gen.go b/internal/test/strict-server/echo/server.gen.go
index 9ba52dc..3002b2a 100644
--- a/internal/test/strict-server/echo/server.gen.go
+++ b/internal/test/strict-server/echo/server.gen.go
@@ -11,7 +11,6 @@ import (
 	"encoding/json"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"mime/multipart"
 	"net/http"
 	"net/url"
@@ -230,38 +229,74 @@ type ReusableresponseJSONResponse struct {
 	Headers ReusableresponseResponseHeaders
 }
 
-func (t ReusableresponseJSONResponse) MarshalJSON() ([]byte, error) {
-	return json.Marshal(t.Body)
-}
-
 type JSONExampleRequestObject struct {
 	Body *JSONExampleJSONRequestBody
 }
 
+type JSONExampleResponseObject interface {
+	VisitJSONExampleResponse(w http.ResponseWriter) error
+}
+
 type JSONExample200JSONResponse Example
 
-func (t JSONExample200JSONResponse) MarshalJSON() ([]byte, error) {
-	return json.Marshal((Example)(t))
+func (response JSONExample200JSONResponse) VisitJSONExampleResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "application/json")
+	w.WriteHeader(200)
+
+	return json.NewEncoder(w).Encode(response)
 }
 
 type JSONExample400Response = BadrequestResponse
 
+func (response JSONExample400Response) VisitJSONExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type JSONExampledefaultResponse struct {
 	StatusCode int
 }
 
+func (response JSONExampledefaultResponse) VisitJSONExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 type MultipartExampleRequestObject struct {
 	Body *multipart.Reader
 }
 
+type MultipartExampleResponseObject interface {
+	VisitMultipartExampleResponse(w http.ResponseWriter) error
+}
+
 type MultipartExample200MultipartResponse func(writer *multipart.Writer) error
 
+func (response MultipartExample200MultipartResponse) VisitMultipartExampleResponse(w http.ResponseWriter) error {
+	writer := multipart.NewWriter(w)
+	w.Header().Set("Content-Type", writer.FormDataContentType())
+	w.WriteHeader(200)
+
+	defer writer.Close()
+	return response(writer)
+}
+
 type MultipartExample400Response = BadrequestResponse
 
+func (response MultipartExample400Response) VisitMultipartExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type MultipartExampledefaultResponse struct {
 	StatusCode int
 }
 
+func (response MultipartExampledefaultResponse) VisitMultipartExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 type MultipleRequestAndResponseTypesRequestObject struct {
 	JSONBody      *MultipleRequestAndResponseTypesJSONRequestBody
 	FormdataBody  *MultipleRequestAndResponseTypesFormdataRequestBody
@@ -270,104 +305,300 @@ type MultipleRequestAndResponseTypesRequestObject struct {
 	TextBody      *MultipleRequestAndResponseTypesTextRequestBody
 }
 
+type MultipleRequestAndResponseTypesResponseObject interface {
+	VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error
+}
+
 type MultipleRequestAndResponseTypes200JSONResponse Example
 
-func (t MultipleRequestAndResponseTypes200JSONResponse) MarshalJSON() ([]byte, error) {
-	return json.Marshal((Example)(t))
+func (response MultipleRequestAndResponseTypes200JSONResponse) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "application/json")
+	w.WriteHeader(200)
+
+	return json.NewEncoder(w).Encode(response)
 }
 
 type MultipleRequestAndResponseTypes200FormdataResponse Example
 
+func (response MultipleRequestAndResponseTypes200FormdataResponse) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
+	w.WriteHeader(200)
+
+	if form, err := runtime.MarshalForm(response, nil); err != nil {
+		return err
+	} else {
+		_, err := w.Write([]byte(form.Encode()))
+		return err
+	}
+}
+
 type MultipleRequestAndResponseTypes200ImagepngResponse struct {
 	Body          io.Reader
 	ContentLength int64
 }
 
+func (response MultipleRequestAndResponseTypes200ImagepngResponse) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "image/png")
+	if response.ContentLength != 0 {
+		w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength))
+	}
+	w.WriteHeader(200)
+
+	if closer, ok := response.Body.(io.ReadCloser); ok {
+		defer closer.Close()
+	}
+	_, err := io.Copy(w, response.Body)
+	return err
+}
+
 type MultipleRequestAndResponseTypes200MultipartResponse func(writer *multipart.Writer) error
 
+func (response MultipleRequestAndResponseTypes200MultipartResponse) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+	writer := multipart.NewWriter(w)
+	w.Header().Set("Content-Type", writer.FormDataContentType())
+	w.WriteHeader(200)
+
+	defer writer.Close()
+	return response(writer)
+}
+
 type MultipleRequestAndResponseTypes200TextResponse string
 
+func (response MultipleRequestAndResponseTypes200TextResponse) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "text/plain")
+	w.WriteHeader(200)
+
+	_, err := w.Write([]byte(response))
+	return err
+}
+
 type MultipleRequestAndResponseTypes400Response = BadrequestResponse
 
+func (response MultipleRequestAndResponseTypes400Response) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type ReusableResponsesRequestObject struct {
 	Body *ReusableResponsesJSONRequestBody
 }
 
+type ReusableResponsesResponseObject interface {
+	VisitReusableResponsesResponse(w http.ResponseWriter) error
+}
+
 type ReusableResponses200JSONResponse = ReusableresponseJSONResponse
 
+func (response ReusableResponses200JSONResponse) VisitReusableResponsesResponse(w http.ResponseWriter) error {
+	w.Header().Set("header1", fmt.Sprint(response.Headers.Header1))
+	w.Header().Set("header2", fmt.Sprint(response.Headers.Header2))
+	w.Header().Set("Content-Type", "application/json")
+	w.WriteHeader(200)
+
+	return json.NewEncoder(w).Encode(response.Body)
+}
+
 type ReusableResponses400Response = BadrequestResponse
 
+func (response ReusableResponses400Response) VisitReusableResponsesResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type ReusableResponsesdefaultResponse struct {
 	StatusCode int
 }
 
+func (response ReusableResponsesdefaultResponse) VisitReusableResponsesResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 type TextExampleRequestObject struct {
 	Body *TextExampleTextRequestBody
 }
 
+type TextExampleResponseObject interface {
+	VisitTextExampleResponse(w http.ResponseWriter) error
+}
+
 type TextExample200TextResponse string
 
+func (response TextExample200TextResponse) VisitTextExampleResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "text/plain")
+	w.WriteHeader(200)
+
+	_, err := w.Write([]byte(response))
+	return err
+}
+
 type TextExample400Response = BadrequestResponse
 
+func (response TextExample400Response) VisitTextExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type TextExampledefaultResponse struct {
 	StatusCode int
 }
 
+func (response TextExampledefaultResponse) VisitTextExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 type UnknownExampleRequestObject struct {
 	Body io.Reader
 }
 
+type UnknownExampleResponseObject interface {
+	VisitUnknownExampleResponse(w http.ResponseWriter) error
+}
+
 type UnknownExample200Videomp4Response struct {
 	Body          io.Reader
 	ContentLength int64
 }
 
+func (response UnknownExample200Videomp4Response) VisitUnknownExampleResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "video/mp4")
+	if response.ContentLength != 0 {
+		w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength))
+	}
+	w.WriteHeader(200)
+
+	if closer, ok := response.Body.(io.ReadCloser); ok {
+		defer closer.Close()
+	}
+	_, err := io.Copy(w, response.Body)
+	return err
+}
+
 type UnknownExample400Response = BadrequestResponse
 
+func (response UnknownExample400Response) VisitUnknownExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type UnknownExampledefaultResponse struct {
 	StatusCode int
 }
 
+func (response UnknownExampledefaultResponse) VisitUnknownExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 type UnspecifiedContentTypeRequestObject struct {
 	ContentType string
 	Body        io.Reader
 }
 
+type UnspecifiedContentTypeResponseObject interface {
+	VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error
+}
+
 type UnspecifiedContentType200VideoResponse struct {
 	Body          io.Reader
 	ContentType   string
 	ContentLength int64
 }
 
+func (response UnspecifiedContentType200VideoResponse) VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", response.ContentType)
+	if response.ContentLength != 0 {
+		w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength))
+	}
+	w.WriteHeader(200)
+
+	if closer, ok := response.Body.(io.ReadCloser); ok {
+		defer closer.Close()
+	}
+	_, err := io.Copy(w, response.Body)
+	return err
+}
+
 type UnspecifiedContentType400Response = BadrequestResponse
 
+func (response UnspecifiedContentType400Response) VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type UnspecifiedContentType401Response struct {
 }
 
+func (response UnspecifiedContentType401Response) VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error {
+	w.WriteHeader(401)
+	return nil
+}
+
 type UnspecifiedContentType403Response struct {
 }
 
+func (response UnspecifiedContentType403Response) VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error {
+	w.WriteHeader(403)
+	return nil
+}
+
 type UnspecifiedContentTypedefaultResponse struct {
 	StatusCode int
 }
 
+func (response UnspecifiedContentTypedefaultResponse) VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 type URLEncodedExampleRequestObject struct {
 	Body *URLEncodedExampleFormdataRequestBody
 }
 
+type URLEncodedExampleResponseObject interface {
+	VisitURLEncodedExampleResponse(w http.ResponseWriter) error
+}
+
 type URLEncodedExample200FormdataResponse Example
 
+func (response URLEncodedExample200FormdataResponse) VisitURLEncodedExampleResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
+	w.WriteHeader(200)
+
+	if form, err := runtime.MarshalForm(response, nil); err != nil {
+		return err
+	} else {
+		_, err := w.Write([]byte(form.Encode()))
+		return err
+	}
+}
+
 type URLEncodedExample400Response = BadrequestResponse
 
+func (response URLEncodedExample400Response) VisitURLEncodedExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type URLEncodedExampledefaultResponse struct {
 	StatusCode int
 }
 
+func (response URLEncodedExampledefaultResponse) VisitURLEncodedExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 type HeadersExampleRequestObject struct {
 	Params HeadersExampleParams
 	Body   *HeadersExampleJSONRequestBody
 }
 
+type HeadersExampleResponseObject interface {
+	VisitHeadersExampleResponse(w http.ResponseWriter) error
+}
+
 type HeadersExample200ResponseHeaders struct {
 	Header1 string
 	Header2 int
@@ -378,48 +609,63 @@ type HeadersExample200JSONResponse struct {
 	Headers HeadersExample200ResponseHeaders
 }
 
-func (t HeadersExample200JSONResponse) MarshalJSON() ([]byte, error) {
-	return json.Marshal(t.Body)
+func (response HeadersExample200JSONResponse) VisitHeadersExampleResponse(w http.ResponseWriter) error {
+	w.Header().Set("header1", fmt.Sprint(response.Headers.Header1))
+	w.Header().Set("header2", fmt.Sprint(response.Headers.Header2))
+	w.Header().Set("Content-Type", "application/json")
+	w.WriteHeader(200)
+
+	return json.NewEncoder(w).Encode(response.Body)
 }
 
 type HeadersExample400Response = BadrequestResponse
 
+func (response HeadersExample400Response) VisitHeadersExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type HeadersExampledefaultResponse struct {
 	StatusCode int
 }
 
+func (response HeadersExampledefaultResponse) VisitHeadersExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 // StrictServerInterface represents all server handlers.
 type StrictServerInterface interface {
 
 	// (POST /json)
-	JSONExample(ctx context.Context, request JSONExampleRequestObject) interface{}
+	JSONExample(ctx context.Context, request JSONExampleRequestObject) (JSONExampleResponseObject, error)
 
 	// (POST /multipart)
-	MultipartExample(ctx context.Context, request MultipartExampleRequestObject) interface{}
+	MultipartExample(ctx context.Context, request MultipartExampleRequestObject) (MultipartExampleResponseObject, error)
 
 	// (POST /multiple)
-	MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) interface{}
+	MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) (MultipleRequestAndResponseTypesResponseObject, error)
 
 	// (POST /reusable-responses)
-	ReusableResponses(ctx context.Context, request ReusableResponsesRequestObject) interface{}
+	ReusableResponses(ctx context.Context, request ReusableResponsesRequestObject) (ReusableResponsesResponseObject, error)
 
 	// (POST /text)
-	TextExample(ctx context.Context, request TextExampleRequestObject) interface{}
+	TextExample(ctx context.Context, request TextExampleRequestObject) (TextExampleResponseObject, error)
 
 	// (POST /unknown)
-	UnknownExample(ctx context.Context, request UnknownExampleRequestObject) interface{}
+	UnknownExample(ctx context.Context, request UnknownExampleRequestObject) (UnknownExampleResponseObject, error)
 
 	// (POST /unspecified-content-type)
-	UnspecifiedContentType(ctx context.Context, request UnspecifiedContentTypeRequestObject) interface{}
+	UnspecifiedContentType(ctx context.Context, request UnspecifiedContentTypeRequestObject) (UnspecifiedContentTypeResponseObject, error)
 
 	// (POST /urlencoded)
-	URLEncodedExample(ctx context.Context, request URLEncodedExampleRequestObject) interface{}
+	URLEncodedExample(ctx context.Context, request URLEncodedExampleRequestObject) (URLEncodedExampleResponseObject, error)
 
 	// (POST /with-headers)
-	HeadersExample(ctx context.Context, request HeadersExampleRequestObject) interface{}
+	HeadersExample(ctx context.Context, request HeadersExampleRequestObject) (HeadersExampleResponseObject, error)
 }
 
-type StrictHandlerFunc func(ctx echo.Context, args interface{}) interface{}
+type StrictHandlerFunc func(ctx echo.Context, args interface{}) (interface{}, error)
 
 type StrictMiddlewareFunc func(f StrictHandlerFunc, operationID string) StrictHandlerFunc
 
@@ -442,27 +688,21 @@ func (sh *strictHandler) JSONExample(ctx echo.Context) error {
 	}
 	request.Body = &body
 
-	handler := func(ctx echo.Context, request interface{}) interface{} {
+	handler := func(ctx echo.Context, request interface{}) (interface{}, error) {
 		return sh.ssi.JSONExample(ctx.Request().Context(), request.(JSONExampleRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "JSONExample")
 	}
 
-	response := handler(ctx, request)
+	response, err := handler(ctx, request)
 
-	switch v := response.(type) {
-	case JSONExample200JSONResponse:
-		return ctx.JSON(200, v)
-	case JSONExample400Response:
-		return ctx.NoContent(400)
-	case JSONExampledefaultResponse:
-		return ctx.NoContent(v.StatusCode)
-	case error:
-		return v
-	case nil:
-	default:
-		return fmt.Errorf("Unexpected response type: %T", v)
+	if err != nil {
+		return err
+	} else if validResponse, ok := response.(JSONExampleResponseObject); ok {
+		return validResponse.VisitJSONExampleResponse(ctx.Response())
+	} else if response != nil {
+		return fmt.Errorf("Unexpected response type: %T", response)
 	}
 	return nil
 }
@@ -477,32 +717,21 @@ func (sh *strictHandler) MultipartExample(ctx echo.Context) error {
 		request.Body = reader
 	}
 
-	handler := func(ctx echo.Context, request interface{}) interface{} {
+	handler := func(ctx echo.Context, request interface{}) (interface{}, error) {
 		return sh.ssi.MultipartExample(ctx.Request().Context(), request.(MultipartExampleRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "MultipartExample")
 	}
 
-	response := handler(ctx, request)
+	response, err := handler(ctx, request)
 
-	switch v := response.(type) {
-	case MultipartExample200MultipartResponse:
-		writer := multipart.NewWriter(ctx.Response())
-		ctx.Response().Header().Set("Content-Type", writer.FormDataContentType())
-		defer writer.Close()
-		if err := v(writer); err != nil {
-			return err
-		}
-	case MultipartExample400Response:
-		return ctx.NoContent(400)
-	case MultipartExampledefaultResponse:
-		return ctx.NoContent(v.StatusCode)
-	case error:
-		return v
-	case nil:
-	default:
-		return fmt.Errorf("Unexpected response type: %T", v)
+	if err != nil {
+		return err
+	} else if validResponse, ok := response.(MultipartExampleResponseObject); ok {
+		return validResponse.VisitMultipartExampleResponse(ctx.Response())
+	} else if response != nil {
+		return fmt.Errorf("Unexpected response type: %T", response)
 	}
 	return nil
 }
@@ -540,7 +769,7 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(ctx echo.Context) error
 		}
 	}
 	if strings.HasPrefix(ctx.Request().Header.Get("Content-Type"), "text/plain") {
-		data, err := ioutil.ReadAll(ctx.Request().Body)
+		data, err := io.ReadAll(ctx.Request().Body)
 		if err != nil {
 			return err
 		}
@@ -548,48 +777,21 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(ctx echo.Context) error
 		request.TextBody = &body
 	}
 
-	handler := func(ctx echo.Context, request interface{}) interface{} {
+	handler := func(ctx echo.Context, request interface{}) (interface{}, error) {
 		return sh.ssi.MultipleRequestAndResponseTypes(ctx.Request().Context(), request.(MultipleRequestAndResponseTypesRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "MultipleRequestAndResponseTypes")
 	}
 
-	response := handler(ctx, request)
+	response, err := handler(ctx, request)
 
-	switch v := response.(type) {
-	case MultipleRequestAndResponseTypes200JSONResponse:
-		return ctx.JSON(200, v)
-	case MultipleRequestAndResponseTypes200FormdataResponse:
-		if form, err := runtime.MarshalForm(v, nil); err != nil {
-			return err
-		} else {
-			return ctx.Blob(200, "application/x-www-form-urlencoded", []byte(form.Encode()))
-		}
-	case MultipleRequestAndResponseTypes200ImagepngResponse:
-		if v.ContentLength != 0 {
-			ctx.Response().Header().Set("Content-Length", fmt.Sprint(v.ContentLength))
-		}
-		if closer, ok := v.Body.(io.ReadCloser); ok {
-			defer closer.Close()
-		}
-		return ctx.Stream(200, "image/png", v.Body)
-	case MultipleRequestAndResponseTypes200MultipartResponse:
-		writer := multipart.NewWriter(ctx.Response())
-		ctx.Response().Header().Set("Content-Type", writer.FormDataContentType())
-		defer writer.Close()
-		if err := v(writer); err != nil {
-			return err
-		}
-	case MultipleRequestAndResponseTypes200TextResponse:
-		return ctx.Blob(200, "text/plain", []byte(v))
-	case MultipleRequestAndResponseTypes400Response:
-		return ctx.NoContent(400)
-	case error:
-		return v
-	case nil:
-	default:
-		return fmt.Errorf("Unexpected response type: %T", v)
+	if err != nil {
+		return err
+	} else if validResponse, ok := response.(MultipleRequestAndResponseTypesResponseObject); ok {
+		return validResponse.VisitMultipleRequestAndResponseTypesResponse(ctx.Response())
+	} else if response != nil {
+		return fmt.Errorf("Unexpected response type: %T", response)
 	}
 	return nil
 }
@@ -604,29 +806,21 @@ func (sh *strictHandler) ReusableResponses(ctx echo.Context) error {
 	}
 	request.Body = &body
 
-	handler := func(ctx echo.Context, request interface{}) interface{} {
+	handler := func(ctx echo.Context, request interface{}) (interface{}, error) {
 		return sh.ssi.ReusableResponses(ctx.Request().Context(), request.(ReusableResponsesRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "ReusableResponses")
 	}
 
-	response := handler(ctx, request)
+	response, err := handler(ctx, request)
 
-	switch v := response.(type) {
-	case ReusableResponses200JSONResponse:
-		ctx.Response().Header().Set("header1", fmt.Sprint(v.Headers.Header1))
-		ctx.Response().Header().Set("header2", fmt.Sprint(v.Headers.Header2))
-		return ctx.JSON(200, v)
-	case ReusableResponses400Response:
-		return ctx.NoContent(400)
-	case ReusableResponsesdefaultResponse:
-		return ctx.NoContent(v.StatusCode)
-	case error:
-		return v
-	case nil:
-	default:
-		return fmt.Errorf("Unexpected response type: %T", v)
+	if err != nil {
+		return err
+	} else if validResponse, ok := response.(ReusableResponsesResponseObject); ok {
+		return validResponse.VisitReusableResponsesResponse(ctx.Response())
+	} else if response != nil {
+		return fmt.Errorf("Unexpected response type: %T", response)
 	}
 	return nil
 }
@@ -635,34 +829,28 @@ func (sh *strictHandler) ReusableResponses(ctx echo.Context) error {
 func (sh *strictHandler) TextExample(ctx echo.Context) error {
 	var request TextExampleRequestObject
 
-	data, err := ioutil.ReadAll(ctx.Request().Body)
+	data, err := io.ReadAll(ctx.Request().Body)
 	if err != nil {
 		return err
 	}
 	body := TextExampleTextRequestBody(data)
 	request.Body = &body
 
-	handler := func(ctx echo.Context, request interface{}) interface{} {
+	handler := func(ctx echo.Context, request interface{}) (interface{}, error) {
 		return sh.ssi.TextExample(ctx.Request().Context(), request.(TextExampleRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "TextExample")
 	}
 
-	response := handler(ctx, request)
+	response, err := handler(ctx, request)
 
-	switch v := response.(type) {
-	case TextExample200TextResponse:
-		return ctx.Blob(200, "text/plain", []byte(v))
-	case TextExample400Response:
-		return ctx.NoContent(400)
-	case TextExampledefaultResponse:
-		return ctx.NoContent(v.StatusCode)
-	case error:
-		return v
-	case nil:
-	default:
-		return fmt.Errorf("Unexpected response type: %T", v)
+	if err != nil {
+		return err
+	} else if validResponse, ok := response.(TextExampleResponseObject); ok {
+		return validResponse.VisitTextExampleResponse(ctx.Response())
+	} else if response != nil {
+		return fmt.Errorf("Unexpected response type: %T", response)
 	}
 	return nil
 }
@@ -673,33 +861,21 @@ func (sh *strictHandler) UnknownExample(ctx echo.Context) error {
 
 	request.Body = ctx.Request().Body
 
-	handler := func(ctx echo.Context, request interface{}) interface{} {
+	handler := func(ctx echo.Context, request interface{}) (interface{}, error) {
 		return sh.ssi.UnknownExample(ctx.Request().Context(), request.(UnknownExampleRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "UnknownExample")
 	}
 
-	response := handler(ctx, request)
+	response, err := handler(ctx, request)
 
-	switch v := response.(type) {
-	case UnknownExample200Videomp4Response:
-		if v.ContentLength != 0 {
-			ctx.Response().Header().Set("Content-Length", fmt.Sprint(v.ContentLength))
-		}
-		if closer, ok := v.Body.(io.ReadCloser); ok {
-			defer closer.Close()
-		}
-		return ctx.Stream(200, "video/mp4", v.Body)
-	case UnknownExample400Response:
-		return ctx.NoContent(400)
-	case UnknownExampledefaultResponse:
-		return ctx.NoContent(v.StatusCode)
-	case error:
-		return v
-	case nil:
-	default:
-		return fmt.Errorf("Unexpected response type: %T", v)
+	if err != nil {
+		return err
+	} else if validResponse, ok := response.(UnknownExampleResponseObject); ok {
+		return validResponse.VisitUnknownExampleResponse(ctx.Response())
+	} else if response != nil {
+		return fmt.Errorf("Unexpected response type: %T", response)
 	}
 	return nil
 }
@@ -712,37 +888,21 @@ func (sh *strictHandler) UnspecifiedContentType(ctx echo.Context) error {
 
 	request.Body = ctx.Request().Body
 
-	handler := func(ctx echo.Context, request interface{}) interface{} {
+	handler := func(ctx echo.Context, request interface{}) (interface{}, error) {
 		return sh.ssi.UnspecifiedContentType(ctx.Request().Context(), request.(UnspecifiedContentTypeRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "UnspecifiedContentType")
 	}
 
-	response := handler(ctx, request)
+	response, err := handler(ctx, request)
 
-	switch v := response.(type) {
-	case UnspecifiedContentType200VideoResponse:
-		if v.ContentLength != 0 {
-			ctx.Response().Header().Set("Content-Length", fmt.Sprint(v.ContentLength))
-		}
-		if closer, ok := v.Body.(io.ReadCloser); ok {
-			defer closer.Close()
-		}
-		return ctx.Stream(200, v.ContentType, v.Body)
-	case UnspecifiedContentType400Response:
-		return ctx.NoContent(400)
-	case UnspecifiedContentType401Response:
-		return ctx.NoContent(401)
-	case UnspecifiedContentType403Response:
-		return ctx.NoContent(403)
-	case UnspecifiedContentTypedefaultResponse:
-		return ctx.NoContent(v.StatusCode)
-	case error:
-		return v
-	case nil:
-	default:
-		return fmt.Errorf("Unexpected response type: %T", v)
+	if err != nil {
+		return err
+	} else if validResponse, ok := response.(UnspecifiedContentTypeResponseObject); ok {
+		return validResponse.VisitUnspecifiedContentTypeResponse(ctx.Response())
+	} else if response != nil {
+		return fmt.Errorf("Unexpected response type: %T", response)
 	}
 	return nil
 }
@@ -761,31 +921,21 @@ func (sh *strictHandler) URLEncodedExample(ctx echo.Context) error {
 		return err
 	}
 
-	handler := func(ctx echo.Context, request interface{}) interface{} {
+	handler := func(ctx echo.Context, request interface{}) (interface{}, error) {
 		return sh.ssi.URLEncodedExample(ctx.Request().Context(), request.(URLEncodedExampleRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "URLEncodedExample")
 	}
 
-	response := handler(ctx, request)
+	response, err := handler(ctx, request)
 
-	switch v := response.(type) {
-	case URLEncodedExample200FormdataResponse:
-		if form, err := runtime.MarshalForm(v, nil); err != nil {
-			return err
-		} else {
-			return ctx.Blob(200, "application/x-www-form-urlencoded", []byte(form.Encode()))
-		}
-	case URLEncodedExample400Response:
-		return ctx.NoContent(400)
-	case URLEncodedExampledefaultResponse:
-		return ctx.NoContent(v.StatusCode)
-	case error:
-		return v
-	case nil:
-	default:
-		return fmt.Errorf("Unexpected response type: %T", v)
+	if err != nil {
+		return err
+	} else if validResponse, ok := response.(URLEncodedExampleResponseObject); ok {
+		return validResponse.VisitURLEncodedExampleResponse(ctx.Response())
+	} else if response != nil {
+		return fmt.Errorf("Unexpected response type: %T", response)
 	}
 	return nil
 }
@@ -802,29 +952,21 @@ func (sh *strictHandler) HeadersExample(ctx echo.Context, params HeadersExampleP
 	}
 	request.Body = &body
 
-	handler := func(ctx echo.Context, request interface{}) interface{} {
+	handler := func(ctx echo.Context, request interface{}) (interface{}, error) {
 		return sh.ssi.HeadersExample(ctx.Request().Context(), request.(HeadersExampleRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "HeadersExample")
 	}
 
-	response := handler(ctx, request)
-
-	switch v := response.(type) {
-	case HeadersExample200JSONResponse:
-		ctx.Response().Header().Set("header1", fmt.Sprint(v.Headers.Header1))
-		ctx.Response().Header().Set("header2", fmt.Sprint(v.Headers.Header2))
-		return ctx.JSON(200, v)
-	case HeadersExample400Response:
-		return ctx.NoContent(400)
-	case HeadersExampledefaultResponse:
-		return ctx.NoContent(v.StatusCode)
-	case error:
-		return v
-	case nil:
-	default:
-		return fmt.Errorf("Unexpected response type: %T", v)
+	response, err := handler(ctx, request)
+
+	if err != nil {
+		return err
+	} else if validResponse, ok := response.(HeadersExampleResponseObject); ok {
+		return validResponse.VisitHeadersExampleResponse(ctx.Response())
+	} else if response != nil {
+		return fmt.Errorf("Unexpected response type: %T", response)
 	}
 	return nil
 }
diff --git a/internal/test/strict-server/echo/server.go b/internal/test/strict-server/echo/server.go
index 876850a..748fc7d 100644
--- a/internal/test/strict-server/echo/server.go
+++ b/internal/test/strict-server/echo/server.go
@@ -12,11 +12,11 @@ import (
 type StrictServer struct {
 }
 
-func (s StrictServer) JSONExample(ctx context.Context, request JSONExampleRequestObject) interface{} {
-	return JSONExample200JSONResponse(*request.Body)
+func (s StrictServer) JSONExample(ctx context.Context, request JSONExampleRequestObject) (JSONExampleResponseObject, error) {
+	return JSONExample200JSONResponse(*request.Body), nil
 }
 
-func (s StrictServer) MultipartExample(ctx context.Context, request MultipartExampleRequestObject) interface{} {
+func (s StrictServer) MultipartExample(ctx context.Context, request MultipartExampleRequestObject) (MultipartExampleResponseObject, error) {
 	return MultipartExample200MultipartResponse(func(writer *multipart.Writer) error {
 		for {
 			part, err := request.Body.NextPart()
@@ -37,19 +37,19 @@ func (s StrictServer) MultipartExample(ctx context.Context, request MultipartExa
 				return err
 			}
 		}
-	})
+	}), nil
 }
 
-func (s StrictServer) MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) interface{} {
+func (s StrictServer) MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) (MultipleRequestAndResponseTypesResponseObject, error) {
 	switch {
 	case request.Body != nil:
-		return MultipleRequestAndResponseTypes200ImagepngResponse{Body: request.Body}
+		return MultipleRequestAndResponseTypes200ImagepngResponse{Body: request.Body}, nil
 	case request.JSONBody != nil:
-		return MultipleRequestAndResponseTypes200JSONResponse(*request.JSONBody)
+		return MultipleRequestAndResponseTypes200JSONResponse(*request.JSONBody), nil
 	case request.FormdataBody != nil:
-		return MultipleRequestAndResponseTypes200FormdataResponse(*request.FormdataBody)
+		return MultipleRequestAndResponseTypes200FormdataResponse(*request.FormdataBody), nil
 	case request.TextBody != nil:
-		return MultipleRequestAndResponseTypes200TextResponse(*request.TextBody)
+		return MultipleRequestAndResponseTypes200TextResponse(*request.TextBody), nil
 	case request.MultipartBody != nil:
 		return MultipleRequestAndResponseTypes200MultipartResponse(func(writer *multipart.Writer) error {
 			for {
@@ -71,32 +71,32 @@ func (s StrictServer) MultipleRequestAndResponseTypes(ctx context.Context, reque
 					return err
 				}
 			}
-		})
+		}), nil
 	default:
-		return MultipleRequestAndResponseTypes400Response{}
+		return MultipleRequestAndResponseTypes400Response{}, nil
 	}
 }
 
-func (s StrictServer) TextExample(ctx context.Context, request TextExampleRequestObject) interface{} {
-	return TextExample200TextResponse(*request.Body)
+func (s StrictServer) TextExample(ctx context.Context, request TextExampleRequestObject) (TextExampleResponseObject, error) {
+	return TextExample200TextResponse(*request.Body), nil
 }
 
-func (s StrictServer) UnknownExample(ctx context.Context, request UnknownExampleRequestObject) interface{} {
-	return UnknownExample200Videomp4Response{Body: request.Body}
+func (s StrictServer) UnknownExample(ctx context.Context, request UnknownExampleRequestObject) (UnknownExampleResponseObject, error) {
+	return UnknownExample200Videomp4Response{Body: request.Body}, nil
 }
 
-func (s StrictServer) UnspecifiedContentType(ctx context.Context, request UnspecifiedContentTypeRequestObject) interface{} {
-	return UnspecifiedContentType200VideoResponse{Body: request.Body, ContentType: request.ContentType}
+func (s StrictServer) UnspecifiedContentType(ctx context.Context, request UnspecifiedContentTypeRequestObject) (UnspecifiedContentTypeResponseObject, error) {
+	return UnspecifiedContentType200VideoResponse{Body: request.Body, ContentType: request.ContentType}, nil
 }
 
-func (s StrictServer) URLEncodedExample(ctx context.Context, request URLEncodedExampleRequestObject) interface{} {
-	return URLEncodedExample200FormdataResponse(*request.Body)
+func (s StrictServer) URLEncodedExample(ctx context.Context, request URLEncodedExampleRequestObject) (URLEncodedExampleResponseObject, error) {
+	return URLEncodedExample200FormdataResponse(*request.Body), nil
 }
 
-func (s StrictServer) HeadersExample(ctx context.Context, request HeadersExampleRequestObject) interface{} {
-	return HeadersExample200JSONResponse{Body: Example(*request.Body), Headers: HeadersExample200ResponseHeaders{Header1: request.Params.Header1, Header2: *request.Params.Header2}}
+func (s StrictServer) HeadersExample(ctx context.Context, request HeadersExampleRequestObject) (HeadersExampleResponseObject, error) {
+	return HeadersExample200JSONResponse{Body: Example(*request.Body), Headers: HeadersExample200ResponseHeaders{Header1: request.Params.Header1, Header2: *request.Params.Header2}}, nil
 }
 
-func (s StrictServer) ReusableResponses(ctx context.Context, request ReusableResponsesRequestObject) interface{} {
-	return ReusableResponses200JSONResponse{Body: *request.Body}
+func (s StrictServer) ReusableResponses(ctx context.Context, request ReusableResponsesRequestObject) (ReusableResponsesResponseObject, error) {
+	return ReusableResponses200JSONResponse{Body: *request.Body}, nil
 }
diff --git a/internal/test/strict-server/gin/server.gen.go b/internal/test/strict-server/gin/server.gen.go
index 56e7552..5192a0d 100644
--- a/internal/test/strict-server/gin/server.gen.go
+++ b/internal/test/strict-server/gin/server.gen.go
@@ -11,7 +11,6 @@ import (
 	"encoding/json"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"mime/multipart"
 	"net/http"
 	"net/url"
@@ -252,38 +251,74 @@ type ReusableresponseJSONResponse struct {
 	Headers ReusableresponseResponseHeaders
 }
 
-func (t ReusableresponseJSONResponse) MarshalJSON() ([]byte, error) {
-	return json.Marshal(t.Body)
-}
-
 type JSONExampleRequestObject struct {
 	Body *JSONExampleJSONRequestBody
 }
 
+type JSONExampleResponseObject interface {
+	VisitJSONExampleResponse(w http.ResponseWriter) error
+}
+
 type JSONExample200JSONResponse Example
 
-func (t JSONExample200JSONResponse) MarshalJSON() ([]byte, error) {
-	return json.Marshal((Example)(t))
+func (response JSONExample200JSONResponse) VisitJSONExampleResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "application/json")
+	w.WriteHeader(200)
+
+	return json.NewEncoder(w).Encode(response)
 }
 
 type JSONExample400Response = BadrequestResponse
 
+func (response JSONExample400Response) VisitJSONExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type JSONExampledefaultResponse struct {
 	StatusCode int
 }
 
+func (response JSONExampledefaultResponse) VisitJSONExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 type MultipartExampleRequestObject struct {
 	Body *multipart.Reader
 }
 
+type MultipartExampleResponseObject interface {
+	VisitMultipartExampleResponse(w http.ResponseWriter) error
+}
+
 type MultipartExample200MultipartResponse func(writer *multipart.Writer) error
 
+func (response MultipartExample200MultipartResponse) VisitMultipartExampleResponse(w http.ResponseWriter) error {
+	writer := multipart.NewWriter(w)
+	w.Header().Set("Content-Type", writer.FormDataContentType())
+	w.WriteHeader(200)
+
+	defer writer.Close()
+	return response(writer)
+}
+
 type MultipartExample400Response = BadrequestResponse
 
+func (response MultipartExample400Response) VisitMultipartExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type MultipartExampledefaultResponse struct {
 	StatusCode int
 }
 
+func (response MultipartExampledefaultResponse) VisitMultipartExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 type MultipleRequestAndResponseTypesRequestObject struct {
 	JSONBody      *MultipleRequestAndResponseTypesJSONRequestBody
 	FormdataBody  *MultipleRequestAndResponseTypesFormdataRequestBody
@@ -292,104 +327,300 @@ type MultipleRequestAndResponseTypesRequestObject struct {
 	TextBody      *MultipleRequestAndResponseTypesTextRequestBody
 }
 
+type MultipleRequestAndResponseTypesResponseObject interface {
+	VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error
+}
+
 type MultipleRequestAndResponseTypes200JSONResponse Example
 
-func (t MultipleRequestAndResponseTypes200JSONResponse) MarshalJSON() ([]byte, error) {
-	return json.Marshal((Example)(t))
+func (response MultipleRequestAndResponseTypes200JSONResponse) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "application/json")
+	w.WriteHeader(200)
+
+	return json.NewEncoder(w).Encode(response)
 }
 
 type MultipleRequestAndResponseTypes200FormdataResponse Example
 
+func (response MultipleRequestAndResponseTypes200FormdataResponse) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
+	w.WriteHeader(200)
+
+	if form, err := runtime.MarshalForm(response, nil); err != nil {
+		return err
+	} else {
+		_, err := w.Write([]byte(form.Encode()))
+		return err
+	}
+}
+
 type MultipleRequestAndResponseTypes200ImagepngResponse struct {
 	Body          io.Reader
 	ContentLength int64
 }
 
+func (response MultipleRequestAndResponseTypes200ImagepngResponse) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "image/png")
+	if response.ContentLength != 0 {
+		w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength))
+	}
+	w.WriteHeader(200)
+
+	if closer, ok := response.Body.(io.ReadCloser); ok {
+		defer closer.Close()
+	}
+	_, err := io.Copy(w, response.Body)
+	return err
+}
+
 type MultipleRequestAndResponseTypes200MultipartResponse func(writer *multipart.Writer) error
 
+func (response MultipleRequestAndResponseTypes200MultipartResponse) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+	writer := multipart.NewWriter(w)
+	w.Header().Set("Content-Type", writer.FormDataContentType())
+	w.WriteHeader(200)
+
+	defer writer.Close()
+	return response(writer)
+}
+
 type MultipleRequestAndResponseTypes200TextResponse string
 
+func (response MultipleRequestAndResponseTypes200TextResponse) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "text/plain")
+	w.WriteHeader(200)
+
+	_, err := w.Write([]byte(response))
+	return err
+}
+
 type MultipleRequestAndResponseTypes400Response = BadrequestResponse
 
+func (response MultipleRequestAndResponseTypes400Response) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type ReusableResponsesRequestObject struct {
 	Body *ReusableResponsesJSONRequestBody
 }
 
+type ReusableResponsesResponseObject interface {
+	VisitReusableResponsesResponse(w http.ResponseWriter) error
+}
+
 type ReusableResponses200JSONResponse = ReusableresponseJSONResponse
 
+func (response ReusableResponses200JSONResponse) VisitReusableResponsesResponse(w http.ResponseWriter) error {
+	w.Header().Set("header1", fmt.Sprint(response.Headers.Header1))
+	w.Header().Set("header2", fmt.Sprint(response.Headers.Header2))
+	w.Header().Set("Content-Type", "application/json")
+	w.WriteHeader(200)
+
+	return json.NewEncoder(w).Encode(response.Body)
+}
+
 type ReusableResponses400Response = BadrequestResponse
 
+func (response ReusableResponses400Response) VisitReusableResponsesResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type ReusableResponsesdefaultResponse struct {
 	StatusCode int
 }
 
+func (response ReusableResponsesdefaultResponse) VisitReusableResponsesResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 type TextExampleRequestObject struct {
 	Body *TextExampleTextRequestBody
 }
 
+type TextExampleResponseObject interface {
+	VisitTextExampleResponse(w http.ResponseWriter) error
+}
+
 type TextExample200TextResponse string
 
+func (response TextExample200TextResponse) VisitTextExampleResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "text/plain")
+	w.WriteHeader(200)
+
+	_, err := w.Write([]byte(response))
+	return err
+}
+
 type TextExample400Response = BadrequestResponse
 
+func (response TextExample400Response) VisitTextExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type TextExampledefaultResponse struct {
 	StatusCode int
 }
 
+func (response TextExampledefaultResponse) VisitTextExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 type UnknownExampleRequestObject struct {
 	Body io.Reader
 }
 
+type UnknownExampleResponseObject interface {
+	VisitUnknownExampleResponse(w http.ResponseWriter) error
+}
+
 type UnknownExample200Videomp4Response struct {
 	Body          io.Reader
 	ContentLength int64
 }
 
+func (response UnknownExample200Videomp4Response) VisitUnknownExampleResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "video/mp4")
+	if response.ContentLength != 0 {
+		w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength))
+	}
+	w.WriteHeader(200)
+
+	if closer, ok := response.Body.(io.ReadCloser); ok {
+		defer closer.Close()
+	}
+	_, err := io.Copy(w, response.Body)
+	return err
+}
+
 type UnknownExample400Response = BadrequestResponse
 
+func (response UnknownExample400Response) VisitUnknownExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type UnknownExampledefaultResponse struct {
 	StatusCode int
 }
 
+func (response UnknownExampledefaultResponse) VisitUnknownExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 type UnspecifiedContentTypeRequestObject struct {
 	ContentType string
 	Body        io.Reader
 }
 
+type UnspecifiedContentTypeResponseObject interface {
+	VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error
+}
+
 type UnspecifiedContentType200VideoResponse struct {
 	Body          io.Reader
 	ContentType   string
 	ContentLength int64
 }
 
+func (response UnspecifiedContentType200VideoResponse) VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", response.ContentType)
+	if response.ContentLength != 0 {
+		w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength))
+	}
+	w.WriteHeader(200)
+
+	if closer, ok := response.Body.(io.ReadCloser); ok {
+		defer closer.Close()
+	}
+	_, err := io.Copy(w, response.Body)
+	return err
+}
+
 type UnspecifiedContentType400Response = BadrequestResponse
 
+func (response UnspecifiedContentType400Response) VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type UnspecifiedContentType401Response struct {
 }
 
+func (response UnspecifiedContentType401Response) VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error {
+	w.WriteHeader(401)
+	return nil
+}
+
 type UnspecifiedContentType403Response struct {
 }
 
+func (response UnspecifiedContentType403Response) VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error {
+	w.WriteHeader(403)
+	return nil
+}
+
 type UnspecifiedContentTypedefaultResponse struct {
 	StatusCode int
 }
 
+func (response UnspecifiedContentTypedefaultResponse) VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 type URLEncodedExampleRequestObject struct {
 	Body *URLEncodedExampleFormdataRequestBody
 }
 
+type URLEncodedExampleResponseObject interface {
+	VisitURLEncodedExampleResponse(w http.ResponseWriter) error
+}
+
 type URLEncodedExample200FormdataResponse Example
 
+func (response URLEncodedExample200FormdataResponse) VisitURLEncodedExampleResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
+	w.WriteHeader(200)
+
+	if form, err := runtime.MarshalForm(response, nil); err != nil {
+		return err
+	} else {
+		_, err := w.Write([]byte(form.Encode()))
+		return err
+	}
+}
+
 type URLEncodedExample400Response = BadrequestResponse
 
+func (response URLEncodedExample400Response) VisitURLEncodedExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type URLEncodedExampledefaultResponse struct {
 	StatusCode int
 }
 
+func (response URLEncodedExampledefaultResponse) VisitURLEncodedExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 type HeadersExampleRequestObject struct {
 	Params HeadersExampleParams
 	Body   *HeadersExampleJSONRequestBody
 }
 
+type HeadersExampleResponseObject interface {
+	VisitHeadersExampleResponse(w http.ResponseWriter) error
+}
+
 type HeadersExample200ResponseHeaders struct {
 	Header1 string
 	Header2 int
@@ -400,48 +631,63 @@ type HeadersExample200JSONResponse struct {
 	Headers HeadersExample200ResponseHeaders
 }
 
-func (t HeadersExample200JSONResponse) MarshalJSON() ([]byte, error) {
-	return json.Marshal(t.Body)
+func (response HeadersExample200JSONResponse) VisitHeadersExampleResponse(w http.ResponseWriter) error {
+	w.Header().Set("header1", fmt.Sprint(response.Headers.Header1))
+	w.Header().Set("header2", fmt.Sprint(response.Headers.Header2))
+	w.Header().Set("Content-Type", "application/json")
+	w.WriteHeader(200)
+
+	return json.NewEncoder(w).Encode(response.Body)
 }
 
 type HeadersExample400Response = BadrequestResponse
 
+func (response HeadersExample400Response) VisitHeadersExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(400)
+	return nil
+}
+
 type HeadersExampledefaultResponse struct {
 	StatusCode int
 }
 
+func (response HeadersExampledefaultResponse) VisitHeadersExampleResponse(w http.ResponseWriter) error {
+	w.WriteHeader(response.StatusCode)
+	return nil
+}
+
 // StrictServerInterface represents all server handlers.
 type StrictServerInterface interface {
 
 	// (POST /json)
-	JSONExample(ctx context.Context, request JSONExampleRequestObject) interface{}
+	JSONExample(ctx context.Context, request JSONExampleRequestObject) (JSONExampleResponseObject, error)
 
 	// (POST /multipart)
-	MultipartExample(ctx context.Context, request MultipartExampleRequestObject) interface{}
+	MultipartExample(ctx context.Context, request MultipartExampleRequestObject) (MultipartExampleResponseObject, error)
 
 	// (POST /multiple)
-	MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) interface{}
+	MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) (MultipleRequestAndResponseTypesResponseObject, error)
 
 	// (POST /reusable-responses)
-	ReusableResponses(ctx context.Context, request ReusableResponsesRequestObject) interface{}
+	ReusableResponses(ctx context.Context, request ReusableResponsesRequestObject) (ReusableResponsesResponseObject, error)
 
 	// (POST /text)
-	TextExample(ctx context.Context, request TextExampleRequestObject) interface{}
+	TextExample(ctx context.Context, request TextExampleRequestObject) (TextExampleResponseObject, error)
 
 	// (POST /unknown)
-	UnknownExample(ctx context.Context, request UnknownExampleRequestObject) interface{}
+	UnknownExample(ctx context.Context, request UnknownExampleRequestObject) (UnknownExampleResponseObject, error)
 
 	// (POST /unspecified-content-type)
-	UnspecifiedContentType(ctx context.Context, request UnspecifiedContentTypeRequestObject) interface{}
+	UnspecifiedContentType(ctx context.Context, request UnspecifiedContentTypeRequestObject) (UnspecifiedContentTypeResponseObject, error)
 
 	// (POST /urlencoded)
-	URLEncodedExample(ctx context.Context, request URLEncodedExampleRequestObject) interface{}
+	URLEncodedExample(ctx context.Context, request URLEncodedExampleRequestObject) (URLEncodedExampleResponseObject, error)
 
 	// (POST /with-headers)
-	HeadersExample(ctx context.Context, request HeadersExampleRequestObject) interface{}
+	HeadersExample(ctx context.Context, request HeadersExampleRequestObject) (HeadersExampleResponseObject, error)
 }
 
-type StrictHandlerFunc func(ctx *gin.Context, args interface{}) interface{}
+type StrictHandlerFunc func(ctx *gin.Context, args interface{}) (interface{}, error)
 
 type StrictMiddlewareFunc func(f StrictHandlerFunc, operationID string) StrictHandlerFunc
 
@@ -465,27 +711,23 @@ func (sh *strictHandler) JSONExample(ctx *gin.Context) {
 	}
 	request.Body = &body
 
-	handler := func(ctx *gin.Context, request interface{}) interface{} {
+	handler := func(ctx *gin.Context, request interface{}) (interface{}, error) {
 		return sh.ssi.JSONExample(ctx, request.(JSONExampleRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "JSONExample")
 	}
 
-	response := handler(ctx, request)
+	response, err := handler(ctx, request)
 
-	switch v := response.(type) {
-	case JSONExample200JSONResponse:
-		ctx.JSON(200, v)
-	case JSONExample400Response:
-		ctx.Status(400)
-	case JSONExampledefaultResponse:
-		ctx.Status(v.StatusCode)
-	case error:
-		ctx.Error(v)
-	case nil:
-	default:
-		ctx.Error(fmt.Errorf("Unexpected response type: %T", v))
+	if err != nil {
+		ctx.Error(err)
+	} else if validResponse, ok := response.(JSONExampleResponseObject); ok {
+		if err := validResponse.VisitJSONExampleResponse(ctx.Writer); err != nil {
+			ctx.Error(err)
+		}
+	} else if response != nil {
+		ctx.Error(fmt.Errorf("Unexpected response type: %T", response))
 	}
 }
 
@@ -500,32 +742,23 @@ func (sh *strictHandler) MultipartExample(ctx *gin.Context) {
 		return
 	}
 
-	handler := func(ctx *gin.Context, request interface{}) interface{} {
+	handler := func(ctx *gin.Context, request interface{}) (interface{}, error) {
 		return sh.ssi.MultipartExample(ctx, request.(MultipartExampleRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "MultipartExample")
 	}
 
-	response := handler(ctx, request)
+	response, err := handler(ctx, request)
 
-	switch v := response.(type) {
-	case MultipartExample200MultipartResponse:
-		writer := multipart.NewWriter(ctx.Writer)
-		ctx.Writer.Header().Set("Content-Type", writer.FormDataContentType())
-		defer writer.Close()
-		if err := v(writer); err != nil {
+	if err != nil {
+		ctx.Error(err)
+	} else if validResponse, ok := response.(MultipartExampleResponseObject); ok {
+		if err := validResponse.VisitMultipartExampleResponse(ctx.Writer); err != nil {
 			ctx.Error(err)
 		}
-	case MultipartExample400Response:
-		ctx.Status(400)
-	case MultipartExampledefaultResponse:
-		ctx.Status(v.StatusCode)
-	case error:
-		ctx.Error(v)
-	case nil:
-	default:
-		ctx.Error(fmt.Errorf("Unexpected response type: %T", v))
+	} else if response != nil {
+		ctx.Error(fmt.Errorf("Unexpected response type: %T", response))
 	}
 }
 
@@ -565,7 +798,7 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(ctx *gin.Context) {
 		}
 	}
 	if strings.HasPrefix(ctx.GetHeader("Content-Type"), "text/plain") {
-		data, err := ioutil.ReadAll(ctx.Request.Body)
+		data, err := io.ReadAll(ctx.Request.Body)
 		if err != nil {
 			ctx.Error(err)
 			return
@@ -574,45 +807,23 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(ctx *gin.Context) {
 		request.TextBody = &body
 	}
 
-	handler := func(ctx *gin.Context, request interface{}) interface{} {
+	handler := func(ctx *gin.Context, request interface{}) (interface{}, error) {
 		return sh.ssi.MultipleRequestAndResponseTypes(ctx, request.(MultipleRequestAndResponseTypesRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "MultipleRequestAndResponseTypes")
 	}
 
-	response := handler(ctx, request)
+	response, err := handler(ctx, request)
 
-	switch v := response.(type) {
-	case MultipleRequestAndResponseTypes200JSONResponse:
-		ctx.JSON(200, v)
-	case MultipleRequestAndResponseTypes200FormdataResponse:
-		if form, err := runtime.MarshalForm(v, nil); err != nil {
-			ctx.Error(err)
-		} else {
-			ctx.Data(200, "application/x-www-form-urlencoded", []byte(form.Encode()))
-		}
-	case MultipleRequestAndResponseTypes200ImagepngResponse:
-		if closer, ok := v.Body.(io.ReadCloser); ok {
-			defer closer.Close()
-		}
-		ctx.DataFromReader(200, v.ContentLength, "image/png", v.Body, nil)
-	case MultipleRequestAndResponseTypes200MultipartResponse:
-		writer := multipart.NewWriter(ctx.Writer)
-		ctx.Writer.Header().Set("Content-Type", writer.FormDataContentType())
-		defer writer.Close()
-		if err := v(writer); err != nil {
+	if err != nil {
+		ctx.Error(err)
+	} else if validResponse, ok := response.(MultipleRequestAndResponseTypesResponseObject); ok {
+		if err := validResponse.VisitMultipleRequestAndResponseTypesResponse(ctx.Writer); err != nil {
 			ctx.Error(err)
 		}
-	case MultipleRequestAndResponseTypes200TextResponse:
-		ctx.Data(200, "text/plain", []byte(v))
-	case MultipleRequestAndResponseTypes400Response:
-		ctx.Status(400)
-	case error:
-		ctx.Error(v)
-	case nil:
-	default:
-		ctx.Error(fmt.Errorf("Unexpected response type: %T", v))
+	} else if response != nil {
+		ctx.Error(fmt.Errorf("Unexpected response type: %T", response))
 	}
 }
 
@@ -627,29 +838,23 @@ func (sh *strictHandler) ReusableResponses(ctx *gin.Context) {
 	}
 	request.Body = &body
 
-	handler := func(ctx *gin.Context, request interface{}) interface{} {
+	handler := func(ctx *gin.Context, request interface{}) (interface{}, error) {
 		return sh.ssi.ReusableResponses(ctx, request.(ReusableResponsesRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "ReusableResponses")
 	}
 
-	response := handler(ctx, request)
+	response, err := handler(ctx, request)
 
-	switch v := response.(type) {
-	case ReusableResponses200JSONResponse:
-		ctx.Header("header1", fmt.Sprint(v.Headers.Header1))
-		ctx.Header("header2", fmt.Sprint(v.Headers.Header2))
-		ctx.JSON(200, v)
-	case ReusableResponses400Response:
-		ctx.Status(400)
-	case ReusableResponsesdefaultResponse:
-		ctx.Status(v.StatusCode)
-	case error:
-		ctx.Error(v)
-	case nil:
-	default:
-		ctx.Error(fmt.Errorf("Unexpected response type: %T", v))
+	if err != nil {
+		ctx.Error(err)
+	} else if validResponse, ok := response.(ReusableResponsesResponseObject); ok {
+		if err := validResponse.VisitReusableResponsesResponse(ctx.Writer); err != nil {
+			ctx.Error(err)
+		}
+	} else if response != nil {
+		ctx.Error(fmt.Errorf("Unexpected response type: %T", response))
 	}
 }
 
@@ -657,7 +862,7 @@ func (sh *strictHandler) ReusableResponses(ctx *gin.Context) {
 func (sh *strictHandler) TextExample(ctx *gin.Context) {
 	var request TextExampleRequestObject
 
-	data, err := ioutil.ReadAll(ctx.Request.Body)
+	data, err := io.ReadAll(ctx.Request.Body)
 	if err != nil {
 		ctx.Error(err)
 		return
@@ -665,27 +870,23 @@ func (sh *strictHandler) TextExample(ctx *gin.Context) {
 	body := TextExampleTextRequestBody(data)
 	request.Body = &body
 
-	handler := func(ctx *gin.Context, request interface{}) interface{} {
+	handler := func(ctx *gin.Context, request interface{}) (interface{}, error) {
 		return sh.ssi.TextExample(ctx, request.(TextExampleRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "TextExample")
 	}
 
-	response := handler(ctx, request)
+	response, err := handler(ctx, request)
 
-	switch v := response.(type) {
-	case TextExample200TextResponse:
-		ctx.Data(200, "text/plain", []byte(v))
-	case TextExample400Response:
-		ctx.Status(400)
-	case TextExampledefaultResponse:
-		ctx.Status(v.StatusCode)
-	case error:
-		ctx.Error(v)
-	case nil:
-	default:
-		ctx.Error(fmt.Errorf("Unexpected response type: %T", v))
+	if err != nil {
+		ctx.Error(err)
+	} else if validResponse, ok := response.(TextExampleResponseObject); ok {
+		if err := validResponse.VisitTextExampleResponse(ctx.Writer); err != nil {
+			ctx.Error(err)
+		}
+	} else if response != nil {
+		ctx.Error(fmt.Errorf("Unexpected response type: %T", response))
 	}
 }
 
@@ -695,30 +896,23 @@ func (sh *strictHandler) UnknownExample(ctx *gin.Context) {
 
 	request.Body = ctx.Request.Body
 
-	handler := func(ctx *gin.Context, request interface{}) interface{} {
+	handler := func(ctx *gin.Context, request interface{}) (interface{}, error) {
 		return sh.ssi.UnknownExample(ctx, request.(UnknownExampleRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "UnknownExample")
 	}
 
-	response := handler(ctx, request)
+	response, err := handler(ctx, request)
 
-	switch v := response.(type) {
-	case UnknownExample200Videomp4Response:
-		if closer, ok := v.Body.(io.ReadCloser); ok {
-			defer closer.Close()
+	if err != nil {
+		ctx.Error(err)
+	} else if validResponse, ok := response.(UnknownExampleResponseObject); ok {
+		if err := validResponse.VisitUnknownExampleResponse(ctx.Writer); err != nil {
+			ctx.Error(err)
 		}
-		ctx.DataFromReader(200, v.ContentLength, "video/mp4", v.Body, nil)
-	case UnknownExample400Response:
-		ctx.Status(400)
-	case UnknownExampledefaultResponse:
-		ctx.Status(v.StatusCode)
-	case error:
-		ctx.Error(v)
-	case nil:
-	default:
-		ctx.Error(fmt.Errorf("Unexpected response type: %T", v))
+	} else if response != nil {
+		ctx.Error(fmt.Errorf("Unexpected response type: %T", response))
 	}
 }
 
@@ -730,34 +924,23 @@ func (sh *strictHandler) UnspecifiedContentType(ctx *gin.Context) {
 
 	request.Body = ctx.Request.Body
 
-	handler := func(ctx *gin.Context, request interface{}) interface{} {
+	handler := func(ctx *gin.Context, request interface{}) (interface{}, error) {
 		return sh.ssi.UnspecifiedContentType(ctx, request.(UnspecifiedContentTypeRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "UnspecifiedContentType")
 	}
 
-	response := handler(ctx, request)
+	response, err := handler(ctx, request)
 
-	switch v := response.(type) {
-	case UnspecifiedContentType200VideoResponse:
-		if closer, ok := v.Body.(io.ReadCloser); ok {
-			defer closer.Close()
+	if err != nil {
+		ctx.Error(err)
+	} else if validResponse, ok := response.(UnspecifiedContentTypeResponseObject); ok {
+		if err := validResponse.VisitUnspecifiedContentTypeResponse(ctx.Writer); err != nil {
+			ctx.Error(err)
 		}
-		ctx.DataFromReader(200, v.ContentLength, v.ContentType, v.Body, nil)
-	case UnspecifiedContentType400Response:
-		ctx.Status(400)
-	case UnspecifiedContentType401Response:
-		ctx.Status(401)
-	case UnspecifiedContentType403Response:
-		ctx.Status(403)
-	case UnspecifiedContentTypedefaultResponse:
-		ctx.Status(v.StatusCode)
-	case error:
-		ctx.Error(v)
-	case nil:
-	default:
-		ctx.Error(fmt.Errorf("Unexpected response type: %T", v))
+	} else if response != nil {
+		ctx.Error(fmt.Errorf("Unexpected response type: %T", response))
 	}
 }
 
@@ -776,31 +959,23 @@ func (sh *strictHandler) URLEncodedExample(ctx *gin.Context) {
 	}
 	request.Body = &body
 
-	handler := func(ctx *gin.Context, request interface{}) interface{} {
+	handler := func(ctx *gin.Context, request interface{}) (interface{}, error) {
 		return sh.ssi.URLEncodedExample(ctx, request.(URLEncodedExampleRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "URLEncodedExample")
 	}
 
-	response := handler(ctx, request)
+	response, err := handler(ctx, request)
 
-	switch v := response.(type) {
-	case URLEncodedExample200FormdataResponse:
-		if form, err := runtime.MarshalForm(v, nil); err != nil {
+	if err != nil {
+		ctx.Error(err)
+	} else if validResponse, ok := response.(URLEncodedExampleResponseObject); ok {
+		if err := validResponse.VisitURLEncodedExampleResponse(ctx.Writer); err != nil {
 			ctx.Error(err)
-		} else {
-			ctx.Data(200, "application/x-www-form-urlencoded", []byte(form.Encode()))
 		}
-	case URLEncodedExample400Response:
-		ctx.Status(400)
-	case URLEncodedExampledefaultResponse:
-		ctx.Status(v.StatusCode)
-	case error:
-		ctx.Error(v)
-	case nil:
-	default:
-		ctx.Error(fmt.Errorf("Unexpected response type: %T", v))
+	} else if response != nil {
+		ctx.Error(fmt.Errorf("Unexpected response type: %T", response))
 	}
 }
 
@@ -817,29 +992,23 @@ func (sh *strictHandler) HeadersExample(ctx *gin.Context, params HeadersExampleP
 	}
 	request.Body = &body
 
-	handler := func(ctx *gin.Context, request interface{}) interface{} {
+	handler := func(ctx *gin.Context, request interface{}) (interface{}, error) {
 		return sh.ssi.HeadersExample(ctx, request.(HeadersExampleRequestObject))
 	}
 	for _, middleware := range sh.middlewares {
 		handler = middleware(handler, "HeadersExample")
 	}
 
-	response := handler(ctx, request)
-
-	switch v := response.(type) {
-	case HeadersExample200JSONResponse:
-		ctx.Header("header1", fmt.Sprint(v.Headers.Header1))
-		ctx.Header("header2", fmt.Sprint(v.Headers.Header2))
-		ctx.JSON(200, v)
-	case HeadersExample400Response:
-		ctx.Status(400)
-	case HeadersExampledefaultResponse:
-		ctx.Status(v.StatusCode)
-	case error:
-		ctx.Error(v)
-	case nil:
-	default:
-		ctx.Error(fmt.Errorf("Unexpected response type: %T", v))
+	response, err := handler(ctx, request)
+
+	if err != nil {
+		ctx.Error(err)
+	} else if validResponse, ok := response.(HeadersExampleResponseObject); ok {
+		if err := validResponse.VisitHeadersExampleResponse(ctx.Writer); err != nil {
+			ctx.Error(err)
+		}
+	} else if response != nil {
+		ctx.Error(fmt.Errorf("Unexpected response type: %T", response))
 	}
 }
 
diff --git a/internal/test/strict-server/gin/server.go b/internal/test/strict-server/gin/server.go
index 876850a..748fc7d 100644
--- a/internal/test/strict-server/gin/server.go
+++ b/internal/test/strict-server/gin/server.go
@@ -12,11 +12,11 @@ import (
 type StrictServer struct {
 }
 
-func (s StrictServer) JSONExample(ctx context.Context, request JSONExampleRequestObject) interface{} {
-	return JSONExample200JSONResponse(*request.Body)
+func (s StrictServer) JSONExample(ctx context.Context, request JSONExampleRequestObject) (JSONExampleResponseObject, error) {
+	return JSONExample200JSONResponse(*request.Body), nil
 }
 
-func (s StrictServer) MultipartExample(ctx context.Context, request MultipartExampleRequestObject) interface{} {
+func (s StrictServer) MultipartExample(ctx context.Context, request MultipartExampleRequestObject) (MultipartExampleResponseObject, error) {
 	return MultipartExample200MultipartResponse(func(writer *multipart.Writer) error {
 		for {
 			part, err := request.Body.NextPart()
@@ -37,19 +37,19 @@ func (s StrictServer) MultipartExample(ctx context.Context, request MultipartExa
 				return err
 			}
 		}
-	})
+	}), nil
 }
 
-func (s StrictServer) MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) interface{} {
+func (s StrictServer) MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) (MultipleRequestAndResponseTypesResponseObject, error) {
 	switch {
 	case request.Body != nil:
-		return MultipleRequestAndResponseTypes200ImagepngResponse{Body: request.Body}
+		return MultipleRequestAndResponseTypes200ImagepngResponse{Body: request.Body}, nil
 	case request.JSONBody != nil:
-		return MultipleRequestAndResponseTypes200JSONResponse(*request.JSONBody)
+		return MultipleRequestAndResponseTypes200JSONResponse(*request.JSONBody), nil
 	case request.FormdataBody != nil:
-		return MultipleRequestAndResponseTypes200FormdataResponse(*request.FormdataBody)
+		return MultipleRequestAndResponseTypes200FormdataResponse(*request.FormdataBody), nil
 	case request.TextBody != nil:
-		return MultipleRequestAndResponseTypes200TextResponse(*request.TextBody)
+		return MultipleRequestAndResponseTypes200TextResponse(*request.TextBody), nil
 	case request.MultipartBody != nil:
 		return MultipleRequestAndResponseTypes200MultipartResponse(func(writer *multipart.Writer) error {
 			for {
@@ -71,32 +71,32 @@ func (s StrictServer) MultipleRequestAndResponseTypes(ctx context.Context, reque
 					return err
 				}
 			}
-		})
+		}), nil
 	default:
-		return MultipleRequestAndResponseTypes400Response{}
+		return MultipleRequestAndResponseTypes400Response{}, nil
 	}
 }
 
-func (s StrictServer) TextExample(ctx context.Context, request TextExampleRequestObject) interface{} {
-	return TextExample200TextResponse(*request.Body)
+func (s StrictServer) TextExample(ctx context.Context, request TextExampleRequestObject) (TextExampleResponseObject, error) {
+	return TextExample200TextResponse(*request.Body), nil
 }
 
-func (s StrictServer) UnknownExample(ctx context.Context, request UnknownExampleRequestObject) interface{} {
-	return UnknownExample200Videomp4Response{Body: request.Body}
+func (s StrictServer) UnknownExample(ctx context.Context, request UnknownExampleRequestObject) (UnknownExampleResponseObject, error) {
+	return UnknownExample200Videomp4Response{Body: request.Body}, nil
 }
 
-func (s StrictServer) UnspecifiedContentType(ctx context.Context, request UnspecifiedContentTypeRequestObject) interface{} {
-	return UnspecifiedContentType200VideoResponse{Body: request.Body, ContentType: request.ContentType}
+func (s StrictServer) UnspecifiedContentType(ctx context.Context, request UnspecifiedContentTypeRequestObject) (UnspecifiedContentTypeResponseObject, error) {
+	return UnspecifiedContentType200VideoResponse{Body: request.Body, ContentType: request.ContentType}, nil
 }
 
-func (s StrictServer) URLEncodedExample(ctx context.Context, request URLEncodedExampleRequestObject) interface{} {
-	return URLEncodedExample200FormdataResponse(*request.Body)
+func (s StrictServer) URLEncodedExample(ctx context.Context, request URLEncodedExampleRequestObject) (URLEncodedExampleResponseObject, error) {
+	return URLEncodedExample200FormdataResponse(*request.Body), nil
 }
 
-func (s StrictServer) HeadersExample(ctx context.Context, request HeadersExampleRequestObject) interface{} {
-	return HeadersExample200JSONResponse{Body: Example(*request.Body), Headers: HeadersExample200ResponseHeaders{Header1: request.Params.Header1, Header2: *request.Params.Header2}}
+func (s StrictServer) HeadersExample(ctx context.Context, request HeadersExampleRequestObject) (HeadersExampleResponseObject, error) {
+	return HeadersExample200JSONResponse{Body: Example(*request.Body), Headers: HeadersExample200ResponseHeaders{Header1: request.Params.Header1, Header2: *request.Params.Header2}}, nil
 }
 
-func (s StrictServer) ReusableResponses(ctx context.Context, request ReusableResponsesRequestObject) interface{} {
-	return ReusableResponses200JSONResponse{Body: *request.Body}
+func (s StrictServer) ReusableResponses(ctx context.Context, request ReusableResponsesRequestObject) (ReusableResponsesResponseObject, error) {
+	return ReusableResponses200JSONResponse{Body: *request.Body}, nil
 }
diff --git a/pkg/runtime/bindstring_test.go b/pkg/runtime/bindstring_test.go
index 42b3cab..f2060de 100644
--- a/pkg/runtime/bindstring_test.go
+++ b/pkg/runtime/bindstring_test.go
@@ -14,6 +14,8 @@
 package runtime
 
 import (
+	"fmt"
+	"math"
 	"testing"
 	"time"
 
@@ -37,39 +39,56 @@ func TestBindStringToObject(t *testing.T) {
 	var i8 int8
 	assert.NoError(t, BindStringToObject("12", &i8))
 	assert.Equal(t, int8(12), i8)
+	assert.NoError(t, BindStringToObject("-12", &i8))
+	assert.Equal(t, int8(-12), i8)
 
 	assert.Error(t, BindStringToObject("5.7", &i8))
 	assert.Error(t, BindStringToObject("foo", &i8))
 	assert.Error(t, BindStringToObject("1,2,3", &i8))
+	assert.Error(t, BindStringToObject(fmt.Sprintf("%d", math.MinInt8-1), &i8))
+	assert.Error(t, BindStringToObject(fmt.Sprintf("%d", math.MaxInt8+1), &i8))
 
 	var i16 int16
 	assert.NoError(t, BindStringToObject("12", &i16))
 	assert.Equal(t, int16(12), i16)
+	assert.NoError(t, BindStringToObject("-12", &i16))
+	assert.Equal(t, int16(-12), i16)
 
 	assert.Error(t, BindStringToObject("5.7", &i16))
 	assert.Error(t, BindStringToObject("foo", &i16))
 	assert.Error(t, BindStringToObject("1,2,3", &i16))
+	assert.Error(t, BindStringToObject(fmt.Sprintf("%d", math.MinInt16-1), &i16))
+	assert.Error(t, BindStringToObject(fmt.Sprintf("%d", math.MaxInt16+1), &i16))
 
 	var i32 int32
 	assert.NoError(t, BindStringToObject("12", &i32))
 	assert.Equal(t, int32(12), i32)
+	assert.NoError(t, BindStringToObject("-12", &i32))
+	assert.Equal(t, int32(-12), i32)
 
 	assert.Error(t, BindStringToObject("5.7", &i32))
 	assert.Error(t, BindStringToObject("foo", &i32))
 	assert.Error(t, BindStringToObject("1,2,3", &i32))
+	assert.Error(t, BindStringToObject(fmt.Sprintf("%d", math.MinInt32-1), &i32))
+	assert.Error(t, BindStringToObject(fmt.Sprintf("%d", math.MaxInt32+1), &i32))
 
 	var i64 int64
 	assert.NoError(t, BindStringToObject("124", &i64))
 	assert.Equal(t, int64(124), i64)
+	assert.NoError(t, BindStringToObject("-124", &i64))
+	assert.Equal(t, int64(-124), i64)
 
 	assert.Error(t, BindStringToObject("5.7", &i64))
 	assert.Error(t, BindStringToObject("foo", &i64))
 	assert.Error(t, BindStringToObject("1,2,3", &i64))
+	assert.Error(t, BindStringToObject("-9223372036854775809", &i64))
+	assert.Error(t, BindStringToObject("9223372036854775808", &i64)) // 1<<63
 
 	var u uint
 	assert.NoError(t, BindStringToObject("5", &u))
 	assert.Equal(t, uint(5), u)
 
+	assert.Error(t, BindStringToObject("-5", &u))
 	assert.Error(t, BindStringToObject("5.7", &u))
 	assert.Error(t, BindStringToObject("foo", &u))
 	assert.Error(t, BindStringToObject("1,2,3", &u))
@@ -78,33 +97,41 @@ func TestBindStringToObject(t *testing.T) {
 	assert.NoError(t, BindStringToObject("12", &u8))
 	assert.Equal(t, uint8(12), u8)
 
+	assert.Error(t, BindStringToObject("-5", &u8))
 	assert.Error(t, BindStringToObject("5.7", &u8))
 	assert.Error(t, BindStringToObject("foo", &u8))
 	assert.Error(t, BindStringToObject("1,2,3", &u8))
+	assert.Error(t, BindStringToObject(fmt.Sprintf("%d", math.MaxUint8+1), &i8))
 
 	var u16 uint16
 	assert.NoError(t, BindStringToObject("12", &u16))
 	assert.Equal(t, uint16(12), u16)
 
+	assert.Error(t, BindStringToObject("-5", &u16))
 	assert.Error(t, BindStringToObject("5.7", &u16))
 	assert.Error(t, BindStringToObject("foo", &u16))
 	assert.Error(t, BindStringToObject("1,2,3", &u16))
+	assert.Error(t, BindStringToObject(fmt.Sprintf("%d", math.MaxUint16+1), &i16))
 
 	var u32 uint32
 	assert.NoError(t, BindStringToObject("12", &u32))
 	assert.Equal(t, uint32(12), u32)
 
+	assert.Error(t, BindStringToObject("-5", &u32))
 	assert.Error(t, BindStringToObject("5.7", &u32))
 	assert.Error(t, BindStringToObject("foo", &u32))
 	assert.Error(t, BindStringToObject("1,2,3", &u32))
+	assert.Error(t, BindStringToObject(fmt.Sprintf("%d", math.MaxUint32+1), &i32))
 
 	var u64 uint64
 	assert.NoError(t, BindStringToObject("124", &u64))
 	assert.Equal(t, uint64(124), u64)
 
+	assert.Error(t, BindStringToObject("-5", &u64))
 	assert.Error(t, BindStringToObject("5.7", &u64))
 	assert.Error(t, BindStringToObject("foo", &u64))
 	assert.Error(t, BindStringToObject("1,2,3", &u64))
+	assert.Error(t, BindStringToObject("18446744073709551616", &i64)) // 1<<64
 
 	var b bool
 	assert.NoError(t, BindStringToObject("True", &b))
@@ -113,6 +140,10 @@ func TestBindStringToObject(t *testing.T) {
 	assert.Equal(t, true, b)
 	assert.NoError(t, BindStringToObject("1", &b))
 	assert.Equal(t, true, b)
+	assert.NoError(t, BindStringToObject("0", &b))
+	assert.Equal(t, false, b)
+	assert.Error(t, BindStringToObject("-1", &b))
+	assert.Error(t, BindStringToObject("hello", &b))
 
 	var f64 float64
 	assert.NoError(t, BindStringToObject("1.25", &f64))
@@ -127,6 +158,8 @@ func TestBindStringToObject(t *testing.T) {
 
 	assert.Error(t, BindStringToObject("foo", &f32))
 	assert.Error(t, BindStringToObject("1,2,3", &f32))
+	assert.NoError(t, BindStringToObject(fmt.Sprintf("%f", math.MaxFloat32), &f32))
+	assert.Error(t, BindStringToObject(fmt.Sprintf("%f", math.MaxFloat32*2), &f32))
 
 	// This checks whether binding works through a type alias.
 	type SomeType int