Repository: deepmap/oapi-codegen
Pull request #208 (2020-07-15 14:44:12)

feature: --exclude-schemas option for excluding schemas from type generation
### New feature:

introduce `--exclude-schemas` option to specify the list of schemas that need to be excluded from type generation. 

This will allow to have both generated and hand-written types or interfaces in the same package, and have valid references in both source code, generated code and the openapi spec. 



Patch:
diff --git a/README.md b/README.md
index 1d5d39a..bb36ca9 100644
--- a/README.md
+++ b/README.md
@@ -455,6 +455,12 @@ To generate a server that only handles `admin` paths, use the argument
 `-include-tags="admin"`. When neither of these arguments is present, all paths
 are generated.
 
+`oapi-codegen` can filter schemas based on the option `--exclude-schemas`, which is
+a comma separated list of schema names. For instance, `--exclude-tags=Pet,NewPet`
+will exclude from generation schemas `Pet` and `NewPet`. This allow to have a
+in the same package a manually defined structure or interface and refer to it 
+in the openapi spec. 
+
 ### Import Mappings
 
 OpenAPI specifications may contain references to other OpenAPI specifications,
diff --git a/cmd/oapi-codegen/oapi-codegen.go b/cmd/oapi-codegen/oapi-codegen.go
index 6a6b523..50816de 100644
--- a/cmd/oapi-codegen/oapi-codegen.go
+++ b/cmd/oapi-codegen/oapi-codegen.go
@@ -33,13 +33,14 @@ func errExit(format string, args ...interface{}) {
 
 func main() {
 	var (
-		packageName   string
-		generate      string
-		outputFile    string
-		includeTags   string
-		excludeTags   string
-		templatesDir  string
-		importMapping string
+		packageName    string
+		generate       string
+		outputFile     string
+		includeTags    string
+		excludeTags    string
+		templatesDir   string
+		importMapping  string
+		excludeSchemas string
 	)
 	flag.StringVar(&packageName, "package", "", "The package name for generated code")
 	flag.StringVar(&generate, "generate", "types,client,server,spec",
@@ -49,6 +50,7 @@ func main() {
 	flag.StringVar(&excludeTags, "exclude-tags", "", "Exclude operations that are tagged with the given tags. Comma-separated list of tags.")
 	flag.StringVar(&templatesDir, "templates", "", "Path to directory containing user templates")
 	flag.StringVar(&importMapping, "import-mapping", "", "A dict from the external reference to golang package path")
+	flag.StringVar(&excludeSchemas, "exclude-schemas", "", "A comma separated list of schemas which must be excluded from generation")
 	flag.Parse()
 
 	if flag.NArg() < 1 {
@@ -92,6 +94,7 @@ func main() {
 
 	opts.IncludeTags = splitCSVArg(includeTags)
 	opts.ExcludeTags = splitCSVArg(excludeTags)
+	opts.ExcludeSchemas = splitCSVArg(excludeSchemas)
 
 	if opts.GenerateEchoServer && opts.GenerateChiServer {
 		errExit("can not specify both server and chi-server targets simultaneously")
@@ -168,4 +171,3 @@ func loadTemplateOverrides(templatesDir string) (map[string]string, error) {
 
 	return templates, nil
 }
-
diff --git a/examples/petstore-expanded/chi/api/petstore.gen.go b/examples/petstore-expanded/chi/api/petstore.gen.go
index d3c25c0..859e2db 100644
--- a/examples/petstore-expanded/chi/api/petstore.gen.go
+++ b/examples/petstore-expanded/chi/api/petstore.gen.go
@@ -6,7 +6,6 @@ package api
 import (
 	"bytes"
 	"compress/gzip"
-	"context"
 	"encoding/base64"
 	"fmt"
 	"github.com/deepmap/oapi-codegen/pkg/runtime"
@@ -62,111 +61,102 @@ type AddPetJSONBody NewPet
 // AddPetRequestBody defines body for AddPet for application/json ContentType.
 type AddPetJSONRequestBody AddPetJSONBody
 
+// ServerInterface represents all server handlers.
 type ServerInterface interface {
-	// Returns all pets (GET /pets)
-	FindPets(w http.ResponseWriter, r *http.Request)
-	// Creates a new pet (POST /pets)
+	// Returns all pets
+	// (GET /pets)
+	FindPets(w http.ResponseWriter, r *http.Request, params FindPetsParams)
+	// Creates a new pet
+	// (POST /pets)
 	AddPet(w http.ResponseWriter, r *http.Request)
-	// Deletes a pet by ID (DELETE /pets/{id})
-	DeletePet(w http.ResponseWriter, r *http.Request)
-	// Returns a pet by ID (GET /pets/{id})
-	FindPetById(w http.ResponseWriter, r *http.Request)
+	// Deletes a pet by ID
+	// (DELETE /pets/{id})
+	DeletePet(w http.ResponseWriter, r *http.Request, id int64)
+	// Returns a pet by ID
+	// (GET /pets/{id})
+	FindPetById(w http.ResponseWriter, r *http.Request, id int64)
 }
 
-// ParamsForFindPets operation parameters from context
-func ParamsForFindPets(ctx context.Context) *FindPetsParams {
-	return ctx.Value("FindPetsParams").(*FindPetsParams)
+// ServerInterfaceWrapper converts contexts to parameters.
+type ServerInterfaceWrapper struct {
+	Handler ServerInterface
 }
 
 // FindPets operation middleware
-func FindPetsCtx(next http.Handler) http.Handler {
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		ctx := r.Context()
+func (siw *ServerInterfaceWrapper) FindPets(w http.ResponseWriter, r *http.Request) {
+	ctx := r.Context()
 
-		var err error
+	var err error
 
-		// Parameter object where we will unmarshal all parameters from the context
-		var params FindPetsParams
+	// Parameter object where we will unmarshal all parameters from the context
+	var params FindPetsParams
 
-		// ------------- Optional query parameter "tags" -------------
-		if paramValue := r.URL.Query().Get("tags"); paramValue != "" {
+	// ------------- Optional query parameter "tags" -------------
+	if paramValue := r.URL.Query().Get("tags"); paramValue != "" {
 
-		}
-
-		err = runtime.BindQueryParameter("form", true, false, "tags", r.URL.Query(), &params.Tags)
-		if err != nil {
-			http.Error(w, fmt.Sprintf("Invalid format for parameter tags: %s", err), http.StatusBadRequest)
-			return
-		}
+	}
 
-		// ------------- Optional query parameter "limit" -------------
-		if paramValue := r.URL.Query().Get("limit"); paramValue != "" {
+	err = runtime.BindQueryParameter("form", true, false, "tags", r.URL.Query(), &params.Tags)
+	if err != nil {
+		http.Error(w, fmt.Sprintf("Invalid format for parameter tags: %s", err), http.StatusBadRequest)
+		return
+	}
 
-		}
+	// ------------- Optional query parameter "limit" -------------
+	if paramValue := r.URL.Query().Get("limit"); paramValue != "" {
 
-		err = runtime.BindQueryParameter("form", true, false, "limit", r.URL.Query(), &params.Limit)
-		if err != nil {
-			http.Error(w, fmt.Sprintf("Invalid format for parameter limit: %s", err), http.StatusBadRequest)
-			return
-		}
+	}
 
-		ctx = context.WithValue(ctx, "FindPetsParams", &params)
+	err = runtime.BindQueryParameter("form", true, false, "limit", r.URL.Query(), &params.Limit)
+	if err != nil {
+		http.Error(w, fmt.Sprintf("Invalid format for parameter limit: %s", err), http.StatusBadRequest)
+		return
+	}
 
-		next.ServeHTTP(w, r.WithContext(ctx))
-	})
+	siw.Handler.FindPets(w, r.WithContext(ctx), params)
 }
 
 // AddPet operation middleware
-func AddPetCtx(next http.Handler) http.Handler {
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		ctx := r.Context()
+func (siw *ServerInterfaceWrapper) AddPet(w http.ResponseWriter, r *http.Request) {
+	ctx := r.Context()
 
-		next.ServeHTTP(w, r.WithContext(ctx))
-	})
+	siw.Handler.AddPet(w, r.WithContext(ctx))
 }
 
 // DeletePet operation middleware
-func DeletePetCtx(next http.Handler) http.Handler {
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		ctx := r.Context()
-
-		var err error
+func (siw *ServerInterfaceWrapper) DeletePet(w http.ResponseWriter, r *http.Request) {
+	ctx := r.Context()
 
-		// ------------- Path parameter "id" -------------
-		var id int64
+	var err error
 
-		err = runtime.BindStyledParameter("simple", false, "id", chi.URLParam(r, "id"), &id)
-		if err != nil {
-			http.Error(w, fmt.Sprintf("Invalid format for parameter id: %s", err), http.StatusBadRequest)
-			return
-		}
+	// ------------- Path parameter "id" -------------
+	var id int64
 
-		ctx = context.WithValue(ctx, "id", id)
+	err = runtime.BindStyledParameter("simple", false, "id", chi.URLParam(r, "id"), &id)
+	if err != nil {
+		http.Error(w, fmt.Sprintf("Invalid format for parameter id: %s", err), http.StatusBadRequest)
+		return
+	}
 
-		next.ServeHTTP(w, r.WithContext(ctx))
-	})
+	siw.Handler.DeletePet(w, r.WithContext(ctx), id)
 }
 
 // FindPetById operation middleware
-func FindPetByIdCtx(next http.Handler) http.Handler {
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		ctx := r.Context()
+func (siw *ServerInterfaceWrapper) FindPetById(w http.ResponseWriter, r *http.Request) {
+	ctx := r.Context()
 
-		var err error
+	var err error
 
-		// ------------- Path parameter "id" -------------
-		var id int64
+	// ------------- Path parameter "id" -------------
+	var id int64
 
-		err = runtime.BindStyledParameter("simple", false, "id", chi.URLParam(r, "id"), &id)
-		if err != nil {
-			http.Error(w, fmt.Sprintf("Invalid format for parameter id: %s", err), http.StatusBadRequest)
-			return
-		}
-
-		ctx = context.WithValue(ctx, "id", id)
+	err = runtime.BindStyledParameter("simple", false, "id", chi.URLParam(r, "id"), &id)
+	if err != nil {
+		http.Error(w, fmt.Sprintf("Invalid format for parameter id: %s", err), http.StatusBadRequest)
+		return
+	}
 
-		next.ServeHTTP(w, r.WithContext(ctx))
-	})
+	siw.Handler.FindPetById(w, r.WithContext(ctx), id)
 }
 
 // Handler creates http.Handler with routing matching OpenAPI spec.
@@ -176,21 +166,21 @@ func Handler(si ServerInterface) http.Handler {
 
 // HandlerFromMux creates http.Handler with routing matching OpenAPI spec based on the provided mux.
 func HandlerFromMux(si ServerInterface, r chi.Router) http.Handler {
+	wrapper := ServerInterfaceWrapper{
+		Handler: si,
+	}
+
 	r.Group(func(r chi.Router) {
-		r.Use(FindPetsCtx)
-		r.Get("/pets", si.FindPets)
+		r.Get("/pets", wrapper.FindPets)
 	})
 	r.Group(func(r chi.Router) {
-		r.Use(AddPetCtx)
-		r.Post("/pets", si.AddPet)
+		r.Post("/pets", wrapper.AddPet)
 	})
 	r.Group(func(r chi.Router) {
-		r.Use(DeletePetCtx)
-		r.Delete("/pets/{id}", si.DeletePet)
+		r.Delete("/pets/{id}", wrapper.DeletePet)
 	})
 	r.Group(func(r chi.Router) {
-		r.Use(FindPetByIdCtx)
-		r.Get("/pets/{id}", si.FindPetById)
+		r.Get("/pets/{id}", wrapper.FindPetById)
 	})
 
 	return r
diff --git a/examples/petstore-expanded/chi/api/petstore.go b/examples/petstore-expanded/chi/api/petstore.go
index a7e2358..a8d31d7 100644
--- a/examples/petstore-expanded/chi/api/petstore.go
+++ b/examples/petstore-expanded/chi/api/petstore.go
@@ -34,9 +34,7 @@ func sendPetstoreError(w http.ResponseWriter, code int, message string) {
 }
 
 // Here, we implement all of the handlers in the ServerInterface
-func (p *PetStore) FindPets(w http.ResponseWriter, r *http.Request) {
-	params := ParamsForFindPets(r.Context())
-
+func (p *PetStore) FindPets(w http.ResponseWriter, r *http.Request, params FindPetsParams) {
 	p.Lock.Lock()
 	defer p.Lock.Unlock()
 
@@ -97,9 +95,7 @@ func (p *PetStore) AddPet(w http.ResponseWriter, r *http.Request) {
 	json.NewEncoder(w).Encode(pet)
 }
 
-func (p *PetStore) FindPetById(w http.ResponseWriter, r *http.Request) {
-	id := r.Context().Value("id").(int64)
-
+func (p *PetStore) FindPetById(w http.ResponseWriter, r *http.Request, id int64) {
 	p.Lock.Lock()
 	defer p.Lock.Unlock()
 
@@ -113,9 +109,7 @@ func (p *PetStore) FindPetById(w http.ResponseWriter, r *http.Request) {
 	json.NewEncoder(w).Encode(pet)
 }
 
-func (p *PetStore) DeletePet(w http.ResponseWriter, r *http.Request) {
-	id := r.Context().Value("id").(int64)
-
+func (p *PetStore) DeletePet(w http.ResponseWriter, r *http.Request, id int64) {
 	p.Lock.Lock()
 	defer p.Lock.Unlock()
 
diff --git a/pkg/codegen/codegen.go b/pkg/codegen/codegen.go
index ea8cf3b..7dc5101 100644
--- a/pkg/codegen/codegen.go
+++ b/pkg/codegen/codegen.go
@@ -43,6 +43,7 @@ type Options struct {
 	ExcludeTags        []string          // Exclude operations that have one of these tags. Ignored when empty.
 	UserTemplates      map[string]string // Override built-in templates from user-provided files
 	ImportMapping      map[string]string // ImportMapping specifies the golang package path for each external reference
+	ExcludeSchemas     []string          // Exclude from generation schemas with given names. Ignored when empty.
 }
 
 type goImport struct {
@@ -151,7 +152,7 @@ func Generate(swagger *openapi3.Swagger, packageName string, opts Options) (stri
 
 	var typeDefinitions string
 	if opts.GenerateTypes {
-		typeDefinitions, err = GenerateTypeDefinitions(t, swagger, ops)
+		typeDefinitions, err = GenerateTypeDefinitions(t, swagger, ops, opts.ExcludeSchemas)
 		if err != nil {
 			return "", errors.Wrap(err, "error generating type definitions")
 		}
@@ -302,8 +303,8 @@ func Generate(swagger *openapi3.Swagger, packageName string, opts Options) (stri
 	return string(outBytes), nil
 }
 
-func GenerateTypeDefinitions(t *template.Template, swagger *openapi3.Swagger, ops []OperationDefinition) (string, error) {
-	schemaTypes, err := GenerateTypesForSchemas(t, swagger.Components.Schemas)
+func GenerateTypeDefinitions(t *template.Template, swagger *openapi3.Swagger, ops []OperationDefinition, excludeSchemas []string) (string, error) {
+	schemaTypes, err := GenerateTypesForSchemas(t, swagger.Components.Schemas, excludeSchemas)
 	if err != nil {
 		return "", errors.Wrap(err, "error generating Go types for component schemas")
 	}
@@ -347,10 +348,17 @@ func GenerateTypeDefinitions(t *template.Template, swagger *openapi3.Swagger, op
 
 // Generates type definitions for any custom types defined in the
 // components/schemas section of the Swagger spec.
-func GenerateTypesForSchemas(t *template.Template, schemas map[string]*openapi3.SchemaRef) ([]TypeDefinition, error) {
+func GenerateTypesForSchemas(t *template.Template, schemas map[string]*openapi3.SchemaRef, excludeSchemas []string) ([]TypeDefinition, error) {
+	var excludeSchemasMap = make(map[string]bool)
+	for _, schema := range excludeSchemas {
+		excludeSchemasMap[schema] = true
+	}
 	types := make([]TypeDefinition, 0)
 	// We're going to define Go types for every object under components/schemas
 	for _, schemaName := range SortedSchemaKeys(schemas) {
+		if _, ok := excludeSchemasMap[schemaName]; ok {
+			continue
+		}
 		schemaRef := schemas[schemaName]
 
 		goSchema, err := GenerateGoSchema(schemaRef, []string{schemaName})
diff --git a/pkg/codegen/extension.go b/pkg/codegen/extension.go
new file mode 100644
index 0000000..4aaca67
--- /dev/null
+++ b/pkg/codegen/extension.go
@@ -0,0 +1,25 @@
+package codegen
+
+import (
+	"encoding/json"
+	"fmt"
+
+	"github.com/pkg/errors"
+)
+
+const (
+	extPropGoType = "x-go-type"
+)
+
+func extTypeName(extPropValue interface{}) (string, error) {
+	raw, ok := extPropValue.(json.RawMessage)
+	if !ok {
+		return "", fmt.Errorf("failed to convert type: %T", extPropValue)
+	}
+	var name string
+	if err := json.Unmarshal(raw, &name); err != nil {
+		return "", errors.Wrap(err, "failed to unmarshal json")
+	}
+
+	return name, nil
+}
diff --git a/pkg/codegen/prune.go b/pkg/codegen/prune.go
index 41783ad..a2804f0 100644
--- a/pkg/codegen/prune.go
+++ b/pkg/codegen/prune.go
@@ -27,6 +27,9 @@ func walkSwagger(swagger *openapi3.Swagger, doFn func(RefWrapper) (bool, error))
 	}
 
 	for _, p := range swagger.Paths {
+		for _, param := range p.Parameters {
+			walkParameterRef(param, doFn)
+		}
 		for _, op := range p.Operations() {
 			walkOperation(op, doFn)
 		}
diff --git a/pkg/codegen/schema.go b/pkg/codegen/schema.go
index 68ddffb..cbee286 100644
--- a/pkg/codegen/schema.go
+++ b/pkg/codegen/schema.go
@@ -134,12 +134,22 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) {
 		return mergedSchema, nil
 	}
 
-	// Schema type and format, eg. string / binary
-	t := schema.Type
-
 	outSchema := Schema{
 		RefType: refType,
 	}
+
+	// Check for custom Go type extension
+	if extension, ok := schema.Extensions[extPropGoType]; ok {
+		typeName, err := extTypeName(extension)
+		if err != nil {
+			return outSchema, errors.Wrapf(err, "invalid value for %q", extPropGoType)
+		}
+		outSchema.GoType = typeName
+		return outSchema, nil
+	}
+
+	// Schema type and format, eg. string / binary
+	t := schema.Type
 	// Handle objects and empty schemas first as a special case
 	if t == "" || t == "object" {
 		var outType string
@@ -427,6 +437,17 @@ func GenStructFromAllOf(allOf []*openapi3.SchemaRef, path []string) (string, err
 			objectParts = append(objectParts, "   // Embedded fields due to inline allOf schema")
 			objectParts = append(objectParts, GenFieldsFromProperties(goSchema.Properties)...)
 
+			if goSchema.HasAdditionalProperties {
+				addPropsType := goSchema.AdditionalPropertiesType.GoType
+				if goSchema.AdditionalPropertiesType.RefType != "" {
+					addPropsType = goSchema.AdditionalPropertiesType.RefType
+				}
+
+				additionalPropertiesPart := fmt.Sprintf("AdditionalProperties map[string]%s `json:\"-\"`", addPropsType)
+				if !StringInArray(additionalPropertiesPart, objectParts) {
+					objectParts = append(objectParts, additionalPropertiesPart)
+				}
+			}
 		}
 	}
 	objectParts = append(objectParts, "}")
diff --git a/pkg/codegen/templates/chi-handler.tmpl b/pkg/codegen/templates/chi-handler.tmpl
index 93cce45..16cd461 100644
--- a/pkg/codegen/templates/chi-handler.tmpl
+++ b/pkg/codegen/templates/chi-handler.tmpl
@@ -5,9 +5,12 @@ func Handler(si ServerInterface) http.Handler {
 
 // HandlerFromMux creates http.Handler with routing matching OpenAPI spec based on the provided mux.
 func HandlerFromMux(si ServerInterface, r chi.Router) http.Handler {
+{{if .}}wrapper := ServerInterfaceWrapper{
+        Handler: si,
+    }
+{{end}}
 {{range .}}r.Group(func(r chi.Router) {
-  r.Use({{.OperationId}}Ctx)
-  r.{{.Method | lower | title }}("{{.Path | swaggerUriToChiUri}}", si.{{.OperationId}})
+  r.{{.Method | lower | title }}("{{.Path | swaggerUriToChiUri}}", wrapper.{{.OperationId}})
 })
 {{end}}
   return r
diff --git a/pkg/codegen/templates/chi-interface.tmpl b/pkg/codegen/templates/chi-interface.tmpl
index fd23067..79a51fd 100644
--- a/pkg/codegen/templates/chi-interface.tmpl
+++ b/pkg/codegen/templates/chi-interface.tmpl
@@ -1,5 +1,7 @@
+// ServerInterface represents all server handlers.
 type ServerInterface interface {
-{{range .}}// {{.Summary | stripNewLines }} ({{.Method}} {{.Path}})
-{{.OperationId}}(w http.ResponseWriter, r *http.Request)
+{{range .}}{{.SummaryAsComment }}
+// ({{.Method}} {{.Path}})
+{{.OperationId}}(w http.ResponseWriter, r *http.Request{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params {{.OperationId}}Params{{end}})
 {{end}}
 }
diff --git a/pkg/codegen/templates/chi-middleware.tmpl b/pkg/codegen/templates/chi-middleware.tmpl
index 4ec3b39..ac9ee23 100644
--- a/pkg/codegen/templates/chi-middleware.tmpl
+++ b/pkg/codegen/templates/chi-middleware.tmpl
@@ -1,173 +1,165 @@
+// ServerInterfaceWrapper converts contexts to parameters.
+type ServerInterfaceWrapper struct {
+    Handler ServerInterface
+}
 
 {{range .}}{{$opid := .OperationId}}
 
-{{if .RequiresParamObject}}
-// ParamsFor{{.OperationId}} operation parameters from context
-func ParamsFor{{.OperationId}}(ctx context.Context) *{{.OperationId}}Params {
-  return ctx.Value("{{.OperationId}}Params").(*{{.OperationId}}Params)
-}
-{{end}}
-
 // {{$opid}} operation middleware
-func {{$opid}}Ctx(next http.Handler) http.Handler {
-  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-    ctx := r.Context()
-    {{if or .RequiresParamObject (gt (len .PathParams) 0) }}
-    var err error
-    {{end}}
-
-    {{range .PathParams}}// ------------- Path parameter "{{.ParamName}}" -------------
-    var {{$varName := .GoVariableName}}{{$varName}} {{.TypeDef}}
-
-    {{if .IsPassThrough}}
-    {{$varName}} = chi.URLParam(r, "{{.ParamName}}")
-    {{end}}
-    {{if .IsJson}}
-    err = json.Unmarshal([]byte(chi.URLParam(r, "{{.ParamName}}")), &{{$varName}})
-    if err != nil {
-      http.Error(w, "Error unmarshaling parameter '{{.ParamName}}' as JSON", http.StatusBadRequest)
-      return
-    }
-    {{end}}
-    {{if .IsStyled}}
-    err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, "{{.ParamName}}", chi.URLParam(r, "{{.ParamName}}"), &{{$varName}})
-    if err != nil {
-      http.Error(w, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err), http.StatusBadRequest)
-      return
-    }
-    {{end}}
-
-    ctx = context.WithValue(ctx, "{{$varName}}", {{$varName}})
-    {{end}}
+func (siw *ServerInterfaceWrapper) {{$opid}}(w http.ResponseWriter, r *http.Request) {
+  ctx := r.Context()
+  {{if or .RequiresParamObject (gt (len .PathParams) 0) }}
+  var err error
+  {{end}}
+
+  {{range .PathParams}}// ------------- Path parameter "{{.ParamName}}" -------------
+  var {{$varName := .GoVariableName}}{{$varName}} {{.TypeDef}}
+
+  {{if .IsPassThrough}}
+  {{$varName}} = chi.URLParam(r, "{{.ParamName}}")
+  {{end}}
+  {{if .IsJson}}
+  err = json.Unmarshal([]byte(chi.URLParam(r, "{{.ParamName}}")), &{{$varName}})
+  if err != nil {
+    http.Error(w, "Error unmarshaling parameter '{{.ParamName}}' as JSON", http.StatusBadRequest)
+    return
+  }
+  {{end}}
+  {{if .IsStyled}}
+  err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, "{{.ParamName}}", chi.URLParam(r, "{{.ParamName}}"), &{{$varName}})
+  if err != nil {
+    http.Error(w, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err), http.StatusBadRequest)
+    return
+  }
+  {{end}}
+
+  {{end}}
 
 {{range .SecurityDefinitions}}
-    ctx = context.WithValue(ctx, "{{.ProviderName}}.Scopes", {{toStringArray .Scopes}})
+  ctx = context.WithValue(ctx, "{{.ProviderName}}.Scopes", {{toStringArray .Scopes}})
 {{end}}
 
-    {{if .RequiresParamObject}}
-      // Parameter object where we will unmarshal all parameters from the context
-      var params {{.OperationId}}Params
+  {{if .RequiresParamObject}}
+    // Parameter object where we will unmarshal all parameters from the context
+    var params {{.OperationId}}Params
 
-      {{range $paramIdx, $param := .QueryParams}}// ------------- {{if .Required}}Required{{else}}Optional{{end}} query parameter "{{.ParamName}}" -------------
-        if paramValue := r.URL.Query().Get("{{.ParamName}}"); paramValue != "" {
+    {{range $paramIdx, $param := .QueryParams}}// ------------- {{if .Required}}Required{{else}}Optional{{end}} query parameter "{{.ParamName}}" -------------
+      if paramValue := r.URL.Query().Get("{{.ParamName}}"); paramValue != "" {
 
-        {{if .IsPassThrough}}
-          params.{{.GoName}} = {{if not .Required}}&{{end}}paramValue
-        {{end}}
-
-        {{if .IsJson}}
-          var value {{.TypeDef}}
-          err = json.Unmarshal([]byte(paramValue), &value)
-          if err != nil {
-            http.Error(w, "Error unmarshaling parameter '{{.ParamName}}' as JSON", http.StatusBadRequest)
-            return
-          }
+      {{if .IsPassThrough}}
+        params.{{.GoName}} = {{if not .Required}}&{{end}}paramValue
+      {{end}}
 
-          params.{{.GoName}} = {{if not .Required}}&{{end}}value
-        {{end}}
-        }{{if .Required}} else {
-            http.Error(w, "Query argument {{.ParamName}} is required, but not found", http.StatusBadRequest)
-            return
-        }{{end}}
-        {{if .IsStyled}}
-        err = runtime.BindQueryParameter("{{.Style}}", {{.Explode}}, {{.Required}}, "{{.ParamName}}", r.URL.Query(), &params.{{.GoName}})
+      {{if .IsJson}}
+        var value {{.TypeDef}}
+        err = json.Unmarshal([]byte(paramValue), &value)
         if err != nil {
-          http.Error(w, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err), http.StatusBadRequest)
+          http.Error(w, "Error unmarshaling parameter '{{.ParamName}}' as JSON", http.StatusBadRequest)
           return
         }
-        {{end}}
-    {{end}}
-
-      {{if .HeaderParams}}
-        headers := r.Header
-
-        {{range .HeaderParams}}// ------------- {{if .Required}}Required{{else}}Optional{{end}} header parameter "{{.ParamName}}" -------------
-          if valueList, found := headers[http.CanonicalHeaderKey("{{.ParamName}}")]; found {
-            var {{.GoName}} {{.TypeDef}}
-            n := len(valueList)
-            if n != 1 {
-              http.Error(w, fmt.Sprintf("Expected one value for {{.ParamName}}, got %d", n), http.StatusBadRequest)
-              return
-            }
-
-          {{if .IsPassThrough}}
-            params.{{.GoName}} = {{if not .Required}}&{{end}}valueList[0]
-          {{end}}
-
-          {{if .IsJson}}
-            err = json.Unmarshal([]byte(valueList[0]), &{{.GoName}})
-            if err != nil {
-              http.Error(w, "Error unmarshaling parameter '{{.ParamName}}' as JSON", http.StatusBadRequest)
-              return
-            }
-          {{end}}
-
-          {{if .IsStyled}}
-            err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, "{{.ParamName}}", valueList[0], &{{.GoName}})
-            if err != nil {
-              http.Error(w, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err), http.StatusBadRequest)
-              return
-            }
-          {{end}}
-
-            params.{{.GoName}} = {{if not .Required}}&{{end}}{{.GoName}}
-
-          } {{if .Required}}else {
-              http.Error(w, fmt.Sprintf("Header parameter {{.ParamName}} is required, but not found: %s", err), http.StatusBadRequest)
-              return
-          }{{end}}
 
-        {{end}}
+        params.{{.GoName}} = {{if not .Required}}&{{end}}value
       {{end}}
+      }{{if .Required}} else {
+          http.Error(w, "Query argument {{.ParamName}} is required, but not found", http.StatusBadRequest)
+          return
+      }{{end}}
+      {{if .IsStyled}}
+      err = runtime.BindQueryParameter("{{.Style}}", {{.Explode}}, {{.Required}}, "{{.ParamName}}", r.URL.Query(), &params.{{.GoName}})
+      if err != nil {
+        http.Error(w, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err), http.StatusBadRequest)
+        return
+      }
+      {{end}}
+  {{end}}
 
-      {{range .CookieParams}}
-        if cookie, err := r.Cookie("{{.ParamName}}"); err == nil {
-
-        {{- if .IsPassThrough}}
-          params.{{.GoName}} = {{if not .Required}}&{{end}}cookie.Value
-        {{end}}
+    {{if .HeaderParams}}
+      headers := r.Header
 
-        {{- if .IsJson}}
-          var value {{.TypeDef}}
-          var decoded string
-          decoded, err := url.QueryUnescape(cookie.Value)
-          if err != nil {
-            http.Error(w, "Error unescaping cookie parameter '{{.ParamName}}'", http.StatusBadRequest)
+      {{range .HeaderParams}}// ------------- {{if .Required}}Required{{else}}Optional{{end}} header parameter "{{.ParamName}}" -------------
+        if valueList, found := headers[http.CanonicalHeaderKey("{{.ParamName}}")]; found {
+          var {{.GoName}} {{.TypeDef}}
+          n := len(valueList)
+          if n != 1 {
+            http.Error(w, fmt.Sprintf("Expected one value for {{.ParamName}}, got %d", n), http.StatusBadRequest)
             return
           }
 
-          err = json.Unmarshal([]byte(decoded), &value)
+        {{if .IsPassThrough}}
+          params.{{.GoName}} = {{if not .Required}}&{{end}}valueList[0]
+        {{end}}
+
+        {{if .IsJson}}
+          err = json.Unmarshal([]byte(valueList[0]), &{{.GoName}})
           if err != nil {
             http.Error(w, "Error unmarshaling parameter '{{.ParamName}}' as JSON", http.StatusBadRequest)
             return
           }
-
-          params.{{.GoName}} = {{if not .Required}}&{{end}}value
         {{end}}
 
-        {{- if .IsStyled}}
-          var value {{.TypeDef}}
-          err = runtime.BindStyledParameter("simple",{{.Explode}}, "{{.ParamName}}", cookie.Value, &value)
+        {{if .IsStyled}}
+          err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, "{{.ParamName}}", valueList[0], &{{.GoName}})
           if err != nil {
-            http.Error(w, "Invalid format for parameter {{.ParamName}}: %s", http.StatusBadRequest)
+            http.Error(w, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err), http.StatusBadRequest)
             return
           }
-          params.{{.GoName}} = {{if not .Required}}&{{end}}value
         {{end}}
 
+          params.{{.GoName}} = {{if not .Required}}&{{end}}{{.GoName}}
+
+        } {{if .Required}}else {
+            http.Error(w, fmt.Sprintf("Header parameter {{.ParamName}} is required, but not found: %s", err), http.StatusBadRequest)
+            return
+        }{{end}}
+
+      {{end}}
+    {{end}}
+
+    {{range .CookieParams}}
+      if cookie, err := r.Cookie("{{.ParamName}}"); err == nil {
+
+      {{- if .IsPassThrough}}
+        params.{{.GoName}} = {{if not .Required}}&{{end}}cookie.Value
+      {{end}}
+
+      {{- if .IsJson}}
+        var value {{.TypeDef}}
+        var decoded string
+        decoded, err := url.QueryUnescape(cookie.Value)
+        if err != nil {
+          http.Error(w, "Error unescaping cookie parameter '{{.ParamName}}'", http.StatusBadRequest)
+          return
         }
 
-        {{- if .Required}} else {
-          http.Error(w, "Query argument {{.ParamName}} is required, but not found", http.StatusBadRequest)
+        err = json.Unmarshal([]byte(decoded), &value)
+        if err != nil {
+          http.Error(w, "Error unmarshaling parameter '{{.ParamName}}' as JSON", http.StatusBadRequest)
           return
         }
-        {{- end}}
+
+        params.{{.GoName}} = {{if not .Required}}&{{end}}value
       {{end}}
 
-      ctx = context.WithValue(ctx, "{{.OperationId}}Params", &params)
+      {{- if .IsStyled}}
+        var value {{.TypeDef}}
+        err = runtime.BindStyledParameter("simple",{{.Explode}}, "{{.ParamName}}", cookie.Value, &value)
+        if err != nil {
+          http.Error(w, "Invalid format for parameter {{.ParamName}}: %s", http.StatusBadRequest)
+          return
+        }
+        params.{{.GoName}} = {{if not .Required}}&{{end}}value
+      {{end}}
+
+      }
+
+      {{- if .Required}} else {
+        http.Error(w, "Query argument {{.ParamName}} is required, but not found", http.StatusBadRequest)
+        return
+      }
+      {{- end}}
     {{end}}
-    next.ServeHTTP(w, r.WithContext(ctx))
-  })
+  {{end}}
+  siw.Handler.{{.OperationId}}(w, r.WithContext(ctx){{genParamNames .PathParams}}{{if .RequiresParamObject}}, params{{end}})
 }
 {{end}}
 
diff --git a/pkg/codegen/templates/templates.gen.go b/pkg/codegen/templates/templates.gen.go
index 02ba038..9b90173 100644
--- a/pkg/codegen/templates/templates.gen.go
+++ b/pkg/codegen/templates/templates.gen.go
@@ -80,190 +80,187 @@ func Handler(si ServerInterface) http.Handler {
 
 // HandlerFromMux creates http.Handler with routing matching OpenAPI spec based on the provided mux.
 func HandlerFromMux(si ServerInterface, r chi.Router) http.Handler {
+{{if .}}wrapper := ServerInterfaceWrapper{
+        Handler: si,
+    }
+{{end}}
 {{range .}}r.Group(func(r chi.Router) {
-  r.Use({{.OperationId}}Ctx)
-  r.{{.Method | lower | title }}("{{.Path | swaggerUriToChiUri}}", si.{{.OperationId}})
+  r.{{.Method | lower | title }}("{{.Path | swaggerUriToChiUri}}", wrapper.{{.OperationId}})
 })
 {{end}}
   return r
 }
 `,
-	"chi-interface.tmpl": `type ServerInterface interface {
-{{range .}}// {{.Summary | stripNewLines }} ({{.Method}} {{.Path}})
-{{.OperationId}}(w http.ResponseWriter, r *http.Request)
+	"chi-interface.tmpl": `// ServerInterface represents all server handlers.
+type ServerInterface interface {
+{{range .}}{{.SummaryAsComment }}
+// ({{.Method}} {{.Path}})
+{{.OperationId}}(w http.ResponseWriter, r *http.Request{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params {{.OperationId}}Params{{end}})
 {{end}}
 }
 `,
-	"chi-middleware.tmpl": `
-{{range .}}{{$opid := .OperationId}}
-
-{{if .RequiresParamObject}}
-// ParamsFor{{.OperationId}} operation parameters from context
-func ParamsFor{{.OperationId}}(ctx context.Context) *{{.OperationId}}Params {
-  return ctx.Value("{{.OperationId}}Params").(*{{.OperationId}}Params)
+	"chi-middleware.tmpl": `// ServerInterfaceWrapper converts contexts to parameters.
+type ServerInterfaceWrapper struct {
+    Handler ServerInterface
 }
-{{end}}
 
-// {{$opid}} operation middleware
-func {{$opid}}Ctx(next http.Handler) http.Handler {
-  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-    ctx := r.Context()
-    {{if or .RequiresParamObject (gt (len .PathParams) 0) }}
-    var err error
-    {{end}}
-
-    {{range .PathParams}}// ------------- Path parameter "{{.ParamName}}" -------------
-    var {{$varName := .GoVariableName}}{{$varName}} {{.TypeDef}}
+{{range .}}{{$opid := .OperationId}}
 
-    {{if .IsPassThrough}}
-    {{$varName}} = chi.URLParam(r, "{{.ParamName}}")
-    {{end}}
-    {{if .IsJson}}
-    err = json.Unmarshal([]byte(chi.URLParam(r, "{{.ParamName}}")), &{{$varName}})
-    if err != nil {
-      http.Error(w, "Error unmarshaling parameter '{{.ParamName}}' as JSON", http.StatusBadRequest)
-      return
-    }
-    {{end}}
-    {{if .IsStyled}}
-    err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, "{{.ParamName}}", chi.URLParam(r, "{{.ParamName}}"), &{{$varName}})
-    if err != nil {
-      http.Error(w, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err), http.StatusBadRequest)
-      return
-    }
-    {{end}}
+// {{$opid}} operation middleware
+func (siw *ServerInterfaceWrapper) {{$opid}}(w http.ResponseWriter, r *http.Request) {
+  ctx := r.Context()
+  {{if or .RequiresParamObject (gt (len .PathParams) 0) }}
+  var err error
+  {{end}}
+
+  {{range .PathParams}}// ------------- Path parameter "{{.ParamName}}" -------------
+  var {{$varName := .GoVariableName}}{{$varName}} {{.TypeDef}}
+
+  {{if .IsPassThrough}}
+  {{$varName}} = chi.URLParam(r, "{{.ParamName}}")
+  {{end}}
+  {{if .IsJson}}
+  err = json.Unmarshal([]byte(chi.URLParam(r, "{{.ParamName}}")), &{{$varName}})
+  if err != nil {
+    http.Error(w, "Error unmarshaling parameter '{{.ParamName}}' as JSON", http.StatusBadRequest)
+    return
+  }
+  {{end}}
+  {{if .IsStyled}}
+  err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, "{{.ParamName}}", chi.URLParam(r, "{{.ParamName}}"), &{{$varName}})
+  if err != nil {
+    http.Error(w, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err), http.StatusBadRequest)
+    return
+  }
+  {{end}}
 
-    ctx = context.WithValue(ctx, "{{$varName}}", {{$varName}})
-    {{end}}
+  {{end}}
 
 {{range .SecurityDefinitions}}
-    ctx = context.WithValue(ctx, "{{.ProviderName}}.Scopes", {{toStringArray .Scopes}})
+  ctx = context.WithValue(ctx, "{{.ProviderName}}.Scopes", {{toStringArray .Scopes}})
 {{end}}
 
-    {{if .RequiresParamObject}}
-      // Parameter object where we will unmarshal all parameters from the context
-      var params {{.OperationId}}Params
-
-      {{range $paramIdx, $param := .QueryParams}}// ------------- {{if .Required}}Required{{else}}Optional{{end}} query parameter "{{.ParamName}}" -------------
-        if paramValue := r.URL.Query().Get("{{.ParamName}}"); paramValue != "" {
+  {{if .RequiresParamObject}}
+    // Parameter object where we will unmarshal all parameters from the context
+    var params {{.OperationId}}Params
 
-        {{if .IsPassThrough}}
-          params.{{.GoName}} = {{if not .Required}}&{{end}}paramValue
-        {{end}}
+    {{range $paramIdx, $param := .QueryParams}}// ------------- {{if .Required}}Required{{else}}Optional{{end}} query parameter "{{.ParamName}}" -------------
+      if paramValue := r.URL.Query().Get("{{.ParamName}}"); paramValue != "" {
 
-        {{if .IsJson}}
-          var value {{.TypeDef}}
-          err = json.Unmarshal([]byte(paramValue), &value)
-          if err != nil {
-            http.Error(w, "Error unmarshaling parameter '{{.ParamName}}' as JSON", http.StatusBadRequest)
-            return
-          }
+      {{if .IsPassThrough}}
+        params.{{.GoName}} = {{if not .Required}}&{{end}}paramValue
+      {{end}}
 
-          params.{{.GoName}} = {{if not .Required}}&{{end}}value
-        {{end}}
-        }{{if .Required}} else {
-            http.Error(w, "Query argument {{.ParamName}} is required, but not found", http.StatusBadRequest)
-            return
-        }{{end}}
-        {{if .IsStyled}}
-        err = runtime.BindQueryParameter("{{.Style}}", {{.Explode}}, {{.Required}}, "{{.ParamName}}", r.URL.Query(), &params.{{.GoName}})
+      {{if .IsJson}}
+        var value {{.TypeDef}}
+        err = json.Unmarshal([]byte(paramValue), &value)
         if err != nil {
-          http.Error(w, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err), http.StatusBadRequest)
+          http.Error(w, "Error unmarshaling parameter '{{.ParamName}}' as JSON", http.StatusBadRequest)
           return
         }
-        {{end}}
-    {{end}}
-
-      {{if .HeaderParams}}
-        headers := r.Header
-
-        {{range .HeaderParams}}// ------------- {{if .Required}}Required{{else}}Optional{{end}} header parameter "{{.ParamName}}" -------------
-          if valueList, found := headers[http.CanonicalHeaderKey("{{.ParamName}}")]; found {
-            var {{.GoName}} {{.TypeDef}}
-            n := len(valueList)
-            if n != 1 {
-              http.Error(w, fmt.Sprintf("Expected one value for {{.ParamName}}, got %d", n), http.StatusBadRequest)
-              return
-            }
-
-          {{if .IsPassThrough}}
-            params.{{.GoName}} = {{if not .Required}}&{{end}}valueList[0]
-          {{end}}
-
-          {{if .IsJson}}
-            err = json.Unmarshal([]byte(valueList[0]), &{{.GoName}})
-            if err != nil {
-              http.Error(w, "Error unmarshaling parameter '{{.ParamName}}' as JSON", http.StatusBadRequest)
-              return
-            }
-          {{end}}
-
-          {{if .IsStyled}}
-            err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, "{{.ParamName}}", valueList[0], &{{.GoName}})
-            if err != nil {
-              http.Error(w, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err), http.StatusBadRequest)
-              return
-            }
-          {{end}}
-
-            params.{{.GoName}} = {{if not .Required}}&{{end}}{{.GoName}}
 
-          } {{if .Required}}else {
-              http.Error(w, fmt.Sprintf("Header parameter {{.ParamName}} is required, but not found: %s", err), http.StatusBadRequest)
-              return
-          }{{end}}
-
-        {{end}}
+        params.{{.GoName}} = {{if not .Required}}&{{end}}value
       {{end}}
+      }{{if .Required}} else {
+          http.Error(w, "Query argument {{.ParamName}} is required, but not found", http.StatusBadRequest)
+          return
+      }{{end}}
+      {{if .IsStyled}}
+      err = runtime.BindQueryParameter("{{.Style}}", {{.Explode}}, {{.Required}}, "{{.ParamName}}", r.URL.Query(), &params.{{.GoName}})
+      if err != nil {
+        http.Error(w, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err), http.StatusBadRequest)
+        return
+      }
+      {{end}}
+  {{end}}
 
-      {{range .CookieParams}}
-        if cookie, err := r.Cookie("{{.ParamName}}"); err == nil {
-
-        {{- if .IsPassThrough}}
-          params.{{.GoName}} = {{if not .Required}}&{{end}}cookie.Value
-        {{end}}
+    {{if .HeaderParams}}
+      headers := r.Header
 
-        {{- if .IsJson}}
-          var value {{.TypeDef}}
-          var decoded string
-          decoded, err := url.QueryUnescape(cookie.Value)
-          if err != nil {
-            http.Error(w, "Error unescaping cookie parameter '{{.ParamName}}'", http.StatusBadRequest)
+      {{range .HeaderParams}}// ------------- {{if .Required}}Required{{else}}Optional{{end}} header parameter "{{.ParamName}}" -------------
+        if valueList, found := headers[http.CanonicalHeaderKey("{{.ParamName}}")]; found {
+          var {{.GoName}} {{.TypeDef}}
+          n := len(valueList)
+          if n != 1 {
+            http.Error(w, fmt.Sprintf("Expected one value for {{.ParamName}}, got %d", n), http.StatusBadRequest)
             return
           }
 
-          err = json.Unmarshal([]byte(decoded), &value)
+        {{if .IsPassThrough}}
+          params.{{.GoName}} = {{if not .Required}}&{{end}}valueList[0]
+        {{end}}
+
+        {{if .IsJson}}
+          err = json.Unmarshal([]byte(valueList[0]), &{{.GoName}})
           if err != nil {
             http.Error(w, "Error unmarshaling parameter '{{.ParamName}}' as JSON", http.StatusBadRequest)
             return
           }
-
-          params.{{.GoName}} = {{if not .Required}}&{{end}}value
         {{end}}
 
-        {{- if .IsStyled}}
-          var value {{.TypeDef}}
-          err = runtime.BindStyledParameter("simple",{{.Explode}}, "{{.ParamName}}", cookie.Value, &value)
+        {{if .IsStyled}}
+          err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, "{{.ParamName}}", valueList[0], &{{.GoName}})
           if err != nil {
-            http.Error(w, "Invalid format for parameter {{.ParamName}}: %s", http.StatusBadRequest)
+            http.Error(w, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err), http.StatusBadRequest)
             return
           }
-          params.{{.GoName}} = {{if not .Required}}&{{end}}value
         {{end}}
 
+          params.{{.GoName}} = {{if not .Required}}&{{end}}{{.GoName}}
+
+        } {{if .Required}}else {
+            http.Error(w, fmt.Sprintf("Header parameter {{.ParamName}} is required, but not found: %s", err), http.StatusBadRequest)
+            return
+        }{{end}}
+
+      {{end}}
+    {{end}}
+
+    {{range .CookieParams}}
+      if cookie, err := r.Cookie("{{.ParamName}}"); err == nil {
+
+      {{- if .IsPassThrough}}
+        params.{{.GoName}} = {{if not .Required}}&{{end}}cookie.Value
+      {{end}}
+
+      {{- if .IsJson}}
+        var value {{.TypeDef}}
+        var decoded string
+        decoded, err := url.QueryUnescape(cookie.Value)
+        if err != nil {
+          http.Error(w, "Error unescaping cookie parameter '{{.ParamName}}'", http.StatusBadRequest)
+          return
         }
 
-        {{- if .Required}} else {
-          http.Error(w, "Query argument {{.ParamName}} is required, but not found", http.StatusBadRequest)
+        err = json.Unmarshal([]byte(decoded), &value)
+        if err != nil {
+          http.Error(w, "Error unmarshaling parameter '{{.ParamName}}' as JSON", http.StatusBadRequest)
+          return
+        }
+
+        params.{{.GoName}} = {{if not .Required}}&{{end}}value
+      {{end}}
+
+      {{- if .IsStyled}}
+        var value {{.TypeDef}}
+        err = runtime.BindStyledParameter("simple",{{.Explode}}, "{{.ParamName}}", cookie.Value, &value)
+        if err != nil {
+          http.Error(w, "Invalid format for parameter {{.ParamName}}: %s", http.StatusBadRequest)
           return
         }
-        {{- end}}
+        params.{{.GoName}} = {{if not .Required}}&{{end}}value
       {{end}}
 
-      ctx = context.WithValue(ctx, "{{.OperationId}}Params", &params)
+      }
+
+      {{- if .Required}} else {
+        http.Error(w, "Query argument {{.ParamName}} is required, but not found", http.StatusBadRequest)
+        return
+      }
+      {{- end}}
     {{end}}
-    next.ServeHTTP(w, r.WithContext(ctx))
-  })
+  {{end}}
+  siw.Handler.{{.OperationId}}(w, r.WithContext(ctx){{genParamNames .PathParams}}{{if .RequiresParamObject}}, params{{end}})
 }
 {{end}}
 
diff --git a/pkg/runtime/bindstring.go b/pkg/runtime/bindstring.go
index 4983279..e43d2e5 100644
--- a/pkg/runtime/bindstring.go
+++ b/pkg/runtime/bindstring.go
@@ -48,12 +48,18 @@ func BindStringToObject(src string, dst interface{}) error {
 	}
 
 	switch t.Kind() {
-	case reflect.Int, reflect.Int32, reflect.Int64:
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 		var val int64
 		val, err = strconv.ParseInt(src, 10, 64)
 		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 {
+			v.SetUint(val)
+		}
 	case reflect.String:
 		v.SetString(src)
 		err = nil


Test patch:
diff --git a/internal/test/schemas/schemas.gen.go b/internal/test/schemas/schemas.gen.go
index 270471a..ee387bf 100644
--- a/internal/test/schemas/schemas.gen.go
+++ b/internal/test/schemas/schemas.gen.go
@@ -45,6 +45,9 @@ type NullableProperties struct {
 	RequiredAndNullable *string `json:"requiredAndNullable"`
 }
 
+// StringInPath defines model for StringInPath.
+type StringInPath string
+
 // Issue185JSONBody defines parameters for Issue185.
 type Issue185JSONBody NullableProperties
 
@@ -144,6 +147,9 @@ type ClientInterface interface {
 
 	Issue185(ctx context.Context, body Issue185JSONRequestBody) (*http.Response, error)
 
+	// Issue209 request
+	Issue209(ctx context.Context, str StringInPath) (*http.Response, error)
+
 	// Issue30 request
 	Issue30(ctx context.Context, pFallthrough string) (*http.Response, error)
 
@@ -216,6 +222,21 @@ func (c *Client) Issue185(ctx context.Context, body Issue185JSONRequestBody) (*h
 	return c.Client.Do(req)
 }
 
+func (c *Client) Issue209(ctx context.Context, str StringInPath) (*http.Response, error) {
+	req, err := NewIssue209Request(c.Server, str)
+	if err != nil {
+		return nil, err
+	}
+	req = req.WithContext(ctx)
+	if c.RequestEditor != nil {
+		err = c.RequestEditor(ctx, req)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return c.Client.Do(req)
+}
+
 func (c *Client) Issue30(ctx context.Context, pFallthrough string) (*http.Response, error) {
 	req, err := NewIssue30Request(c.Server, pFallthrough)
 	if err != nil {
@@ -369,6 +390,40 @@ func NewIssue185RequestWithBody(server string, contentType string, body io.Reade
 	return req, nil
 }
 
+// NewIssue209Request generates requests for Issue209
+func NewIssue209Request(server string, str StringInPath) (*http.Request, error) {
+	var err error
+
+	var pathParam0 string
+
+	pathParam0, err = runtime.StyleParam("simple", false, "str", str)
+	if err != nil {
+		return nil, err
+	}
+
+	queryUrl, err := url.Parse(server)
+	if err != nil {
+		return nil, err
+	}
+
+	basePath := fmt.Sprintf("/issues/209/$%s", pathParam0)
+	if basePath[0] == '/' {
+		basePath = basePath[1:]
+	}
+
+	queryUrl, err = queryUrl.Parse(basePath)
+	if err != nil {
+		return nil, err
+	}
+
+	req, err := http.NewRequest("GET", queryUrl.String(), nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return req, nil
+}
+
 // NewIssue30Request generates requests for Issue30
 func NewIssue30Request(server string, pFallthrough string) (*http.Request, error) {
 	var err error
@@ -532,6 +587,9 @@ type ClientWithResponsesInterface interface {
 
 	Issue185WithResponse(ctx context.Context, body Issue185JSONRequestBody) (*Issue185Response, error)
 
+	// Issue209 request
+	Issue209WithResponse(ctx context.Context, str StringInPath) (*Issue209Response, error)
+
 	// Issue30 request
 	Issue30WithResponse(ctx context.Context, pFallthrough string) (*Issue30Response, error)
 
@@ -618,6 +676,27 @@ func (r Issue185Response) StatusCode() int {
 	return 0
 }
 
+type Issue209Response struct {
+	Body         []byte
+	HTTPResponse *http.Response
+}
+
+// Status returns HTTPResponse.Status
+func (r Issue209Response) Status() string {
+	if r.HTTPResponse != nil {
+		return r.HTTPResponse.Status
+	}
+	return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r Issue209Response) StatusCode() int {
+	if r.HTTPResponse != nil {
+		return r.HTTPResponse.StatusCode
+	}
+	return 0
+}
+
 type Issue30Response struct {
 	Body         []byte
 	HTTPResponse *http.Response
@@ -716,6 +795,15 @@ func (c *ClientWithResponses) Issue185WithResponse(ctx context.Context, body Iss
 	return ParseIssue185Response(rsp)
 }
 
+// Issue209WithResponse request returning *Issue209Response
+func (c *ClientWithResponses) Issue209WithResponse(ctx context.Context, str StringInPath) (*Issue209Response, error) {
+	rsp, err := c.Issue209(ctx, str)
+	if err != nil {
+		return nil, err
+	}
+	return ParseIssue209Response(rsp)
+}
+
 // Issue30WithResponse request returning *Issue30Response
 func (c *ClientWithResponses) Issue30WithResponse(ctx context.Context, pFallthrough string) (*Issue30Response, error) {
 	rsp, err := c.Issue30(ctx, pFallthrough)
@@ -855,6 +943,25 @@ func ParseIssue185Response(rsp *http.Response) (*Issue185Response, error) {
 	return response, nil
 }
 
+// ParseIssue209Response parses an HTTP response from a Issue209WithResponse call
+func ParseIssue209Response(rsp *http.Response) (*Issue209Response, error) {
+	bodyBytes, err := ioutil.ReadAll(rsp.Body)
+	defer rsp.Body.Close()
+	if err != nil {
+		return nil, err
+	}
+
+	response := &Issue209Response{
+		Body:         bodyBytes,
+		HTTPResponse: rsp,
+	}
+
+	switch {
+	}
+
+	return response, nil
+}
+
 // ParseIssue30Response parses an HTTP response from a Issue30WithResponse call
 func ParseIssue30Response(rsp *http.Response) (*Issue30Response, error) {
 	bodyBytes, err := ioutil.ReadAll(rsp.Body)
@@ -924,6 +1031,9 @@ type ServerInterface interface {
 	// (GET /issues/185)
 	Issue185(ctx echo.Context) error
 
+	// (GET /issues/209/${str})
+	Issue209(ctx echo.Context, str StringInPath) error
+
 	// (GET /issues/30/{fallthrough})
 	Issue30(ctx echo.Context, pFallthrough string) error
 
@@ -966,6 +1076,22 @@ func (w *ServerInterfaceWrapper) Issue185(ctx echo.Context) error {
 	return err
 }
 
+// Issue209 converts echo context to params.
+func (w *ServerInterfaceWrapper) Issue209(ctx echo.Context) error {
+	var err error
+	// ------------- Path parameter "str" -------------
+	var str StringInPath
+
+	err = runtime.BindStyledParameter("simple", false, "str", ctx.Param("str"), &str)
+	if err != nil {
+		return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter str: %s", err))
+	}
+
+	// Invoke the callback with all the unmarshalled arguments
+	err = w.Handler.Issue209(ctx, str)
+	return err
+}
+
 // Issue30 converts echo context to params.
 func (w *ServerInterfaceWrapper) Issue30(ctx echo.Context) error {
 	var err error
@@ -1041,6 +1167,7 @@ func RegisterHandlers(router EchoRouter, si ServerInterface) {
 	router.GET("/ensure-everything-is-referenced", wrapper.EnsureEverythingIsReferenced)
 	router.GET("/issues/127", wrapper.Issue127)
 	router.GET("/issues/185", wrapper.Issue185)
+	router.GET("/issues/209/$:str", wrapper.Issue209)
 	router.GET("/issues/30/:fallthrough", wrapper.Issue30)
 	router.GET("/issues/41/:1param", wrapper.Issue41)
 	router.GET("/issues/9", wrapper.Issue9)
@@ -1050,22 +1177,23 @@ func RegisterHandlers(router EchoRouter, si ServerInterface) {
 // Base64 encoded, gzipped, json marshaled Swagger object
 var swaggerSpec = []string{
 
-	"H4sIAAAAAAAC/7RW32/bNhD+Vw7cgL04lp00WKu3riiGPKwNmgB7aPJAi2eLjXRkyWMSwdD/PpCyIqWW",
-	"vXVpnyxLvLvv++4Xt6IwtTWExF7kW+GLEmuZHs+vWDr2f2suP4R6hS6+VOgLpy1rQyIX16X20JkAyRrB",
-	"JxN40FyCBOrMZoIbiyIXZvUFCxbtTLyl5rqxuBT5dvh3eihAaUKlYIUgCTQxurUscNtGR++CZ1NfsdO0",
-	"uU5RtmJtXC1Z5KJIH4f4Ph2LZn8iodPFxw5Qvt1H+CFUlVxVeOmMRccakyb22T+TYMpq5GAI0X98S6r3",
-	"Fc/R0zO7gBPQHH4N2qGadNp//D6nz7x+Hp6n/d3u5Ss60LQ2E/lBz1BIjx7WxsG9dNoED9r7kF4FUmDu",
-	"0QHrGudwWaH0CFIpkMC9bTS9IUkNrMIG1voR1fyGYto0R05dlCt096mY7tH5LvpyvpgvOq2RpNUiF2fz",
-	"xXwpZsJKLlOOMiQfHJ7gPbqGS02bE+1PHK7RIRWdzBvkA6WHpKzRxICP2rMHb4BLyTA0DRSSYmkWDiWj",
-	"Ak3ApfY35C0WIEkBGY4HrAuEKvGKNSRjmAslcvE+AXz/hO/CfxrQxRR5a8h3FXe6WMSfwhAjJdDS2koX",
-	"yVv2xUfkfRPv16scuk786nAtcvFLNlDJds2fPXVnO+ttTv+jzWm0KSaa8pjtXhPHgturwTbVYdbVVrY8",
-	"/f1g6v6SdwhRVAjkg7XGxcwk0R4ZomMPytBvDNYh1pZhOJW+zifSdBHjxqgvTMkxIZ6PpUh37Ouxrl7i",
-	"KpLPaunulHmgFztq5EvQRDcK1zJU/BPF+0GMv6281+eHh0ZjETbRPjGAhxIJ+k2Q9dMWhrYE6RD68X24",
-	"7F6f74Y1ev7DqOaHiTax5jq2oxqP8MYCnC2y7VpWFZfOhE3Z7svwCX2c1grusHkwTo13uHWYRnyclHFf",
-	"xOjp8rDrup2uEyqcLcQ+rjjqnayR0XmRf94KHQHE8S9mIroVuRiBFeNV2C3LQahv1+btiPSrZbZdplDt",
-	"wexf9khGlyFNm+469HQZmmD2qltZ/8aji3+UwrFc71/o2vb2aKbfHKT6rtJIDAmQT0MTNBXGOSy4auJz",
-	"FRSqdCvY1W0nw8qoJq7FGxr4Hqz7Nwdk+RrQNaP8GvN9ef3fvbQbXGMlPu66OzETU53TzkRqhx2D4CqR",
-	"i5LZ5lm2u7nEu9BcIdpa2rnUor1t/wkAAP//DG3tepoLAAA=",
+	"H4sIAAAAAAAC/7RX32/bNhD+Vw5cgb24lu00WKO3rCiGPKwNmgB7aPJAi2eLjUSy5CmJYOh/H46yLXmW",
+	"vGbpniKZuh/fd98dLxuR2dJZg4aCSDfCSS9LJPTx7Ya8Nusrcy0p53eFIfPakbZGpOISQjwHJymHvaWY",
+	"CM3H/KuYCCNLFKkIxAcev1faoxIp+QonImQ5lpJdU+22n2mzFk3T7A5jIuc3JD2FvzTln6pyif44m9tc",
+	"B2hNgGNCiCbwpCkHCaY1m+wC2eU3zEg0E3Fp6tva4Vykm+5tMRYgt1WhYIkgDWhD6Fcyw03Djj5UgWzZ",
+	"cnYbo2zEyvpSkkhFFg+7+DugE/EHGvQ6+9wm1FHRZfipKgq5LPDaW4eeNLalOnizMU1ZDHA52R9eGrXz",
+	"xd+Z/XNbjSO7rlyb8cOXOT3w+rV7HvZ3f1QvdqDNyg7UBwNBJgMGWFkPj9JrWwXQIVTxp8oosI/ogXSJ",
+	"U7guUAYEqRRIoJ0tm94ZaWpYVmtY6WdU0zvDZdPEmNooN+gfo5ge0Yc2+nw6m85artFIp0Uqzqaz6VxM",
+	"YiPEGiVoQuXxLT6irynXZv1Wh7ceV+jRZC3Na6QR6aFRzmpDgM86UIBggXJJ0DUwZNKwNDOPklCBNkC5",
+	"DncmOMxAGgXGEn/gfGVQRVysIclhrpRIxceY4Md9flfhS5cdlyg4a0KruMVsxn8yawhNTFo6V+gseku+",
+	"Bc580+vwQ73KruvEG48rkYpfkg5Ksm3+ZN+dzWRns/hBmwXbZANNecr2qIlZcEcabKIOk1ZbyXzx22jp",
+	"/pQPCEwqVCZUzlnPlYmkPROw4wDKml8JnEcsHUH3VTydDpTpiuNy1FeW5BQRh2OJ4fZ9PZfFa1wx+KSU",
+	"/kHZJ/NqR7V8TTbsRuFKVgX9j+T9JMT/VN778/GhUTuENdtHBPCUo4HdTZDspi10bQnSI+zG97js3p9v",
+	"hzUG+t2q+qeRNnDNtWh7Guf0+gQsZhfJm00g34zy8CHH7CGAXnUrSgtVYVbIjoKiHga8mF2I4xwmB6vS",
+	"12Fk3SfJwSrV3PcgnM2SzUoWBeXeVuu8OUbwBQNfOAoesH6yXvXXEOcx3lI87PnKYwLj/rMdHFtKBnCd",
+	"zX4E1sAq10v2RStdH/S7ebKZx1DjhbveZdLb53jdjBvdfp8bQPauvXX/DUcb/ySEU3I93kmb5v6kWC/G",
+	"NVpoNNQKNMS5D9pk1nvMqKj5uagUqrjYbFuvpWFpVc03+53p8I627sUILd8r9HWvvta+rK7/eRxsZ2+f",
+	"ic/bARWRiaHm5/8M4v7VIqh8IVKRE7k0SbbLF69zU4XoSummUnO//R0AAP//Wanza+kMAAA=",
 }
 
 // GetSwagger returns the Swagger specification corresponding to the generated code
diff --git a/internal/test/schemas/schemas.yaml b/internal/test/schemas/schemas.yaml
index 4c2e375..3efb89d 100644
--- a/internal/test/schemas/schemas.yaml
+++ b/internal/test/schemas/schemas.yaml
@@ -104,6 +104,14 @@ paths:
           application/json:
             schema:
               $ref: "#/components/schemas/NullableProperties"
+  /issues/209/${str}:
+    parameters:
+      - $ref: '#/components/parameters/StringInPath'
+    get:
+      operationId: Issue209
+      description: Checks if parameters are declared properly
+
+
 components:
   schemas:
     GenericObject:
@@ -133,3 +141,11 @@ components:
     5StartsWithNumber:
       type: object
       description: This schema name starts with a number
+  parameters:
+    StringInPath:
+      name: str
+      description: A string path parameter
+      in: path
+      required: true
+      schema:
+        type: string
diff --git a/internal/test/server/server.gen.go b/internal/test/server/server.gen.go
index 9b68f51..26e4923 100644
--- a/internal/test/server/server.gen.go
+++ b/internal/test/server/server.gen.go
@@ -4,7 +4,6 @@
 package server
 
 import (
-	"context"
 	"fmt"
 	"github.com/deepmap/oapi-codegen/pkg/runtime"
 	openapi_types "github.com/deepmap/oapi-codegen/pkg/types"
@@ -126,271 +125,243 @@ type CreateResource2JSONRequestBody CreateResource2JSONBody
 // UpdateResource3RequestBody defines body for UpdateResource3 for application/json ContentType.
 type UpdateResource3JSONRequestBody UpdateResource3JSONBody
 
+// ServerInterface represents all server handlers.
 type ServerInterface interface {
-	// get every type optional (GET /every-type-optional)
+	// get every type optional
+	// (GET /every-type-optional)
 	GetEveryTypeOptional(w http.ResponseWriter, r *http.Request)
-	// Get resource via simple path (GET /get-simple)
+	// Get resource via simple path
+	// (GET /get-simple)
 	GetSimple(w http.ResponseWriter, r *http.Request)
-	// Getter with referenced parameter and referenced response (GET /get-with-args)
-	GetWithArgs(w http.ResponseWriter, r *http.Request)
-	// Getter with referenced parameter and referenced response (GET /get-with-references/{global_argument}/{argument})
-	GetWithReferences(w http.ResponseWriter, r *http.Request)
-	// Get an object by ID (GET /get-with-type/{content_type})
-	GetWithContentType(w http.ResponseWriter, r *http.Request)
-	// get with reserved keyword (GET /reserved-keyword)
+	// Getter with referenced parameter and referenced response
+	// (GET /get-with-args)
+	GetWithArgs(w http.ResponseWriter, r *http.Request, params GetWithArgsParams)
+	// Getter with referenced parameter and referenced response
+	// (GET /get-with-references/{global_argument}/{argument})
+	GetWithReferences(w http.ResponseWriter, r *http.Request, globalArgument int64, argument Argument)
+	// Get an object by ID
+	// (GET /get-with-type/{content_type})
+	GetWithContentType(w http.ResponseWriter, r *http.Request, contentType string)
+	// get with reserved keyword
+	// (GET /reserved-keyword)
 	GetReservedKeyword(w http.ResponseWriter, r *http.Request)
-	// Create a resource (POST /resource/{argument})
-	CreateResource(w http.ResponseWriter, r *http.Request)
-	// Create a resource with inline parameter (POST /resource2/{inline_argument})
-	CreateResource2(w http.ResponseWriter, r *http.Request)
-	// Update a resource with inline body. The parameter name is a reservedkeyword, so make sure that gets prefixed to avoid syntax errors (PUT /resource3/{fallthrough})
-	UpdateResource3(w http.ResponseWriter, r *http.Request)
-	// get response with reference (GET /response-with-reference)
+	// Create a resource
+	// (POST /resource/{argument})
+	CreateResource(w http.ResponseWriter, r *http.Request, argument Argument)
+	// Create a resource with inline parameter
+	// (POST /resource2/{inline_argument})
+	CreateResource2(w http.ResponseWriter, r *http.Request, inlineArgument int, params CreateResource2Params)
+	// Update a resource with inline body. The parameter name is a reserved
+	// keyword, so make sure that gets prefixed to avoid syntax errors
+	// (PUT /resource3/{fallthrough})
+	UpdateResource3(w http.ResponseWriter, r *http.Request, pFallthrough int)
+	// get response with reference
+	// (GET /response-with-reference)
 	GetResponseWithReference(w http.ResponseWriter, r *http.Request)
 }
 
+// ServerInterfaceWrapper converts contexts to parameters.
+type ServerInterfaceWrapper struct {
+	Handler ServerInterface
+}
+
 // GetEveryTypeOptional operation middleware
-func GetEveryTypeOptionalCtx(next http.Handler) http.Handler {
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		ctx := r.Context()
+func (siw *ServerInterfaceWrapper) GetEveryTypeOptional(w http.ResponseWriter, r *http.Request) {
+	ctx := r.Context()
 
-		next.ServeHTTP(w, r.WithContext(ctx))
-	})
+	siw.Handler.GetEveryTypeOptional(w, r.WithContext(ctx))
 }
 
 // GetSimple operation middleware
-func GetSimpleCtx(next http.Handler) http.Handler {
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		ctx := r.Context()
-
-		next.ServeHTTP(w, r.WithContext(ctx))
-	})
-}
+func (siw *ServerInterfaceWrapper) GetSimple(w http.ResponseWriter, r *http.Request) {
+	ctx := r.Context()
 
-// ParamsForGetWithArgs operation parameters from context
-func ParamsForGetWithArgs(ctx context.Context) *GetWithArgsParams {
-	return ctx.Value("GetWithArgsParams").(*GetWithArgsParams)
+	siw.Handler.GetSimple(w, r.WithContext(ctx))
 }
 
 // GetWithArgs operation middleware
-func GetWithArgsCtx(next http.Handler) http.Handler {
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		ctx := r.Context()
+func (siw *ServerInterfaceWrapper) GetWithArgs(w http.ResponseWriter, r *http.Request) {
+	ctx := r.Context()
 
-		var err error
+	var err error
 
-		// Parameter object where we will unmarshal all parameters from the context
-		var params GetWithArgsParams
+	// Parameter object where we will unmarshal all parameters from the context
+	var params GetWithArgsParams
 
-		// ------------- Optional query parameter "optional_argument" -------------
-		if paramValue := r.URL.Query().Get("optional_argument"); paramValue != "" {
+	// ------------- Optional query parameter "optional_argument" -------------
+	if paramValue := r.URL.Query().Get("optional_argument"); paramValue != "" {
 
-		}
+	}
 
-		err = runtime.BindQueryParameter("form", true, false, "optional_argument", r.URL.Query(), &params.OptionalArgument)
-		if err != nil {
-			http.Error(w, fmt.Sprintf("Invalid format for parameter optional_argument: %s", err), http.StatusBadRequest)
-			return
-		}
+	err = runtime.BindQueryParameter("form", true, false, "optional_argument", r.URL.Query(), &params.OptionalArgument)
+	if err != nil {
+		http.Error(w, fmt.Sprintf("Invalid format for parameter optional_argument: %s", err), http.StatusBadRequest)
+		return
+	}
+
+	// ------------- Required query parameter "required_argument" -------------
+	if paramValue := r.URL.Query().Get("required_argument"); paramValue != "" {
+
+	} else {
+		http.Error(w, "Query argument required_argument is required, but not found", http.StatusBadRequest)
+		return
+	}
 
-		// ------------- Required query parameter "required_argument" -------------
-		if paramValue := r.URL.Query().Get("required_argument"); paramValue != "" {
+	err = runtime.BindQueryParameter("form", true, true, "required_argument", r.URL.Query(), &params.RequiredArgument)
+	if err != nil {
+		http.Error(w, fmt.Sprintf("Invalid format for parameter required_argument: %s", err), http.StatusBadRequest)
+		return
+	}
 
-		} else {
-			http.Error(w, "Query argument required_argument is required, but not found", http.StatusBadRequest)
+	headers := r.Header
+
+	// ------------- Optional header parameter "header_argument" -------------
+	if valueList, found := headers[http.CanonicalHeaderKey("header_argument")]; found {
+		var HeaderArgument int32
+		n := len(valueList)
+		if n != 1 {
+			http.Error(w, fmt.Sprintf("Expected one value for header_argument, got %d", n), http.StatusBadRequest)
 			return
 		}
 
-		err = runtime.BindQueryParameter("form", true, true, "required_argument", r.URL.Query(), &params.RequiredArgument)
+		err = runtime.BindStyledParameter("simple", false, "header_argument", valueList[0], &HeaderArgument)
 		if err != nil {
-			http.Error(w, fmt.Sprintf("Invalid format for parameter required_argument: %s", err), http.StatusBadRequest)
+			http.Error(w, fmt.Sprintf("Invalid format for parameter header_argument: %s", err), http.StatusBadRequest)
 			return
 		}
 
-		headers := r.Header
-
-		// ------------- Optional header parameter "header_argument" -------------
-		if valueList, found := headers[http.CanonicalHeaderKey("header_argument")]; found {
-			var HeaderArgument int32
-			n := len(valueList)
-			if n != 1 {
-				http.Error(w, fmt.Sprintf("Expected one value for header_argument, got %d", n), http.StatusBadRequest)
-				return
-			}
-
-			err = runtime.BindStyledParameter("simple", false, "header_argument", valueList[0], &HeaderArgument)
-			if err != nil {
-				http.Error(w, fmt.Sprintf("Invalid format for parameter header_argument: %s", err), http.StatusBadRequest)
-				return
-			}
+		params.HeaderArgument = &HeaderArgument
 
-			params.HeaderArgument = &HeaderArgument
+	}
 
-		}
-
-		ctx = context.WithValue(ctx, "GetWithArgsParams", &params)
-
-		next.ServeHTTP(w, r.WithContext(ctx))
-	})
+	siw.Handler.GetWithArgs(w, r.WithContext(ctx), params)
 }
 
 // GetWithReferences operation middleware
-func GetWithReferencesCtx(next http.Handler) http.Handler {
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		ctx := r.Context()
+func (siw *ServerInterfaceWrapper) GetWithReferences(w http.ResponseWriter, r *http.Request) {
+	ctx := r.Context()
 
-		var err error
+	var err error
 
-		// ------------- Path parameter "global_argument" -------------
-		var globalArgument int64
-
-		err = runtime.BindStyledParameter("simple", false, "global_argument", chi.URLParam(r, "global_argument"), &globalArgument)
-		if err != nil {
-			http.Error(w, fmt.Sprintf("Invalid format for parameter global_argument: %s", err), http.StatusBadRequest)
-			return
-		}
+	// ------------- Path parameter "global_argument" -------------
+	var globalArgument int64
 
-		ctx = context.WithValue(ctx, "globalArgument", globalArgument)
-		// ------------- Path parameter "argument" -------------
-		var argument Argument
+	err = runtime.BindStyledParameter("simple", false, "global_argument", chi.URLParam(r, "global_argument"), &globalArgument)
+	if err != nil {
+		http.Error(w, fmt.Sprintf("Invalid format for parameter global_argument: %s", err), http.StatusBadRequest)
+		return
+	}
 
-		err = runtime.BindStyledParameter("simple", false, "argument", chi.URLParam(r, "argument"), &argument)
-		if err != nil {
-			http.Error(w, fmt.Sprintf("Invalid format for parameter argument: %s", err), http.StatusBadRequest)
-			return
-		}
+	// ------------- Path parameter "argument" -------------
+	var argument Argument
 
-		ctx = context.WithValue(ctx, "argument", argument)
+	err = runtime.BindStyledParameter("simple", false, "argument", chi.URLParam(r, "argument"), &argument)
+	if err != nil {
+		http.Error(w, fmt.Sprintf("Invalid format for parameter argument: %s", err), http.StatusBadRequest)
+		return
+	}
 
-		next.ServeHTTP(w, r.WithContext(ctx))
-	})
+	siw.Handler.GetWithReferences(w, r.WithContext(ctx), globalArgument, argument)
 }
 
 // GetWithContentType operation middleware
-func GetWithContentTypeCtx(next http.Handler) http.Handler {
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		ctx := r.Context()
+func (siw *ServerInterfaceWrapper) GetWithContentType(w http.ResponseWriter, r *http.Request) {
+	ctx := r.Context()
 
-		var err error
+	var err error
 
-		// ------------- Path parameter "content_type" -------------
-		var contentType string
+	// ------------- Path parameter "content_type" -------------
+	var contentType string
 
-		err = runtime.BindStyledParameter("simple", false, "content_type", chi.URLParam(r, "content_type"), &contentType)
-		if err != nil {
-			http.Error(w, fmt.Sprintf("Invalid format for parameter content_type: %s", err), http.StatusBadRequest)
-			return
-		}
-
-		ctx = context.WithValue(ctx, "contentType", contentType)
+	err = runtime.BindStyledParameter("simple", false, "content_type", chi.URLParam(r, "content_type"), &contentType)
+	if err != nil {
+		http.Error(w, fmt.Sprintf("Invalid format for parameter content_type: %s", err), http.StatusBadRequest)
+		return
+	}
 
-		next.ServeHTTP(w, r.WithContext(ctx))
-	})
+	siw.Handler.GetWithContentType(w, r.WithContext(ctx), contentType)
 }
 
 // GetReservedKeyword operation middleware
-func GetReservedKeywordCtx(next http.Handler) http.Handler {
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		ctx := r.Context()
+func (siw *ServerInterfaceWrapper) GetReservedKeyword(w http.ResponseWriter, r *http.Request) {
+	ctx := r.Context()
 
-		next.ServeHTTP(w, r.WithContext(ctx))
-	})
+	siw.Handler.GetReservedKeyword(w, r.WithContext(ctx))
 }
 
 // CreateResource operation middleware
-func CreateResourceCtx(next http.Handler) http.Handler {
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		ctx := r.Context()
+func (siw *ServerInterfaceWrapper) CreateResource(w http.ResponseWriter, r *http.Request) {
+	ctx := r.Context()
 
-		var err error
-
-		// ------------- Path parameter "argument" -------------
-		var argument Argument
-
-		err = runtime.BindStyledParameter("simple", false, "argument", chi.URLParam(r, "argument"), &argument)
-		if err != nil {
-			http.Error(w, fmt.Sprintf("Invalid format for parameter argument: %s", err), http.StatusBadRequest)
-			return
-		}
+	var err error
 
-		ctx = context.WithValue(ctx, "argument", argument)
+	// ------------- Path parameter "argument" -------------
+	var argument Argument
 
-		next.ServeHTTP(w, r.WithContext(ctx))
-	})
-}
+	err = runtime.BindStyledParameter("simple", false, "argument", chi.URLParam(r, "argument"), &argument)
+	if err != nil {
+		http.Error(w, fmt.Sprintf("Invalid format for parameter argument: %s", err), http.StatusBadRequest)
+		return
+	}
 
-// ParamsForCreateResource2 operation parameters from context
-func ParamsForCreateResource2(ctx context.Context) *CreateResource2Params {
-	return ctx.Value("CreateResource2Params").(*CreateResource2Params)
+	siw.Handler.CreateResource(w, r.WithContext(ctx), argument)
 }
 
 // CreateResource2 operation middleware
-func CreateResource2Ctx(next http.Handler) http.Handler {
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		ctx := r.Context()
+func (siw *ServerInterfaceWrapper) CreateResource2(w http.ResponseWriter, r *http.Request) {
+	ctx := r.Context()
 
-		var err error
-
-		// ------------- Path parameter "inline_argument" -------------
-		var inlineArgument int
-
-		err = runtime.BindStyledParameter("simple", false, "inline_argument", chi.URLParam(r, "inline_argument"), &inlineArgument)
-		if err != nil {
-			http.Error(w, fmt.Sprintf("Invalid format for parameter inline_argument: %s", err), http.StatusBadRequest)
-			return
-		}
+	var err error
 
-		ctx = context.WithValue(ctx, "inlineArgument", inlineArgument)
+	// ------------- Path parameter "inline_argument" -------------
+	var inlineArgument int
 
-		// Parameter object where we will unmarshal all parameters from the context
-		var params CreateResource2Params
+	err = runtime.BindStyledParameter("simple", false, "inline_argument", chi.URLParam(r, "inline_argument"), &inlineArgument)
+	if err != nil {
+		http.Error(w, fmt.Sprintf("Invalid format for parameter inline_argument: %s", err), http.StatusBadRequest)
+		return
+	}
 
-		// ------------- Optional query parameter "inline_query_argument" -------------
-		if paramValue := r.URL.Query().Get("inline_query_argument"); paramValue != "" {
+	// Parameter object where we will unmarshal all parameters from the context
+	var params CreateResource2Params
 
-		}
+	// ------------- Optional query parameter "inline_query_argument" -------------
+	if paramValue := r.URL.Query().Get("inline_query_argument"); paramValue != "" {
 
-		err = runtime.BindQueryParameter("form", true, false, "inline_query_argument", r.URL.Query(), &params.InlineQueryArgument)
-		if err != nil {
-			http.Error(w, fmt.Sprintf("Invalid format for parameter inline_query_argument: %s", err), http.StatusBadRequest)
-			return
-		}
+	}
 
-		ctx = context.WithValue(ctx, "CreateResource2Params", &params)
+	err = runtime.BindQueryParameter("form", true, false, "inline_query_argument", r.URL.Query(), &params.InlineQueryArgument)
+	if err != nil {
+		http.Error(w, fmt.Sprintf("Invalid format for parameter inline_query_argument: %s", err), http.StatusBadRequest)
+		return
+	}
 
-		next.ServeHTTP(w, r.WithContext(ctx))
-	})
+	siw.Handler.CreateResource2(w, r.WithContext(ctx), inlineArgument, params)
 }
 
 // UpdateResource3 operation middleware
-func UpdateResource3Ctx(next http.Handler) http.Handler {
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		ctx := r.Context()
+func (siw *ServerInterfaceWrapper) UpdateResource3(w http.ResponseWriter, r *http.Request) {
+	ctx := r.Context()
 
-		var err error
+	var err error
 
-		// ------------- Path parameter "fallthrough" -------------
-		var pFallthrough int
+	// ------------- Path parameter "fallthrough" -------------
+	var pFallthrough int
 
-		err = runtime.BindStyledParameter("simple", false, "fallthrough", chi.URLParam(r, "fallthrough"), &pFallthrough)
-		if err != nil {
-			http.Error(w, fmt.Sprintf("Invalid format for parameter fallthrough: %s", err), http.StatusBadRequest)
-			return
-		}
-
-		ctx = context.WithValue(ctx, "pFallthrough", pFallthrough)
+	err = runtime.BindStyledParameter("simple", false, "fallthrough", chi.URLParam(r, "fallthrough"), &pFallthrough)
+	if err != nil {
+		http.Error(w, fmt.Sprintf("Invalid format for parameter fallthrough: %s", err), http.StatusBadRequest)
+		return
+	}
 
-		next.ServeHTTP(w, r.WithContext(ctx))
-	})
+	siw.Handler.UpdateResource3(w, r.WithContext(ctx), pFallthrough)
 }
 
 // GetResponseWithReference operation middleware
-func GetResponseWithReferenceCtx(next http.Handler) http.Handler {
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		ctx := r.Context()
+func (siw *ServerInterfaceWrapper) GetResponseWithReference(w http.ResponseWriter, r *http.Request) {
+	ctx := r.Context()
 
-		next.ServeHTTP(w, r.WithContext(ctx))
-	})
+	siw.Handler.GetResponseWithReference(w, r.WithContext(ctx))
 }
 
 // Handler creates http.Handler with routing matching OpenAPI spec.
@@ -400,45 +371,39 @@ func Handler(si ServerInterface) http.Handler {
 
 // HandlerFromMux creates http.Handler with routing matching OpenAPI spec based on the provided mux.
 func HandlerFromMux(si ServerInterface, r chi.Router) http.Handler {
+	wrapper := ServerInterfaceWrapper{
+		Handler: si,
+	}
+
 	r.Group(func(r chi.Router) {
-		r.Use(GetEveryTypeOptionalCtx)
-		r.Get("/every-type-optional", si.GetEveryTypeOptional)
+		r.Get("/every-type-optional", wrapper.GetEveryTypeOptional)
 	})
 	r.Group(func(r chi.Router) {
-		r.Use(GetSimpleCtx)
-		r.Get("/get-simple", si.GetSimple)
+		r.Get("/get-simple", wrapper.GetSimple)
 	})
 	r.Group(func(r chi.Router) {
-		r.Use(GetWithArgsCtx)
-		r.Get("/get-with-args", si.GetWithArgs)
+		r.Get("/get-with-args", wrapper.GetWithArgs)
 	})
 	r.Group(func(r chi.Router) {
-		r.Use(GetWithReferencesCtx)
-		r.Get("/get-with-references/{global_argument}/{argument}", si.GetWithReferences)
+		r.Get("/get-with-references/{global_argument}/{argument}", wrapper.GetWithReferences)
 	})
 	r.Group(func(r chi.Router) {
-		r.Use(GetWithContentTypeCtx)
-		r.Get("/get-with-type/{content_type}", si.GetWithContentType)
+		r.Get("/get-with-type/{content_type}", wrapper.GetWithContentType)
 	})
 	r.Group(func(r chi.Router) {
-		r.Use(GetReservedKeywordCtx)
-		r.Get("/reserved-keyword", si.GetReservedKeyword)
+		r.Get("/reserved-keyword", wrapper.GetReservedKeyword)
 	})
 	r.Group(func(r chi.Router) {
-		r.Use(CreateResourceCtx)
-		r.Post("/resource/{argument}", si.CreateResource)
+		r.Post("/resource/{argument}", wrapper.CreateResource)
 	})
 	r.Group(func(r chi.Router) {
-		r.Use(CreateResource2Ctx)
-		r.Post("/resource2/{inline_argument}", si.CreateResource2)
+		r.Post("/resource2/{inline_argument}", wrapper.CreateResource2)
 	})
 	r.Group(func(r chi.Router) {
-		r.Use(UpdateResource3Ctx)
-		r.Put("/resource3/{fallthrough}", si.UpdateResource3)
+		r.Put("/resource3/{fallthrough}", wrapper.UpdateResource3)
 	})
 	r.Group(func(r chi.Router) {
-		r.Use(GetResponseWithReferenceCtx)
-		r.Get("/response-with-reference", si.GetResponseWithReference)
+		r.Get("/response-with-reference", wrapper.GetResponseWithReference)
 	})
 
 	return r
diff --git a/internal/test/server/server_moq.gen.go b/internal/test/server/server_moq.gen.go
index 0736acc..b3194e7 100644
--- a/internal/test/server/server_moq.gen.go
+++ b/internal/test/server/server_moq.gen.go
@@ -31,10 +31,10 @@ var _ ServerInterface = &ServerInterfaceMock{}
 //
 //         // make and configure a mocked ServerInterface
 //         mockedServerInterface := &ServerInterfaceMock{
-//             CreateResourceFunc: func(w http.ResponseWriter, r *http.Request)  {
+//             CreateResourceFunc: func(w http.ResponseWriter, r *http.Request, argument Argument)  {
 // 	               panic("mock out the CreateResource method")
 //             },
-//             CreateResource2Func: func(w http.ResponseWriter, r *http.Request)  {
+//             CreateResource2Func: func(w http.ResponseWriter, r *http.Request, inlineArgument int, params CreateResource2Params)  {
 // 	               panic("mock out the CreateResource2 method")
 //             },
 //             GetEveryTypeOptionalFunc: func(w http.ResponseWriter, r *http.Request)  {
@@ -49,16 +49,16 @@ var _ ServerInterface = &ServerInterfaceMock{}
 //             GetSimpleFunc: func(w http.ResponseWriter, r *http.Request)  {
 // 	               panic("mock out the GetSimple method")
 //             },
-//             GetWithArgsFunc: func(w http.ResponseWriter, r *http.Request)  {
+//             GetWithArgsFunc: func(w http.ResponseWriter, r *http.Request, params GetWithArgsParams)  {
 // 	               panic("mock out the GetWithArgs method")
 //             },
-//             GetWithContentTypeFunc: func(w http.ResponseWriter, r *http.Request)  {
+//             GetWithContentTypeFunc: func(w http.ResponseWriter, r *http.Request, contentType string)  {
 // 	               panic("mock out the GetWithContentType method")
 //             },
-//             GetWithReferencesFunc: func(w http.ResponseWriter, r *http.Request)  {
+//             GetWithReferencesFunc: func(w http.ResponseWriter, r *http.Request, globalArgument int64, argument Argument)  {
 // 	               panic("mock out the GetWithReferences method")
 //             },
-//             UpdateResource3Func: func(w http.ResponseWriter, r *http.Request)  {
+//             UpdateResource3Func: func(w http.ResponseWriter, r *http.Request, pFallthrough int)  {
 // 	               panic("mock out the UpdateResource3 method")
 //             },
 //         }
@@ -69,10 +69,10 @@ var _ ServerInterface = &ServerInterfaceMock{}
 //     }
 type ServerInterfaceMock struct {
 	// CreateResourceFunc mocks the CreateResource method.
-	CreateResourceFunc func(w http.ResponseWriter, r *http.Request)
+	CreateResourceFunc func(w http.ResponseWriter, r *http.Request, argument Argument)
 
 	// CreateResource2Func mocks the CreateResource2 method.
-	CreateResource2Func func(w http.ResponseWriter, r *http.Request)
+	CreateResource2Func func(w http.ResponseWriter, r *http.Request, inlineArgument int, params CreateResource2Params)
 
 	// GetEveryTypeOptionalFunc mocks the GetEveryTypeOptional method.
 	GetEveryTypeOptionalFunc func(w http.ResponseWriter, r *http.Request)
@@ -87,16 +87,16 @@ type ServerInterfaceMock struct {
 	GetSimpleFunc func(w http.ResponseWriter, r *http.Request)
 
 	// GetWithArgsFunc mocks the GetWithArgs method.
-	GetWithArgsFunc func(w http.ResponseWriter, r *http.Request)
+	GetWithArgsFunc func(w http.ResponseWriter, r *http.Request, params GetWithArgsParams)
 
 	// GetWithContentTypeFunc mocks the GetWithContentType method.
-	GetWithContentTypeFunc func(w http.ResponseWriter, r *http.Request)
+	GetWithContentTypeFunc func(w http.ResponseWriter, r *http.Request, contentType string)
 
 	// GetWithReferencesFunc mocks the GetWithReferences method.
-	GetWithReferencesFunc func(w http.ResponseWriter, r *http.Request)
+	GetWithReferencesFunc func(w http.ResponseWriter, r *http.Request, globalArgument int64, argument Argument)
 
 	// UpdateResource3Func mocks the UpdateResource3 method.
-	UpdateResource3Func func(w http.ResponseWriter, r *http.Request)
+	UpdateResource3Func func(w http.ResponseWriter, r *http.Request, pFallthrough int)
 
 	// calls tracks calls to the methods.
 	calls struct {
@@ -106,6 +106,8 @@ type ServerInterfaceMock struct {
 			W http.ResponseWriter
 			// R is the r argument value.
 			R *http.Request
+			// Argument is the argument argument value.
+			Argument Argument
 		}
 		// CreateResource2 holds details about calls to the CreateResource2 method.
 		CreateResource2 []struct {
@@ -113,6 +115,10 @@ type ServerInterfaceMock struct {
 			W http.ResponseWriter
 			// R is the r argument value.
 			R *http.Request
+			// InlineArgument is the inlineArgument argument value.
+			InlineArgument int
+			// Params is the params argument value.
+			Params CreateResource2Params
 		}
 		// GetEveryTypeOptional holds details about calls to the GetEveryTypeOptional method.
 		GetEveryTypeOptional []struct {
@@ -148,6 +154,8 @@ type ServerInterfaceMock struct {
 			W http.ResponseWriter
 			// R is the r argument value.
 			R *http.Request
+			// Params is the params argument value.
+			Params GetWithArgsParams
 		}
 		// GetWithContentType holds details about calls to the GetWithContentType method.
 		GetWithContentType []struct {
@@ -155,6 +163,8 @@ type ServerInterfaceMock struct {
 			W http.ResponseWriter
 			// R is the r argument value.
 			R *http.Request
+			// ContentType is the contentType argument value.
+			ContentType string
 		}
 		// GetWithReferences holds details about calls to the GetWithReferences method.
 		GetWithReferences []struct {
@@ -162,6 +172,10 @@ type ServerInterfaceMock struct {
 			W http.ResponseWriter
 			// R is the r argument value.
 			R *http.Request
+			// GlobalArgument is the globalArgument argument value.
+			GlobalArgument int64
+			// Argument is the argument argument value.
+			Argument Argument
 		}
 		// UpdateResource3 holds details about calls to the UpdateResource3 method.
 		UpdateResource3 []struct {
@@ -169,38 +183,44 @@ type ServerInterfaceMock struct {
 			W http.ResponseWriter
 			// R is the r argument value.
 			R *http.Request
+			// PFallthrough is the pFallthrough argument value.
+			PFallthrough int
 		}
 	}
 }
 
 // CreateResource calls CreateResourceFunc.
-func (mock *ServerInterfaceMock) CreateResource(w http.ResponseWriter, r *http.Request) {
+func (mock *ServerInterfaceMock) CreateResource(w http.ResponseWriter, r *http.Request, argument Argument) {
 	if mock.CreateResourceFunc == nil {
 		panic("ServerInterfaceMock.CreateResourceFunc: method is nil but ServerInterface.CreateResource was just called")
 	}
 	callInfo := struct {
-		W http.ResponseWriter
-		R *http.Request
+		W        http.ResponseWriter
+		R        *http.Request
+		Argument Argument
 	}{
-		W: w,
-		R: r,
+		W:        w,
+		R:        r,
+		Argument: argument,
 	}
 	lockServerInterfaceMockCreateResource.Lock()
 	mock.calls.CreateResource = append(mock.calls.CreateResource, callInfo)
 	lockServerInterfaceMockCreateResource.Unlock()
-	mock.CreateResourceFunc(w, r)
+	mock.CreateResourceFunc(w, r, argument)
 }
 
 // CreateResourceCalls gets all the calls that were made to CreateResource.
 // Check the length with:
 //     len(mockedServerInterface.CreateResourceCalls())
 func (mock *ServerInterfaceMock) CreateResourceCalls() []struct {
-	W http.ResponseWriter
-	R *http.Request
+	W        http.ResponseWriter
+	R        *http.Request
+	Argument Argument
 } {
 	var calls []struct {
-		W http.ResponseWriter
-		R *http.Request
+		W        http.ResponseWriter
+		R        *http.Request
+		Argument Argument
 	}
 	lockServerInterfaceMockCreateResource.RLock()
 	calls = mock.calls.CreateResource
@@ -209,33 +229,41 @@ func (mock *ServerInterfaceMock) CreateResourceCalls() []struct {
 }
 
 // CreateResource2 calls CreateResource2Func.
-func (mock *ServerInterfaceMock) CreateResource2(w http.ResponseWriter, r *http.Request) {
+func (mock *ServerInterfaceMock) CreateResource2(w http.ResponseWriter, r *http.Request, inlineArgument int, params CreateResource2Params) {
 	if mock.CreateResource2Func == nil {
 		panic("ServerInterfaceMock.CreateResource2Func: method is nil but ServerInterface.CreateResource2 was just called")
 	}
 	callInfo := struct {
-		W http.ResponseWriter
-		R *http.Request
+		W              http.ResponseWriter
+		R              *http.Request
+		InlineArgument int
+		Params         CreateResource2Params
 	}{
-		W: w,
-		R: r,
+		W:              w,
+		R:              r,
+		InlineArgument: inlineArgument,
+		Params:         params,
 	}
 	lockServerInterfaceMockCreateResource2.Lock()
 	mock.calls.CreateResource2 = append(mock.calls.CreateResource2, callInfo)
 	lockServerInterfaceMockCreateResource2.Unlock()
-	mock.CreateResource2Func(w, r)
+	mock.CreateResource2Func(w, r, inlineArgument, params)
 }
 
 // CreateResource2Calls gets all the calls that were made to CreateResource2.
 // Check the length with:
 //     len(mockedServerInterface.CreateResource2Calls())
 func (mock *ServerInterfaceMock) CreateResource2Calls() []struct {
-	W http.ResponseWriter
-	R *http.Request
+	W              http.ResponseWriter
+	R              *http.Request
+	InlineArgument int
+	Params         CreateResource2Params
 } {
 	var calls []struct {
-		W http.ResponseWriter
-		R *http.Request
+		W              http.ResponseWriter
+		R              *http.Request
+		InlineArgument int
+		Params         CreateResource2Params
 	}
 	lockServerInterfaceMockCreateResource2.RLock()
 	calls = mock.calls.CreateResource2
@@ -384,33 +412,37 @@ func (mock *ServerInterfaceMock) GetSimpleCalls() []struct {
 }
 
 // GetWithArgs calls GetWithArgsFunc.
-func (mock *ServerInterfaceMock) GetWithArgs(w http.ResponseWriter, r *http.Request) {
+func (mock *ServerInterfaceMock) GetWithArgs(w http.ResponseWriter, r *http.Request, params GetWithArgsParams) {
 	if mock.GetWithArgsFunc == nil {
 		panic("ServerInterfaceMock.GetWithArgsFunc: method is nil but ServerInterface.GetWithArgs was just called")
 	}
 	callInfo := struct {
-		W http.ResponseWriter
-		R *http.Request
+		W      http.ResponseWriter
+		R      *http.Request
+		Params GetWithArgsParams
 	}{
-		W: w,
-		R: r,
+		W:      w,
+		R:      r,
+		Params: params,
 	}
 	lockServerInterfaceMockGetWithArgs.Lock()
 	mock.calls.GetWithArgs = append(mock.calls.GetWithArgs, callInfo)
 	lockServerInterfaceMockGetWithArgs.Unlock()
-	mock.GetWithArgsFunc(w, r)
+	mock.GetWithArgsFunc(w, r, params)
 }
 
 // GetWithArgsCalls gets all the calls that were made to GetWithArgs.
 // Check the length with:
 //     len(mockedServerInterface.GetWithArgsCalls())
 func (mock *ServerInterfaceMock) GetWithArgsCalls() []struct {
-	W http.ResponseWriter
-	R *http.Request
+	W      http.ResponseWriter
+	R      *http.Request
+	Params GetWithArgsParams
 } {
 	var calls []struct {
-		W http.ResponseWriter
-		R *http.Request
+		W      http.ResponseWriter
+		R      *http.Request
+		Params GetWithArgsParams
 	}
 	lockServerInterfaceMockGetWithArgs.RLock()
 	calls = mock.calls.GetWithArgs
@@ -419,33 +451,37 @@ func (mock *ServerInterfaceMock) GetWithArgsCalls() []struct {
 }
 
 // GetWithContentType calls GetWithContentTypeFunc.
-func (mock *ServerInterfaceMock) GetWithContentType(w http.ResponseWriter, r *http.Request) {
+func (mock *ServerInterfaceMock) GetWithContentType(w http.ResponseWriter, r *http.Request, contentType string) {
 	if mock.GetWithContentTypeFunc == nil {
 		panic("ServerInterfaceMock.GetWithContentTypeFunc: method is nil but ServerInterface.GetWithContentType was just called")
 	}
 	callInfo := struct {
-		W http.ResponseWriter
-		R *http.Request
+		W           http.ResponseWriter
+		R           *http.Request
+		ContentType string
 	}{
-		W: w,
-		R: r,
+		W:           w,
+		R:           r,
+		ContentType: contentType,
 	}
 	lockServerInterfaceMockGetWithContentType.Lock()
 	mock.calls.GetWithContentType = append(mock.calls.GetWithContentType, callInfo)
 	lockServerInterfaceMockGetWithContentType.Unlock()
-	mock.GetWithContentTypeFunc(w, r)
+	mock.GetWithContentTypeFunc(w, r, contentType)
 }
 
 // GetWithContentTypeCalls gets all the calls that were made to GetWithContentType.
 // Check the length with:
 //     len(mockedServerInterface.GetWithContentTypeCalls())
 func (mock *ServerInterfaceMock) GetWithContentTypeCalls() []struct {
-	W http.ResponseWriter
-	R *http.Request
+	W           http.ResponseWriter
+	R           *http.Request
+	ContentType string
 } {
 	var calls []struct {
-		W http.ResponseWriter
-		R *http.Request
+		W           http.ResponseWriter
+		R           *http.Request
+		ContentType string
 	}
 	lockServerInterfaceMockGetWithContentType.RLock()
 	calls = mock.calls.GetWithContentType
@@ -454,33 +490,41 @@ func (mock *ServerInterfaceMock) GetWithContentTypeCalls() []struct {
 }
 
 // GetWithReferences calls GetWithReferencesFunc.
-func (mock *ServerInterfaceMock) GetWithReferences(w http.ResponseWriter, r *http.Request) {
+func (mock *ServerInterfaceMock) GetWithReferences(w http.ResponseWriter, r *http.Request, globalArgument int64, argument Argument) {
 	if mock.GetWithReferencesFunc == nil {
 		panic("ServerInterfaceMock.GetWithReferencesFunc: method is nil but ServerInterface.GetWithReferences was just called")
 	}
 	callInfo := struct {
-		W http.ResponseWriter
-		R *http.Request
+		W              http.ResponseWriter
+		R              *http.Request
+		GlobalArgument int64
+		Argument       Argument
 	}{
-		W: w,
-		R: r,
+		W:              w,
+		R:              r,
+		GlobalArgument: globalArgument,
+		Argument:       argument,
 	}
 	lockServerInterfaceMockGetWithReferences.Lock()
 	mock.calls.GetWithReferences = append(mock.calls.GetWithReferences, callInfo)
 	lockServerInterfaceMockGetWithReferences.Unlock()
-	mock.GetWithReferencesFunc(w, r)
+	mock.GetWithReferencesFunc(w, r, globalArgument, argument)
 }
 
 // GetWithReferencesCalls gets all the calls that were made to GetWithReferences.
 // Check the length with:
 //     len(mockedServerInterface.GetWithReferencesCalls())
 func (mock *ServerInterfaceMock) GetWithReferencesCalls() []struct {
-	W http.ResponseWriter
-	R *http.Request
+	W              http.ResponseWriter
+	R              *http.Request
+	GlobalArgument int64
+	Argument       Argument
 } {
 	var calls []struct {
-		W http.ResponseWriter
-		R *http.Request
+		W              http.ResponseWriter
+		R              *http.Request
+		GlobalArgument int64
+		Argument       Argument
 	}
 	lockServerInterfaceMockGetWithReferences.RLock()
 	calls = mock.calls.GetWithReferences
@@ -489,33 +533,37 @@ func (mock *ServerInterfaceMock) GetWithReferencesCalls() []struct {
 }
 
 // UpdateResource3 calls UpdateResource3Func.
-func (mock *ServerInterfaceMock) UpdateResource3(w http.ResponseWriter, r *http.Request) {
+func (mock *ServerInterfaceMock) UpdateResource3(w http.ResponseWriter, r *http.Request, pFallthrough int) {
 	if mock.UpdateResource3Func == nil {
 		panic("ServerInterfaceMock.UpdateResource3Func: method is nil but ServerInterface.UpdateResource3 was just called")
 	}
 	callInfo := struct {
-		W http.ResponseWriter
-		R *http.Request
+		W            http.ResponseWriter
+		R            *http.Request
+		PFallthrough int
 	}{
-		W: w,
-		R: r,
+		W:            w,
+		R:            r,
+		PFallthrough: pFallthrough,
 	}
 	lockServerInterfaceMockUpdateResource3.Lock()
 	mock.calls.UpdateResource3 = append(mock.calls.UpdateResource3, callInfo)
 	lockServerInterfaceMockUpdateResource3.Unlock()
-	mock.UpdateResource3Func(w, r)
+	mock.UpdateResource3Func(w, r, pFallthrough)
 }
 
 // UpdateResource3Calls gets all the calls that were made to UpdateResource3.
 // Check the length with:
 //     len(mockedServerInterface.UpdateResource3Calls())
 func (mock *ServerInterfaceMock) UpdateResource3Calls() []struct {
-	W http.ResponseWriter
-	R *http.Request
+	W            http.ResponseWriter
+	R            *http.Request
+	PFallthrough int
 } {
 	var calls []struct {
-		W http.ResponseWriter
-		R *http.Request
+		W            http.ResponseWriter
+		R            *http.Request
+		PFallthrough int
 	}
 	lockServerInterfaceMockUpdateResource3.RLock()
 	calls = mock.calls.UpdateResource3
diff --git a/internal/test/server/server_test.go b/internal/test/server/server_test.go
index 31c40c4..de25598 100644
--- a/internal/test/server/server_test.go
+++ b/internal/test/server/server_test.go
@@ -11,12 +11,9 @@ import (
 func TestParameters(t *testing.T) {
 	m := ServerInterfaceMock{}
 
-	m.CreateResource2Func = func(w http.ResponseWriter, r *http.Request) {
-		params := ParamsForCreateResource2(r.Context())
-		arg := r.Context().Value("inlineArgument").(int)
-
+	m.CreateResource2Func = func(w http.ResponseWriter, r *http.Request, inlineArgument int, params CreateResource2Params) {
 		assert.Equal(t, 99, *params.InlineQueryArgument)
-		assert.Equal(t, 1, arg)
+		assert.Equal(t, 1, inlineArgument)
 	}
 
 	h := Handler(&m)
diff --git a/pkg/codegen/extension_test.go b/pkg/codegen/extension_test.go
new file mode 100644
index 0000000..64681a6
--- /dev/null
+++ b/pkg/codegen/extension_test.go
@@ -0,0 +1,50 @@
+package codegen
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func Test_extTypeName(t *testing.T) {
+	type args struct {
+		extPropValue interface{}
+	}
+	tests := []struct {
+		name    string
+		args    args
+		want    string
+		wantErr bool
+	}{
+		{
+			name:    "success",
+			args:    args{json.RawMessage(`"uint64"`)},
+			want:    "uint64",
+			wantErr: false,
+		},
+		{
+			name:    "type conversion error",
+			args:    args{nil},
+			want:    "",
+			wantErr: true,
+		},
+		{
+			name:    "json unmarshal error",
+			args:    args{json.RawMessage("invalid json format")},
+			want:    "",
+			wantErr: true,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got, err := extTypeName(tt.args.extPropValue)
+			if tt.wantErr {
+				assert.Error(t, err)
+				return
+			}
+			assert.NoError(t, err)
+			assert.Equal(t, tt.want, got)
+		})
+	}
+}
diff --git a/pkg/runtime/bindstring_test.go b/pkg/runtime/bindstring_test.go
index 193f54e..8909e81 100644
--- a/pkg/runtime/bindstring_test.go
+++ b/pkg/runtime/bindstring_test.go
@@ -32,13 +32,21 @@ func TestBindStringToObject(t *testing.T) {
 	assert.Error(t, BindStringToObject("foo", &i))
 	assert.Error(t, BindStringToObject("1,2,3", &i))
 
-	var i64 int64
-	assert.NoError(t, BindStringToObject("124", &i64))
-	assert.Equal(t, int64(124), i64)
+	var i8 int8
+	assert.NoError(t, BindStringToObject("12", &i8))
+	assert.Equal(t, int8(12), i8)
 
-	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("5.7", &i8))
+	assert.Error(t, BindStringToObject("foo", &i8))
+	assert.Error(t, BindStringToObject("1,2,3", &i8))
+
+	var i16 int16
+	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))
 
 	var i32 int32
 	assert.NoError(t, BindStringToObject("12", &i32))
@@ -48,6 +56,54 @@ func TestBindStringToObject(t *testing.T) {
 	assert.Error(t, BindStringToObject("foo", &i32))
 	assert.Error(t, BindStringToObject("1,2,3", &i32))
 
+	var i64 int64
+	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))
+
+	var u uint
+	assert.NoError(t, BindStringToObject("5", &u))
+	assert.Equal(t, uint(5), u)
+
+	assert.Error(t, BindStringToObject("5.7", &u))
+	assert.Error(t, BindStringToObject("foo", &u))
+	assert.Error(t, BindStringToObject("1,2,3", &u))
+
+	var u8 uint8
+	assert.NoError(t, BindStringToObject("12", &u8))
+	assert.Equal(t, uint8(12), u8)
+
+	assert.Error(t, BindStringToObject("5.7", &u8))
+	assert.Error(t, BindStringToObject("foo", &u8))
+	assert.Error(t, BindStringToObject("1,2,3", &u8))
+
+	var u16 uint16
+	assert.NoError(t, BindStringToObject("12", &u16))
+	assert.Equal(t, uint16(12), u16)
+
+	assert.Error(t, BindStringToObject("5.7", &u16))
+	assert.Error(t, BindStringToObject("foo", &u16))
+	assert.Error(t, BindStringToObject("1,2,3", &u16))
+
+	var u32 uint32
+	assert.NoError(t, BindStringToObject("12", &u32))
+	assert.Equal(t, uint32(12), u32)
+
+	assert.Error(t, BindStringToObject("5.7", &u32))
+	assert.Error(t, BindStringToObject("foo", &u32))
+	assert.Error(t, BindStringToObject("1,2,3", &u32))
+
+	var u64 uint64
+	assert.NoError(t, BindStringToObject("124", &u64))
+	assert.Equal(t, uint64(124), u64)
+
+	assert.Error(t, BindStringToObject("5.7", &u64))
+	assert.Error(t, BindStringToObject("foo", &u64))
+	assert.Error(t, BindStringToObject("1,2,3", &u64))
+
 	var b bool
 	assert.NoError(t, BindStringToObject("True", &b))
 	assert.Equal(t, true, b)