Repository: deepmap/oapi-codegen
Pull request #242 (2020-10-21 13:38:09)

fix: fixing time styling
This fixes the serialization of time values. 

If a  param with type _time_ has a value with positive timezone, e.g.  `2020-01-01T22:00:00+02:00`, it is unescaped by `url.ParseQuery` in the generated code into the `2020-01-01T22:00:00 02:00` string (missing the + char) and then wrongly escaped with %20 at that place later by `queryValues.Encode() `.



Patch:
diff --git a/README.md b/README.md
index a5e3468..c9a036d 100644
--- a/README.md
+++ b/README.md
@@ -470,6 +470,26 @@ 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.
 
+Since `go generate` commands must be one line, all the options above can make
+them pretty unwieldy, so one it's possible to specify all of them in a configuration
+file via the `--config` option. Please see the test under `/internal/test/externalref/`
+for an example. The structure of the file is as follows:
+    
+```yaml
+output:
+  externalref.gen.go
+package: externalref
+generate:
+  - types
+  - skip-prune
+import-mapping:
+  ./packageA/spec.yaml: github.com/deepmap/oapi-codegen/internal/test/externalref/packageA
+  ./packageB/spec.yaml: github.com/deepmap/oapi-codegen/internal/test/externalref/packageB
+```
+
+Have a look at `cmd/oapi-codegen/oapi-codegen.go` to see all the fields on the
+configuration structure.
+
 ### 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 50816de..8a02e89 100644
--- a/cmd/oapi-codegen/oapi-codegen.go
+++ b/cmd/oapi-codegen/oapi-codegen.go
@@ -22,6 +22,8 @@ import (
 	"path/filepath"
 	"strings"
 
+	"gopkg.in/yaml.v2"
+
 	"github.com/deepmap/oapi-codegen/pkg/codegen"
 	"github.com/deepmap/oapi-codegen/pkg/util"
 )
@@ -31,26 +33,41 @@ func errExit(format string, args ...interface{}) {
 	os.Exit(1)
 }
 
+var (
+	flagPackageName    string
+	flagGenerate       string
+	flagOutputFile     string
+	flagIncludeTags    string
+	flagExcludeTags    string
+	flagTemplatesDir   string
+	flagImportMapping  string
+	flagExcludeSchemas string
+	flagConfigFile     string
+)
+
+type configuration struct {
+	PackageName     string            `yaml:"package"`
+	GenerateTargets []string          `yaml:"generate"`
+	OutputFile      string            `yaml:"output"`
+	IncludeTags     []string          `yaml:"include-tags"`
+	ExcludeTags     []string          `yaml:"exclude-tags"`
+	TemplatesDir    string            `yaml:"templates"`
+	ImportMapping   map[string]string `yaml:"import-mapping"`
+	ExcludeSchemas  []string          `yaml:"exclude-schemas"`
+}
+
 func main() {
-	var (
-		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",
+
+	flag.StringVar(&flagPackageName, "package", "", "The package name for generated code")
+	flag.StringVar(&flagGenerate, "generate", "types,client,server,spec",
 		`Comma-separated list of code to generate; valid options: "types", "client", "chi-server", "server", "spec", "skip-fmt", "skip-prune"`)
-	flag.StringVar(&outputFile, "o", "", "Where to output generated code, stdout is default")
-	flag.StringVar(&includeTags, "include-tags", "", "Only include operations with the given tags. Comma-separated list of tags.")
-	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.StringVar(&flagOutputFile, "o", "", "Where to output generated code, stdout is default")
+	flag.StringVar(&flagIncludeTags, "include-tags", "", "Only include operations with the given tags. Comma-separated list of tags.")
+	flag.StringVar(&flagExcludeTags, "exclude-tags", "", "Exclude operations that are tagged with the given tags. Comma-separated list of tags.")
+	flag.StringVar(&flagTemplatesDir, "templates", "", "Path to directory containing user templates")
+	flag.StringVar(&flagImportMapping, "import-mapping", "", "A dict from the external reference to golang package path")
+	flag.StringVar(&flagExcludeSchemas, "exclude-schemas", "", "A comma separated list of schemas which must be excluded from generation")
+	flag.StringVar(&flagConfigFile, "config", "", "a YAML config file that controls oapi-codegen behavior")
 	flag.Parse()
 
 	if flag.NArg() < 1 {
@@ -58,18 +75,20 @@ func main() {
 		os.Exit(1)
 	}
 
+	cfg := configFromFlags()
+
 	// If the package name has not been specified, we will use the name of the
 	// swagger file.
-	if packageName == "" {
+	if cfg.PackageName == "" {
 		path := flag.Arg(0)
 		baseName := filepath.Base(path)
 		// Split the base name on '.' to get the first part of the file.
 		nameParts := strings.Split(baseName, ".")
-		packageName = codegen.ToCamelCase(nameParts[0])
+		cfg.PackageName = codegen.ToCamelCase(nameParts[0])
 	}
 
 	opts := codegen.Options{}
-	for _, g := range splitCSVArg(generate) {
+	for _, g := range cfg.GenerateTargets {
 		switch g {
 		case "client":
 			opts.GenerateClient = true
@@ -92,9 +111,9 @@ func main() {
 		}
 	}
 
-	opts.IncludeTags = splitCSVArg(includeTags)
-	opts.ExcludeTags = splitCSVArg(excludeTags)
-	opts.ExcludeSchemas = splitCSVArg(excludeSchemas)
+	opts.IncludeTags = cfg.IncludeTags
+	opts.ExcludeTags = cfg.ExcludeTags
+	opts.ExcludeSchemas = cfg.ExcludeSchemas
 
 	if opts.GenerateEchoServer && opts.GenerateChiServer {
 		errExit("can not specify both server and chi-server targets simultaneously")
@@ -105,26 +124,21 @@ func main() {
 		errExit("error loading swagger spec\n: %s", err)
 	}
 
-	templates, err := loadTemplateOverrides(templatesDir)
+	templates, err := loadTemplateOverrides(cfg.TemplatesDir)
 	if err != nil {
 		errExit("error loading template overrides: %s\n", err)
 	}
 	opts.UserTemplates = templates
 
-	if len(importMapping) > 0 {
-		opts.ImportMapping, err = util.ParseCommandlineMap(importMapping)
-		if err != nil {
-			errExit("error parsing import-mapping: %s\n", err)
-		}
-	}
+	opts.ImportMapping = cfg.ImportMapping
 
-	code, err := codegen.Generate(swagger, packageName, opts)
+	code, err := codegen.Generate(swagger, cfg.PackageName, opts)
 	if err != nil {
 		errExit("error generating code: %s\n", err)
 	}
 
-	if outputFile != "" {
-		err = ioutil.WriteFile(outputFile, []byte(code), 0644)
+	if cfg.OutputFile != "" {
+		err = ioutil.WriteFile(cfg.OutputFile, []byte(code), 0644)
 		if err != nil {
 			errExit("error writing generated code to file: %s", err)
 		}
@@ -133,22 +147,6 @@ func main() {
 	}
 }
 
-func splitCSVArg(input string) []string {
-	input = strings.TrimSpace(input)
-	if len(input) == 0 {
-		return nil
-	}
-	splitInput := strings.Split(input, ",")
-	args := make([]string, 0, len(splitInput))
-	for _, s := range splitInput {
-		s = strings.TrimSpace(s)
-		if len(s) > 0 {
-			args = append(args, s)
-		}
-	}
-	return args
-}
-
 func loadTemplateOverrides(templatesDir string) (map[string]string, error) {
 	var templates = make(map[string]string)
 
@@ -171,3 +169,53 @@ func loadTemplateOverrides(templatesDir string) (map[string]string, error) {
 
 	return templates, nil
 }
+
+// configFromFlags parses the flags and the config file. Anything which is
+// a zerovalue in the configuration file will be replaced with the flag
+// value, this means that the config file overrides flag values.
+func configFromFlags() *configuration {
+	var cfg configuration
+
+	// Load the configuration file first.
+	if flagConfigFile != "" {
+		f, err := os.Open(flagConfigFile)
+		if err != nil {
+			errExit("failed to open config file with error: %v\n", err)
+		}
+		defer f.Close()
+		err = yaml.NewDecoder(f).Decode(&cfg)
+		if err != nil {
+			errExit("error parsing config file: %v\n", err)
+		}
+	}
+
+	if cfg.PackageName == "" {
+		cfg.PackageName = flagPackageName
+	}
+	if cfg.GenerateTargets == nil {
+		cfg.GenerateTargets = util.ParseCommandLineList(flagGenerate)
+	}
+	if cfg.IncludeTags == nil {
+		cfg.IncludeTags = util.ParseCommandLineList(flagIncludeTags)
+	}
+	if cfg.ExcludeTags == nil {
+		cfg.ExcludeTags = util.ParseCommandLineList(flagExcludeTags)
+	}
+	if cfg.TemplatesDir == "" {
+		cfg.TemplatesDir = flagTemplatesDir
+	}
+	if cfg.ImportMapping == nil && flagImportMapping != "" {
+		var err error
+		cfg.ImportMapping, err = util.ParseCommandlineMap(flagImportMapping)
+		if err != nil {
+			errExit("error parsing import-mapping: %s\n", err)
+		}
+	}
+	if cfg.ExcludeSchemas == nil {
+		cfg.ExcludeSchemas = util.ParseCommandLineList(flagExcludeSchemas)
+	}
+	if cfg.OutputFile == "" {
+		cfg.OutputFile = flagOutputFile
+	}
+	return &cfg
+}
diff --git a/examples/petstore-expanded/chi/api/petstore.gen.go b/examples/petstore-expanded/chi/api/petstore.gen.go
index 1c5c0fb..1f3fb98 100644
--- a/examples/petstore-expanded/chi/api/petstore.gen.go
+++ b/examples/petstore-expanded/chi/api/petstore.gen.go
@@ -167,21 +167,25 @@ 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 {
+	return HandlerFromMuxWithBaseURL(si, r, "")
+}
+
+func HandlerFromMuxWithBaseURL(si ServerInterface, r chi.Router, baseURL string) http.Handler {
 	wrapper := ServerInterfaceWrapper{
 		Handler: si,
 	}
 
 	r.Group(func(r chi.Router) {
-		r.Get("/pets", wrapper.FindPets)
+		r.Get(baseURL+"/pets", wrapper.FindPets)
 	})
 	r.Group(func(r chi.Router) {
-		r.Post("/pets", wrapper.AddPet)
+		r.Post(baseURL+"/pets", wrapper.AddPet)
 	})
 	r.Group(func(r chi.Router) {
-		r.Delete("/pets/{id}", wrapper.DeletePet)
+		r.Delete(baseURL+"/pets/{id}", wrapper.DeletePet)
 	})
 	r.Group(func(r chi.Router) {
-		r.Get("/pets/{id}", wrapper.FindPetById)
+		r.Get(baseURL+"/pets/{id}", wrapper.FindPetById)
 	})
 
 	return r
diff --git a/examples/petstore-expanded/echo/api/petstore-server.gen.go b/examples/petstore-expanded/echo/api/petstore-server.gen.go
index ecbed3b..baa05c6 100644
--- a/examples/petstore-expanded/echo/api/petstore-server.gen.go
+++ b/examples/petstore-expanded/echo/api/petstore-server.gen.go
@@ -120,15 +120,21 @@ type EchoRouter interface {
 
 // RegisterHandlers adds each server route to the EchoRouter.
 func RegisterHandlers(router EchoRouter, si ServerInterface) {
+	RegisterHandlersWithBaseURL(router, si, "")
+}
+
+// Registers handlers, and prepends BaseURL to the paths, so that the paths
+// can be served under a prefix.
+func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL string) {
 
 	wrapper := ServerInterfaceWrapper{
 		Handler: si,
 	}
 
-	router.GET("/pets", wrapper.FindPets)
-	router.POST("/pets", wrapper.AddPet)
-	router.DELETE("/pets/:id", wrapper.DeletePet)
-	router.GET("/pets/:id", wrapper.FindPetById)
+	router.GET(baseURL+"/pets", wrapper.FindPets)
+	router.POST(baseURL+"/pets", wrapper.AddPet)
+	router.DELETE(baseURL+"/pets/:id", wrapper.DeletePet)
+	router.GET(baseURL+"/pets/:id", wrapper.FindPetById)
 
 }
 
diff --git a/examples/petstore-expanded/echo/api/petstore.go b/examples/petstore-expanded/echo/api/petstore.go
index 74caaf0..60367a3 100644
--- a/examples/petstore-expanded/echo/api/petstore.go
+++ b/examples/petstore-expanded/echo/api/petstore.go
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-//go:generate go run github.com/deepmap/oapi-codegen/cmd/oapi-codegen --package=api --generate types -o petstore-types.gen.go ../../petstore-expanded.yaml
-//go:generate go run github.com/deepmap/oapi-codegen/cmd/oapi-codegen --package=api --generate server,spec -o petstore-server.gen.go ../../petstore-expanded.yaml
+//go:generate go run github.com/deepmap/oapi-codegen/cmd/oapi-codegen --config=types.cfg.yaml ../../petstore-expanded.yaml
+//go:generate go run github.com/deepmap/oapi-codegen/cmd/oapi-codegen --config=server.cfg.yaml ../../petstore-expanded.yaml
 
 package api
 
diff --git a/examples/petstore-expanded/echo/api/server.cfg.yaml b/examples/petstore-expanded/echo/api/server.cfg.yaml
new file mode 100644
index 0000000..653a7c5
--- /dev/null
+++ b/examples/petstore-expanded/echo/api/server.cfg.yaml
@@ -0,0 +1,6 @@
+output:
+  petstore-server.gen.go
+generate:
+  - server
+  - spec
+package: api
diff --git a/examples/petstore-expanded/echo/api/types.cfg.yaml b/examples/petstore-expanded/echo/api/types.cfg.yaml
new file mode 100644
index 0000000..e812b1a
--- /dev/null
+++ b/examples/petstore-expanded/echo/api/types.cfg.yaml
@@ -0,0 +1,5 @@
+output:
+  petstore-types.gen.go
+generate:
+  - types
+package: api
diff --git a/examples/petstore-expanded/petstore-client.gen.go b/examples/petstore-expanded/petstore-client.gen.go
index 7f562d8..5f1cf6f 100644
--- a/examples/petstore-expanded/petstore-client.gen.go
+++ b/examples/petstore-expanded/petstore-client.gen.go
@@ -76,7 +76,9 @@ type HttpRequestDoer interface {
 // Client which conforms to the OpenAPI3 specification for this service.
 type Client struct {
 	// The endpoint of the server conforming to this interface, with scheme,
-	// https://api.deepmap.com for example.
+	// https://api.deepmap.com for example. This can contain a path relative
+	// to the server, such as https://api.deepmap.com/dev-test, and all the
+	// paths in the swagger spec will be appended to the server.
 	Server string
 
 	// Doer for performing requests, typically a *http.Client with any
diff --git a/pkg/codegen/templates/chi-handler.tmpl b/pkg/codegen/templates/chi-handler.tmpl
index 16cd461..8175a8c 100644
--- a/pkg/codegen/templates/chi-handler.tmpl
+++ b/pkg/codegen/templates/chi-handler.tmpl
@@ -5,12 +5,16 @@ 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 {
+    return HandlerFromMuxWithBaseURL(si, r, "")
+}
+
+func HandlerFromMuxWithBaseURL(si ServerInterface, r chi.Router, baseURL string) http.Handler {
 {{if .}}wrapper := ServerInterfaceWrapper{
         Handler: si,
     }
 {{end}}
 {{range .}}r.Group(func(r chi.Router) {
-  r.{{.Method | lower | title }}("{{.Path | swaggerUriToChiUri}}", wrapper.{{.OperationId}})
+  r.{{.Method | lower | title }}(baseURL+"{{.Path | swaggerUriToChiUri}}", wrapper.{{.OperationId}})
 })
 {{end}}
   return r
diff --git a/pkg/codegen/templates/client.tmpl b/pkg/codegen/templates/client.tmpl
index a215895..5d264a2 100644
--- a/pkg/codegen/templates/client.tmpl
+++ b/pkg/codegen/templates/client.tmpl
@@ -11,7 +11,9 @@ type HttpRequestDoer interface {
 // Client which conforms to the OpenAPI3 specification for this service.
 type Client struct {
 	// The endpoint of the server conforming to this interface, with scheme,
-	// https://api.deepmap.com for example.
+	// https://api.deepmap.com for example. This can contain a path relative
+	// to the server, such as https://api.deepmap.com/dev-test, and all the
+	// paths in the swagger spec will be appended to the server.
 	Server string
 
 	// Doer for performing requests, typically a *http.Client with any
diff --git a/pkg/codegen/templates/register.tmpl b/pkg/codegen/templates/register.tmpl
index d7857f1..21b52fe 100644
--- a/pkg/codegen/templates/register.tmpl
+++ b/pkg/codegen/templates/register.tmpl
@@ -17,11 +17,17 @@ type EchoRouter interface {
 
 // RegisterHandlers adds each server route to the EchoRouter.
 func RegisterHandlers(router EchoRouter, si ServerInterface) {
+    RegisterHandlersWithBaseURL(router, si, "")
+}
+
+// Registers handlers, and prepends BaseURL to the paths, so that the paths
+// can be served under a prefix.
+func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL string) {
 {{if .}}
     wrapper := ServerInterfaceWrapper{
         Handler: si,
     }
 {{end}}
-{{range .}}router.{{.Method}}("{{.Path | swaggerUriToEchoUri}}", wrapper.{{.OperationId}})
+{{range .}}router.{{.Method}}(baseURL + "{{.Path | swaggerUriToEchoUri}}", wrapper.{{.OperationId}})
 {{end}}
 }
diff --git a/pkg/codegen/templates/templates.gen.go b/pkg/codegen/templates/templates.gen.go
index 770ba76..5e6f629 100644
--- a/pkg/codegen/templates/templates.gen.go
+++ b/pkg/codegen/templates/templates.gen.go
@@ -80,12 +80,16 @@ 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 {
+    return HandlerFromMuxWithBaseURL(si, r, "")
+}
+
+func HandlerFromMuxWithBaseURL(si ServerInterface, r chi.Router, baseURL string) http.Handler {
 {{if .}}wrapper := ServerInterfaceWrapper{
         Handler: si,
     }
 {{end}}
 {{range .}}r.Group(func(r chi.Router) {
-  r.{{.Method | lower | title }}("{{.Path | swaggerUriToChiUri}}", wrapper.{{.OperationId}})
+  r.{{.Method | lower | title }}(baseURL+"{{.Path | swaggerUriToChiUri}}", wrapper.{{.OperationId}})
 })
 {{end}}
   return r
@@ -396,7 +400,9 @@ type HttpRequestDoer interface {
 // Client which conforms to the OpenAPI3 specification for this service.
 type Client struct {
 	// The endpoint of the server conforming to this interface, with scheme,
-	// https://api.deepmap.com for example.
+	// https://api.deepmap.com for example. This can contain a path relative
+	// to the server, such as https://api.deepmap.com/dev-test, and all the
+	// paths in the swagger spec will be appended to the server.
 	Server string
 
 	// Doer for performing requests, typically a *http.Client with any
@@ -746,12 +752,18 @@ type EchoRouter interface {
 
 // RegisterHandlers adds each server route to the EchoRouter.
 func RegisterHandlers(router EchoRouter, si ServerInterface) {
+    RegisterHandlersWithBaseURL(router, si, "")
+}
+
+// Registers handlers, and prepends BaseURL to the paths, so that the paths
+// can be served under a prefix.
+func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL string) {
 {{if .}}
     wrapper := ServerInterfaceWrapper{
         Handler: si,
     }
 {{end}}
-{{range .}}router.{{.Method}}("{{.Path | swaggerUriToEchoUri}}", wrapper.{{.OperationId}})
+{{range .}}router.{{.Method}}(baseURL + "{{.Path | swaggerUriToEchoUri}}", wrapper.{{.OperationId}})
 {{end}}
 }
 `,
@@ -933,4 +945,3 @@ func Parse(t *template.Template) (*template.Template, error) {
 	}
 	return t, nil
 }
-
diff --git a/pkg/runtime/deepobject.go b/pkg/runtime/deepobject.go
index f7446d2..57d0625 100644
--- a/pkg/runtime/deepobject.go
+++ b/pkg/runtime/deepobject.go
@@ -311,9 +311,9 @@ func assignSlice(dst reflect.Value, pathValues fieldOrValue) error {
 
 	// This could be cleaner, but we can call into assignPathValues to
 	// avoid recreating this logic.
-	for i:=0; i < nValues; i++ {
+	for i := 0; i < nValues; i++ {
 		dstElem := dst.Index(i).Addr()
-		err := assignPathValues(dstElem.Interface(), fieldOrValue{value:values[i]})
+		err := assignPathValues(dstElem.Interface(), fieldOrValue{value: values[i]})
 		if err != nil {
 			return errors.Wrap(err, "error binding array")
 		}
diff --git a/pkg/runtime/styleparam.go b/pkg/runtime/styleparam.go
index 1d28131..e2a110c 100644
--- a/pkg/runtime/styleparam.go
+++ b/pkg/runtime/styleparam.go
@@ -16,11 +16,14 @@ package runtime
 import (
 	"errors"
 	"fmt"
+	"net/url"
 	"reflect"
 	"sort"
 	"strconv"
 	"strings"
 	"time"
+
+	errorsw "github.com/pkg/errors"
 )
 
 // Given an input value, such as a primitive type, array or object, turn it
@@ -132,7 +135,6 @@ func sortedKeys(strMap map[string]string) []string {
 	return keys
 }
 
-
 // This is a special case. The struct may be a time, in which case, marshal
 // it in RFC3339 format.
 func marshalTimeValue(value interface{}) (string, bool) {
@@ -149,7 +151,11 @@ func marshalTimeValue(value interface{}) (string, bool) {
 
 func styleStruct(style string, explode bool, paramName string, value interface{}) (string, error) {
 	if timeVal, ok := marshalTimeValue(value); ok {
-		return stylePrimitive(style, explode, paramName, timeVal)
+		styledVal, err := stylePrimitive(style, explode, paramName, url.QueryEscape(timeVal))
+		if err != nil {
+			return "", errorsw.Wrap(err, "failed to style time")
+		}
+		return styledVal, nil
 	}
 
 	if style == "deepObject" {
diff --git a/pkg/util/inputmapping.go b/pkg/util/inputmapping.go
index 3557ce5..fb2ac75 100644
--- a/pkg/util/inputmapping.go
+++ b/pkg/util/inputmapping.go
@@ -28,10 +28,29 @@ func ParseCommandlineMap(src string) (map[string]string, error) {
 	return result, nil
 }
 
+// ParseCommandLineList parses comma separated string lists which are passed
+// in on the command line. Spaces are trimmed off both sides of result
+// strings.
+func ParseCommandLineList(input string) []string {
+	input = strings.TrimSpace(input)
+	if len(input) == 0 {
+		return nil
+	}
+	splitInput := strings.Split(input, ",")
+	args := make([]string, 0, len(splitInput))
+	for _, s := range splitInput {
+		s = strings.TrimSpace(s)
+		if len(s) > 0 {
+			args = append(args, s)
+		}
+	}
+	return args
+}
+
 // This function splits a string along the specifed separator, but it
 // ignores anything between double quotes for splitting. We do simple
 // inside/outside quote counting. Quotes are not stripped from output.
-func splitString(s string, sep rune) ([]string) {
+func splitString(s string, sep rune) []string {
 	const escapeChar rune = '"'
 
 	var parts []string
@@ -39,7 +58,7 @@ func splitString(s string, sep rune) ([]string) {
 	inQuotes := false
 
 	for _, c := range s {
-		if c == escapeChar{
+		if c == escapeChar {
 			if inQuotes {
 				inQuotes = false
 			} else {


Test patch:
diff --git a/internal/test/client/client.gen.go b/internal/test/client/client.gen.go
index 09e2fb4..41cd7f0 100644
--- a/internal/test/client/client.gen.go
+++ b/internal/test/client/client.gen.go
@@ -51,7 +51,9 @@ type HttpRequestDoer interface {
 // Client which conforms to the OpenAPI3 specification for this service.
 type Client struct {
 	// The endpoint of the server conforming to this interface, with scheme,
-	// https://api.deepmap.com for example.
+	// https://api.deepmap.com for example. This can contain a path relative
+	// to the server, such as https://api.deepmap.com/dev-test, and all the
+	// paths in the swagger spec will be appended to the server.
 	Server string
 
 	// Doer for performing requests, typically a *http.Client with any
@@ -1012,18 +1014,24 @@ type EchoRouter interface {
 
 // RegisterHandlers adds each server route to the EchoRouter.
 func RegisterHandlers(router EchoRouter, si ServerInterface) {
+	RegisterHandlersWithBaseURL(router, si, "")
+}
+
+// Registers handlers, and prepends BaseURL to the paths, so that the paths
+// can be served under a prefix.
+func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL string) {
 
 	wrapper := ServerInterfaceWrapper{
 		Handler: si,
 	}
 
-	router.POST("/with_both_bodies", wrapper.PostBoth)
-	router.GET("/with_both_responses", wrapper.GetBoth)
-	router.POST("/with_json_body", wrapper.PostJson)
-	router.GET("/with_json_response", wrapper.GetJson)
-	router.POST("/with_other_body", wrapper.PostOther)
-	router.GET("/with_other_response", wrapper.GetOther)
-	router.GET("/with_trailing_slash/", wrapper.GetJsonWithTrailingSlash)
+	router.POST(baseURL+"/with_both_bodies", wrapper.PostBoth)
+	router.GET(baseURL+"/with_both_responses", wrapper.GetBoth)
+	router.POST(baseURL+"/with_json_body", wrapper.PostJson)
+	router.GET(baseURL+"/with_json_response", wrapper.GetJson)
+	router.POST(baseURL+"/with_other_body", wrapper.PostOther)
+	router.GET(baseURL+"/with_other_response", wrapper.GetOther)
+	router.GET(baseURL+"/with_trailing_slash/", wrapper.GetJsonWithTrailingSlash)
 
 }
 
diff --git a/internal/test/client/doc.go b/internal/test/client/doc.go
index 4a3bcfc..8244197 100644
--- a/internal/test/client/doc.go
+++ b/internal/test/client/doc.go
@@ -1,4 +1,3 @@
 package client
 
 //go:generate go run github.com/deepmap/oapi-codegen/cmd/oapi-codegen --package=client -o client.gen.go client.yaml
-
diff --git a/internal/test/components/components.gen.go b/internal/test/components/components.gen.go
index 222b4c2..eda0b1a 100644
--- a/internal/test/components/components.gen.go
+++ b/internal/test/components/components.gen.go
@@ -733,7 +733,9 @@ type HttpRequestDoer interface {
 // Client which conforms to the OpenAPI3 specification for this service.
 type Client struct {
 	// The endpoint of the server conforming to this interface, with scheme,
-	// https://api.deepmap.com for example.
+	// https://api.deepmap.com for example. This can contain a path relative
+	// to the server, such as https://api.deepmap.com/dev-test, and all the
+	// paths in the swagger spec will be appended to the server.
 	Server string
 
 	// Doer for performing requests, typically a *http.Client with any
@@ -1354,14 +1356,20 @@ type EchoRouter interface {
 
 // RegisterHandlers adds each server route to the EchoRouter.
 func RegisterHandlers(router EchoRouter, si ServerInterface) {
+	RegisterHandlersWithBaseURL(router, si, "")
+}
+
+// Registers handlers, and prepends BaseURL to the paths, so that the paths
+// can be served under a prefix.
+func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL string) {
 
 	wrapper := ServerInterfaceWrapper{
 		Handler: si,
 	}
 
-	router.GET("/ensure-everything-is-referenced", wrapper.EnsureEverythingIsReferenced)
-	router.GET("/params_with_add_props", wrapper.ParamsWithAddProps)
-	router.POST("/params_with_add_props", wrapper.BodyWithAddProps)
+	router.GET(baseURL+"/ensure-everything-is-referenced", wrapper.EnsureEverythingIsReferenced)
+	router.GET(baseURL+"/params_with_add_props", wrapper.ParamsWithAddProps)
+	router.POST(baseURL+"/params_with_add_props", wrapper.BodyWithAddProps)
 
 }
 
diff --git a/internal/test/externalref/doc.go b/internal/test/externalref/doc.go
index e239ead..ea1d5f5 100644
--- a/internal/test/externalref/doc.go
+++ b/internal/test/externalref/doc.go
@@ -1,3 +1,3 @@
 package externalref
 
-//go:generate go run github.com/deepmap/oapi-codegen/cmd/oapi-codegen -generate types,skip-prune --package=externalref -o externalref.gen.go --import-mapping=./packageA/spec.yaml:github.com/deepmap/oapi-codegen/internal/test/externalref/packageA,./packageB/spec.yaml:github.com/deepmap/oapi-codegen/internal/test/externalref/packageB spec.yaml
+//go:generate go run github.com/deepmap/oapi-codegen/cmd/oapi-codegen --config=externalref.cfg.yaml spec.yaml
diff --git a/internal/test/externalref/externalref.cfg.yaml b/internal/test/externalref/externalref.cfg.yaml
new file mode 100644
index 0000000..92d36a5
--- /dev/null
+++ b/internal/test/externalref/externalref.cfg.yaml
@@ -0,0 +1,9 @@
+output:
+  externalref.gen.go
+package: externalref
+generate:
+  - types
+  - skip-prune
+import-mapping:
+  ./packageA/spec.yaml: github.com/deepmap/oapi-codegen/internal/test/externalref/packageA
+  ./packageB/spec.yaml: github.com/deepmap/oapi-codegen/internal/test/externalref/packageB
diff --git a/internal/test/issues/issue-52/issue.gen.go b/internal/test/issues/issue-52/issue.gen.go
index 33ef172..b189325 100644
--- a/internal/test/issues/issue-52/issue.gen.go
+++ b/internal/test/issues/issue-52/issue.gen.go
@@ -105,7 +105,9 @@ type HttpRequestDoer interface {
 // Client which conforms to the OpenAPI3 specification for this service.
 type Client struct {
 	// The endpoint of the server conforming to this interface, with scheme,
-	// https://api.deepmap.com for example.
+	// https://api.deepmap.com for example. This can contain a path relative
+	// to the server, such as https://api.deepmap.com/dev-test, and all the
+	// paths in the swagger spec will be appended to the server.
 	Server string
 
 	// Doer for performing requests, typically a *http.Client with any
@@ -337,12 +339,18 @@ type EchoRouter interface {
 
 // RegisterHandlers adds each server route to the EchoRouter.
 func RegisterHandlers(router EchoRouter, si ServerInterface) {
+	RegisterHandlersWithBaseURL(router, si, "")
+}
+
+// Registers handlers, and prepends BaseURL to the paths, so that the paths
+// can be served under a prefix.
+func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL string) {
 
 	wrapper := ServerInterfaceWrapper{
 		Handler: si,
 	}
 
-	router.GET("/example", wrapper.ExampleGet)
+	router.GET(baseURL+"/example", wrapper.ExampleGet)
 
 }
 
diff --git a/internal/test/issues/issue-grab_import_names/issue.gen.go b/internal/test/issues/issue-grab_import_names/issue.gen.go
index 035f47b..c8e1fc4 100644
--- a/internal/test/issues/issue-grab_import_names/issue.gen.go
+++ b/internal/test/issues/issue-grab_import_names/issue.gen.go
@@ -43,7 +43,9 @@ type HttpRequestDoer interface {
 // Client which conforms to the OpenAPI3 specification for this service.
 type Client struct {
 	// The endpoint of the server conforming to this interface, with scheme,
-	// https://api.deepmap.com for example.
+	// https://api.deepmap.com for example. This can contain a path relative
+	// to the server, such as https://api.deepmap.com/dev-test, and all the
+	// paths in the swagger spec will be appended to the server.
 	Server string
 
 	// Doer for performing requests, typically a *http.Client with any
@@ -332,12 +334,18 @@ type EchoRouter interface {
 
 // RegisterHandlers adds each server route to the EchoRouter.
 func RegisterHandlers(router EchoRouter, si ServerInterface) {
+	RegisterHandlersWithBaseURL(router, si, "")
+}
+
+// Registers handlers, and prepends BaseURL to the paths, so that the paths
+// can be served under a prefix.
+func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL string) {
 
 	wrapper := ServerInterfaceWrapper{
 		Handler: si,
 	}
 
-	router.GET("/foo", wrapper.GetFoo)
+	router.GET(baseURL+"/foo", wrapper.GetFoo)
 
 }
 
diff --git a/internal/test/issues/issue-illegal_enum_names/issue.gen.go b/internal/test/issues/issue-illegal_enum_names/issue.gen.go
index 8548802..5a57bef 100644
--- a/internal/test/issues/issue-illegal_enum_names/issue.gen.go
+++ b/internal/test/issues/issue-illegal_enum_names/issue.gen.go
@@ -47,7 +47,9 @@ type HttpRequestDoer interface {
 // Client which conforms to the OpenAPI3 specification for this service.
 type Client struct {
 	// The endpoint of the server conforming to this interface, with scheme,
-	// https://api.deepmap.com for example.
+	// https://api.deepmap.com for example. This can contain a path relative
+	// to the server, such as https://api.deepmap.com/dev-test, and all the
+	// paths in the swagger spec will be appended to the server.
 	Server string
 
 	// Doer for performing requests, typically a *http.Client with any
@@ -279,12 +281,18 @@ type EchoRouter interface {
 
 // RegisterHandlers adds each server route to the EchoRouter.
 func RegisterHandlers(router EchoRouter, si ServerInterface) {
+	RegisterHandlersWithBaseURL(router, si, "")
+}
+
+// Registers handlers, and prepends BaseURL to the paths, so that the paths
+// can be served under a prefix.
+func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL string) {
 
 	wrapper := ServerInterfaceWrapper{
 		Handler: si,
 	}
 
-	router.GET("/foo", wrapper.GetFoo)
+	router.GET(baseURL+"/foo", wrapper.GetFoo)
 
 }
 
diff --git a/internal/test/parameters/parameters.gen.go b/internal/test/parameters/parameters.gen.go
index 5a57bfa..f0dfe05 100644
--- a/internal/test/parameters/parameters.gen.go
+++ b/internal/test/parameters/parameters.gen.go
@@ -128,7 +128,9 @@ type HttpRequestDoer interface {
 // Client which conforms to the OpenAPI3 specification for this service.
 type Client struct {
 	// The endpoint of the server conforming to this interface, with scheme,
-	// https://api.deepmap.com for example.
+	// https://api.deepmap.com for example. This can contain a path relative
+	// to the server, such as https://api.deepmap.com/dev-test, and all the
+	// paths in the swagger spec will be appended to the server.
 	Server string
 
 	// Doer for performing requests, typically a *http.Client with any
@@ -3093,30 +3095,36 @@ type EchoRouter interface {
 
 // RegisterHandlers adds each server route to the EchoRouter.
 func RegisterHandlers(router EchoRouter, si ServerInterface) {
+	RegisterHandlersWithBaseURL(router, si, "")
+}
+
+// Registers handlers, and prepends BaseURL to the paths, so that the paths
+// can be served under a prefix.
+func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL string) {
 
 	wrapper := ServerInterfaceWrapper{
 		Handler: si,
 	}
 
-	router.GET("/contentObject/:param", wrapper.GetContentObject)
-	router.GET("/cookie", wrapper.GetCookie)
-	router.GET("/header", wrapper.GetHeader)
-	router.GET("/labelExplodeArray/:param", wrapper.GetLabelExplodeArray)
-	router.GET("/labelExplodeObject/:param", wrapper.GetLabelExplodeObject)
-	router.GET("/labelNoExplodeArray/:param", wrapper.GetLabelNoExplodeArray)
-	router.GET("/labelNoExplodeObject/:param", wrapper.GetLabelNoExplodeObject)
-	router.GET("/matrixExplodeArray/:id", wrapper.GetMatrixExplodeArray)
-	router.GET("/matrixExplodeObject/:id", wrapper.GetMatrixExplodeObject)
-	router.GET("/matrixNoExplodeArray/:id", wrapper.GetMatrixNoExplodeArray)
-	router.GET("/matrixNoExplodeObject/:id", wrapper.GetMatrixNoExplodeObject)
-	router.GET("/passThrough/:param", wrapper.GetPassThrough)
-	router.GET("/queryDeepObject", wrapper.GetDeepObject)
-	router.GET("/queryForm", wrapper.GetQueryForm)
-	router.GET("/simpleExplodeArray/:param", wrapper.GetSimpleExplodeArray)
-	router.GET("/simpleExplodeObject/:param", wrapper.GetSimpleExplodeObject)
-	router.GET("/simpleNoExplodeArray/:param", wrapper.GetSimpleNoExplodeArray)
-	router.GET("/simpleNoExplodeObject/:param", wrapper.GetSimpleNoExplodeObject)
-	router.GET("/simplePrimitive/:param", wrapper.GetSimplePrimitive)
+	router.GET(baseURL+"/contentObject/:param", wrapper.GetContentObject)
+	router.GET(baseURL+"/cookie", wrapper.GetCookie)
+	router.GET(baseURL+"/header", wrapper.GetHeader)
+	router.GET(baseURL+"/labelExplodeArray/:param", wrapper.GetLabelExplodeArray)
+	router.GET(baseURL+"/labelExplodeObject/:param", wrapper.GetLabelExplodeObject)
+	router.GET(baseURL+"/labelNoExplodeArray/:param", wrapper.GetLabelNoExplodeArray)
+	router.GET(baseURL+"/labelNoExplodeObject/:param", wrapper.GetLabelNoExplodeObject)
+	router.GET(baseURL+"/matrixExplodeArray/:id", wrapper.GetMatrixExplodeArray)
+	router.GET(baseURL+"/matrixExplodeObject/:id", wrapper.GetMatrixExplodeObject)
+	router.GET(baseURL+"/matrixNoExplodeArray/:id", wrapper.GetMatrixNoExplodeArray)
+	router.GET(baseURL+"/matrixNoExplodeObject/:id", wrapper.GetMatrixNoExplodeObject)
+	router.GET(baseURL+"/passThrough/:param", wrapper.GetPassThrough)
+	router.GET(baseURL+"/queryDeepObject", wrapper.GetDeepObject)
+	router.GET(baseURL+"/queryForm", wrapper.GetQueryForm)
+	router.GET(baseURL+"/simpleExplodeArray/:param", wrapper.GetSimpleExplodeArray)
+	router.GET(baseURL+"/simpleExplodeObject/:param", wrapper.GetSimpleExplodeObject)
+	router.GET(baseURL+"/simpleNoExplodeArray/:param", wrapper.GetSimpleNoExplodeArray)
+	router.GET(baseURL+"/simpleNoExplodeObject/:param", wrapper.GetSimpleNoExplodeObject)
+	router.GET(baseURL+"/simplePrimitive/:param", wrapper.GetSimplePrimitive)
 
 }
 
diff --git a/internal/test/parameters/parameters_test.go b/internal/test/parameters/parameters_test.go
index 06d0b0a..734e09f 100644
--- a/internal/test/parameters/parameters_test.go
+++ b/internal/test/parameters/parameters_test.go
@@ -387,7 +387,6 @@ func TestParameterBinding(t *testing.T) {
 	assert.EqualValues(t, &expectedComplexObject, ts.complexObject)
 	ts.reset()
 
-
 	// ---------------------- Test Header Query Parameters --------------------
 
 	// unexploded header primitive.
diff --git a/internal/test/schemas/schemas.gen.go b/internal/test/schemas/schemas.gen.go
index bab13e6..f628d7c 100644
--- a/internal/test/schemas/schemas.gen.go
+++ b/internal/test/schemas/schemas.gen.go
@@ -80,7 +80,9 @@ type HttpRequestDoer interface {
 // Client which conforms to the OpenAPI3 specification for this service.
 type Client struct {
 	// The endpoint of the server conforming to this interface, with scheme,
-	// https://api.deepmap.com for example.
+	// https://api.deepmap.com for example. This can contain a path relative
+	// to the server, such as https://api.deepmap.com/dev-test, and all the
+	// paths in the swagger spec will be appended to the server.
 	Server string
 
 	// Doer for performing requests, typically a *http.Client with any
@@ -1161,18 +1163,24 @@ type EchoRouter interface {
 
 // RegisterHandlers adds each server route to the EchoRouter.
 func RegisterHandlers(router EchoRouter, si ServerInterface) {
+	RegisterHandlersWithBaseURL(router, si, "")
+}
+
+// Registers handlers, and prepends BaseURL to the paths, so that the paths
+// can be served under a prefix.
+func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL string) {
 
 	wrapper := ServerInterfaceWrapper{
 		Handler: si,
 	}
 
-	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)
+	router.GET(baseURL+"/ensure-everything-is-referenced", wrapper.EnsureEverythingIsReferenced)
+	router.GET(baseURL+"/issues/127", wrapper.Issue127)
+	router.GET(baseURL+"/issues/185", wrapper.Issue185)
+	router.GET(baseURL+"/issues/209/$:str", wrapper.Issue209)
+	router.GET(baseURL+"/issues/30/:fallthrough", wrapper.Issue30)
+	router.GET(baseURL+"/issues/41/:1param", wrapper.Issue41)
+	router.GET(baseURL+"/issues/9", wrapper.Issue9)
 
 }
 
diff --git a/internal/test/server/server.gen.go b/internal/test/server/server.gen.go
index 1fd6623..da5544f 100644
--- a/internal/test/server/server.gen.go
+++ b/internal/test/server/server.gen.go
@@ -372,39 +372,43 @@ 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 {
+	return HandlerFromMuxWithBaseURL(si, r, "")
+}
+
+func HandlerFromMuxWithBaseURL(si ServerInterface, r chi.Router, baseURL string) http.Handler {
 	wrapper := ServerInterfaceWrapper{
 		Handler: si,
 	}
 
 	r.Group(func(r chi.Router) {
-		r.Get("/every-type-optional", wrapper.GetEveryTypeOptional)
+		r.Get(baseURL+"/every-type-optional", wrapper.GetEveryTypeOptional)
 	})
 	r.Group(func(r chi.Router) {
-		r.Get("/get-simple", wrapper.GetSimple)
+		r.Get(baseURL+"/get-simple", wrapper.GetSimple)
 	})
 	r.Group(func(r chi.Router) {
-		r.Get("/get-with-args", wrapper.GetWithArgs)
+		r.Get(baseURL+"/get-with-args", wrapper.GetWithArgs)
 	})
 	r.Group(func(r chi.Router) {
-		r.Get("/get-with-references/{global_argument}/{argument}", wrapper.GetWithReferences)
+		r.Get(baseURL+"/get-with-references/{global_argument}/{argument}", wrapper.GetWithReferences)
 	})
 	r.Group(func(r chi.Router) {
-		r.Get("/get-with-type/{content_type}", wrapper.GetWithContentType)
+		r.Get(baseURL+"/get-with-type/{content_type}", wrapper.GetWithContentType)
 	})
 	r.Group(func(r chi.Router) {
-		r.Get("/reserved-keyword", wrapper.GetReservedKeyword)
+		r.Get(baseURL+"/reserved-keyword", wrapper.GetReservedKeyword)
 	})
 	r.Group(func(r chi.Router) {
-		r.Post("/resource/{argument}", wrapper.CreateResource)
+		r.Post(baseURL+"/resource/{argument}", wrapper.CreateResource)
 	})
 	r.Group(func(r chi.Router) {
-		r.Post("/resource2/{inline_argument}", wrapper.CreateResource2)
+		r.Post(baseURL+"/resource2/{inline_argument}", wrapper.CreateResource2)
 	})
 	r.Group(func(r chi.Router) {
-		r.Put("/resource3/{fallthrough}", wrapper.UpdateResource3)
+		r.Put(baseURL+"/resource3/{fallthrough}", wrapper.UpdateResource3)
 	})
 	r.Group(func(r chi.Router) {
-		r.Get("/response-with-reference", wrapper.GetResponseWithReference)
+		r.Get(baseURL+"/response-with-reference", wrapper.GetResponseWithReference)
 	})
 
 	return r
diff --git a/pkg/codegen/operations_test.go b/pkg/codegen/operations_test.go
index 0636f29..538b06f 100644
--- a/pkg/codegen/operations_test.go
+++ b/pkg/codegen/operations_test.go
@@ -20,45 +20,45 @@ import (
 
 func TestGenerateDefaultOperationID(t *testing.T) {
 	type test struct {
-		op string
-		path string
-		want string
+		op      string
+		path    string
+		want    string
 		wantErr bool
 	}
 
-	suite := []test {
+	suite := []test{
 		{
-			op: http.MethodGet,
-			path: "/v1/foo/bar",
-			want: "GetV1FooBar",
+			op:      http.MethodGet,
+			path:    "/v1/foo/bar",
+			want:    "GetV1FooBar",
 			wantErr: false,
 		},
 		{
-			op: http.MethodGet,
-			path: "/v1/foo/bar/",
-			want: "GetV1FooBar",
+			op:      http.MethodGet,
+			path:    "/v1/foo/bar/",
+			want:    "GetV1FooBar",
 			wantErr: false,
 		},
 		{
-			op: http.MethodPost,
-			path: "/v1",
-			want: "PostV1",
+			op:      http.MethodPost,
+			path:    "/v1",
+			want:    "PostV1",
 			wantErr: false,
 		},
 		{
-			op: http.MethodPost,
-			path: "v1",
-			want: "PostV1",
+			op:      http.MethodPost,
+			path:    "v1",
+			want:    "PostV1",
 			wantErr: false,
 		},
 		{
-			path: "v1",
-			want: "",
+			path:    "v1",
+			want:    "",
 			wantErr: true,
 		},
 		{
-			path: "",
-			want: "PostV1",
+			path:    "",
+			want:    "PostV1",
 			wantErr: true,
 		},
 	}
@@ -71,11 +71,11 @@ func TestGenerateDefaultOperationID(t *testing.T) {
 			}
 		}
 
-		if test.wantErr	{
+		if test.wantErr {
 			return
 		}
 		if got != test.want {
 			t.Fatalf("Operation ID generation error. Want [%v] Got [%v]", test.want, got)
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/pkg/runtime/styleparam_test.go b/pkg/runtime/styleparam_test.go
index 48ad36e..fcf4eef 100644
--- a/pkg/runtime/styleparam_test.go
+++ b/pkg/runtime/styleparam_test.go
@@ -34,7 +34,7 @@ func TestStyleParam(t *testing.T) {
 	dict := map[string]interface{}{}
 	dict["firstName"] = "Alex"
 	dict["role"] = "admin"
-	timestamp, _ := time.Parse(time.RFC3339, "2020-01-01T22:00:00Z")
+	timestamp, _ := time.Parse(time.RFC3339, "2020-01-01T22:00:00+02:00")
 
 	// ---------------------------- Simple Style -------------------------------
 
@@ -72,19 +72,19 @@ func TestStyleParam(t *testing.T) {
 
 	result, err = StyleParam("simple", false, "id", timestamp)
 	assert.NoError(t, err)
-	assert.EqualValues(t, "2020-01-01T22:00:00Z", result)
+	assert.EqualValues(t, "2020-01-01T22%3A00%3A00%2B02%3A00", result)
 
 	result, err = StyleParam("simple", true, "id", timestamp)
 	assert.NoError(t, err)
-	assert.EqualValues(t, "2020-01-01T22:00:00Z", result)
+	assert.EqualValues(t, "2020-01-01T22%3A00%3A00%2B02%3A00", result)
 
 	result, err = StyleParam("simple", false, "id", &timestamp)
 	assert.NoError(t, err)
-	assert.EqualValues(t, "2020-01-01T22:00:00Z", result)
+	assert.EqualValues(t, "2020-01-01T22%3A00%3A00%2B02%3A00", result)
 
 	result, err = StyleParam("simple", true, "id", &timestamp)
 	assert.NoError(t, err)
-	assert.EqualValues(t, "2020-01-01T22:00:00Z", result)
+	assert.EqualValues(t, "2020-01-01T22%3A00%3A00%2B02%3A00", result)
 
 	// ----------------------------- Label Style -------------------------------
 
@@ -122,19 +122,19 @@ func TestStyleParam(t *testing.T) {
 
 	result, err = StyleParam("label", false, "id", timestamp)
 	assert.NoError(t, err)
-	assert.EqualValues(t, ".2020-01-01T22:00:00Z", result)
+	assert.EqualValues(t, ".2020-01-01T22%3A00%3A00%2B02%3A00", result)
 
 	result, err = StyleParam("label", true, "id", timestamp)
 	assert.NoError(t, err)
-	assert.EqualValues(t, ".2020-01-01T22:00:00Z", result)
+	assert.EqualValues(t, ".2020-01-01T22%3A00%3A00%2B02%3A00", result)
 
 	result, err = StyleParam("label", false, "id", &timestamp)
 	assert.NoError(t, err)
-	assert.EqualValues(t, ".2020-01-01T22:00:00Z", result)
+	assert.EqualValues(t, ".2020-01-01T22%3A00%3A00%2B02%3A00", result)
 
 	result, err = StyleParam("label", true, "id", &timestamp)
 	assert.NoError(t, err)
-	assert.EqualValues(t, ".2020-01-01T22:00:00Z", result)
+	assert.EqualValues(t, ".2020-01-01T22%3A00%3A00%2B02%3A00", result)
 
 	// ----------------------------- Matrix Style ------------------------------
 
@@ -172,19 +172,19 @@ func TestStyleParam(t *testing.T) {
 
 	result, err = StyleParam("matrix", false, "id", timestamp)
 	assert.NoError(t, err)
-	assert.EqualValues(t, ";id=2020-01-01T22:00:00Z", result)
+	assert.EqualValues(t, ";id=2020-01-01T22%3A00%3A00%2B02%3A00", result)
 
 	result, err = StyleParam("matrix", true, "id", timestamp)
 	assert.NoError(t, err)
-	assert.EqualValues(t, ";id=2020-01-01T22:00:00Z", result)
+	assert.EqualValues(t, ";id=2020-01-01T22%3A00%3A00%2B02%3A00", result)
 
 	result, err = StyleParam("matrix", false, "id", &timestamp)
 	assert.NoError(t, err)
-	assert.EqualValues(t, ";id=2020-01-01T22:00:00Z", result)
+	assert.EqualValues(t, ";id=2020-01-01T22%3A00%3A00%2B02%3A00", result)
 
 	result, err = StyleParam("matrix", true, "id", &timestamp)
 	assert.NoError(t, err)
-	assert.EqualValues(t, ";id=2020-01-01T22:00:00Z", result)
+	assert.EqualValues(t, ";id=2020-01-01T22%3A00%3A00%2B02%3A00", result)
 
 	// ------------------------------ Form Style -------------------------------
 	result, err = StyleParam("form", false, "id", primitive)
@@ -221,19 +221,19 @@ func TestStyleParam(t *testing.T) {
 
 	result, err = StyleParam("form", false, "id", timestamp)
 	assert.NoError(t, err)
-	assert.EqualValues(t, "id=2020-01-01T22:00:00Z", result)
+	assert.EqualValues(t, "id=2020-01-01T22%3A00%3A00%2B02%3A00", result)
 
 	result, err = StyleParam("form", true, "id", timestamp)
 	assert.NoError(t, err)
-	assert.EqualValues(t, "id=2020-01-01T22:00:00Z", result)
+	assert.EqualValues(t, "id=2020-01-01T22%3A00%3A00%2B02%3A00", result)
 
 	result, err = StyleParam("form", false, "id", &timestamp)
 	assert.NoError(t, err)
-	assert.EqualValues(t, "id=2020-01-01T22:00:00Z", result)
+	assert.EqualValues(t, "id=2020-01-01T22%3A00%3A00%2B02%3A00", result)
 
 	result, err = StyleParam("form", true, "id", &timestamp)
 	assert.NoError(t, err)
-	assert.EqualValues(t, "id=2020-01-01T22:00:00Z", result)
+	assert.EqualValues(t, "id=2020-01-01T22%3A00%3A00%2B02%3A00", result)
 
 	// ------------------------  spaceDelimited Style --------------------------
 
@@ -352,7 +352,6 @@ func TestStyleParam(t *testing.T) {
 	result, err = StyleParam("deepObject", true, "id", &timestamp)
 	assert.Error(t, err)
 
-
 	// Misc tests
 	// Test type aliases
 	type StrType string
diff --git a/pkg/types/date_test.go b/pkg/types/date_test.go
index 1369b1c..18bfd4b 100644
--- a/pkg/types/date_test.go
+++ b/pkg/types/date_test.go
@@ -11,7 +11,7 @@ import (
 func TestDate_MarshalJSON(t *testing.T) {
 	testDate := time.Date(2019, 4, 1, 0, 0, 0, 0, time.UTC)
 	b := struct {
-		DateField Date	`json:"date"`
+		DateField Date `json:"date"`
 	}{
 		DateField: Date{testDate},
 	}
@@ -24,7 +24,7 @@ func TestDate_UnmarshalJSON(t *testing.T) {
 	testDate := time.Date(2019, 4, 1, 0, 0, 0, 0, time.UTC)
 	jsonStr := `{"date":"2019-04-01"}`
 	b := struct {
-		DateField Date	`json:"date"`
+		DateField Date `json:"date"`
 	}{}
 	err := json.Unmarshal([]byte(jsonStr), &b)
 	assert.NoError(t, err)
diff --git a/pkg/util/inputmapping_test.go b/pkg/util/inputmapping_test.go
index 4310463..aeeebb6 100644
--- a/pkg/util/inputmapping_test.go
+++ b/pkg/util/inputmapping_test.go
@@ -13,13 +13,13 @@ func TestParseInputMapping(t *testing.T) {
 	var err error
 
 	src = "key1:value1,key2:value2"
-	expected = map[string]string{"key1": "value1", "key2":"value2"}
+	expected = map[string]string{"key1": "value1", "key2": "value2"}
 	parsed, err = ParseCommandlineMap(src)
 	require.NoError(t, err)
 	assert.Equal(t, expected, parsed)
 
 	src = `key1:"value1,value2",key2:value3`
-	expected = map[string]string{"key1": "value1,value2", "key2":"value3"}
+	expected = map[string]string{"key1": "value1,value2", "key2": "value3"}
 	parsed, err = ParseCommandlineMap(src)
 	require.NoError(t, err)
 	assert.Equal(t, expected, parsed)
@@ -49,13 +49,13 @@ func TestSplitString(t *testing.T) {
 	assert.Equal(t, expected, result)
 
 	src = `"1,2",3`
-	expected = []string{`"1,2"`,"3"}
+	expected = []string{`"1,2"`, "3"}
 	result = splitString(src, ',')
 	require.NoError(t, err)
 	assert.Equal(t, expected, result)
 
 	src = `1,"2,3",`
-	expected = []string{"1",`"2,3"`, ""}
+	expected = []string{"1", `"2,3"`, ""}
 	result = splitString(src, ',')
 	require.NoError(t, err)
 	assert.Equal(t, expected, result)