go.mod: bump github.com/getkin/kin-openapi to v0.131.0
As deepmap/oapi-codegen didn't work with this newer version, upgrade to oapi-codegen/oapi-codegen v2. Mitigating CVE-2025-30153
This commit is contained in:
parent
c5cb0d0618
commit
b2700903ae
403 changed files with 44758 additions and 16347 deletions
201
vendor/github.com/oapi-codegen/oapi-codegen/v2/LICENSE
generated
vendored
Normal file
201
vendor/github.com/oapi-codegen/oapi-codegen/v2/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
562
vendor/github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen/oapi-codegen.go
generated
vendored
Normal file
562
vendor/github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen/oapi-codegen.go
generated
vendored
Normal file
|
|
@ -0,0 +1,562 @@
|
|||
// Copyright 2019 DeepMap, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen"
|
||||
"github.com/oapi-codegen/oapi-codegen/v2/pkg/util"
|
||||
)
|
||||
|
||||
func errExit(format string, args ...interface{}) {
|
||||
if !strings.HasSuffix(format, "\n") {
|
||||
format = format + "\n"
|
||||
}
|
||||
_, _ = fmt.Fprintf(os.Stderr, format, args...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var (
|
||||
flagOutputFile string
|
||||
flagConfigFile string
|
||||
flagOldConfigStyle bool
|
||||
flagOutputConfig bool
|
||||
flagPrintVersion bool
|
||||
flagPackageName string
|
||||
flagPrintUsage bool
|
||||
flagGenerate string
|
||||
flagTemplatesDir string
|
||||
|
||||
// Deprecated: The options below will be removed in a future
|
||||
// release. Please use the new config file format.
|
||||
flagIncludeTags string
|
||||
flagExcludeTags string
|
||||
flagIncludeOperationIDs string
|
||||
flagExcludeOperationIDs string
|
||||
flagImportMapping string
|
||||
flagExcludeSchemas string
|
||||
flagResponseTypeSuffix string
|
||||
flagAliasTypes bool
|
||||
flagInitialismOverrides bool
|
||||
)
|
||||
|
||||
type configuration struct {
|
||||
codegen.Configuration `yaml:",inline"`
|
||||
|
||||
// OutputFile is the filename to output.
|
||||
OutputFile string `yaml:"output,omitempty"`
|
||||
}
|
||||
|
||||
// oldConfiguration is deprecated. Please add no more flags here. It is here
|
||||
// for backwards compatibility, and it will be removed in the future.
|
||||
type oldConfiguration struct {
|
||||
PackageName string `yaml:"package"`
|
||||
GenerateTargets []string `yaml:"generate"`
|
||||
OutputFile string `yaml:"output"`
|
||||
IncludeTags []string `yaml:"include-tags"`
|
||||
ExcludeTags []string `yaml:"exclude-tags"`
|
||||
IncludeOperationIDs []string `yaml:"include-operation-ids"`
|
||||
ExcludeOperationIDs []string `yaml:"exclude-operation-ids"`
|
||||
TemplatesDir string `yaml:"templates"`
|
||||
ImportMapping map[string]string `yaml:"import-mapping"`
|
||||
ExcludeSchemas []string `yaml:"exclude-schemas"`
|
||||
ResponseTypeSuffix string `yaml:"response-type-suffix"`
|
||||
Compatibility codegen.CompatibilityOptions `yaml:"compatibility"`
|
||||
}
|
||||
|
||||
// noVCSVersionOverride allows overriding the version of the application for cases where no Version Control System (VCS) is available when building, for instance when using a Nix derivation.
|
||||
// See documentation for how to use it in examples/no-vcs-version-override/README.md
|
||||
var noVCSVersionOverride string
|
||||
|
||||
func main() {
|
||||
flag.StringVar(&flagOutputFile, "o", "", "Where to output generated code, stdout is default.")
|
||||
flag.BoolVar(&flagOldConfigStyle, "old-config-style", false, "Whether to use the older style config file format.")
|
||||
flag.BoolVar(&flagOutputConfig, "output-config", false, "When true, outputs a configuration file for oapi-codegen using current settings.")
|
||||
flag.StringVar(&flagConfigFile, "config", "", "A YAML config file that controls oapi-codegen behavior.")
|
||||
flag.BoolVar(&flagPrintVersion, "version", false, "When specified, print version and exit.")
|
||||
flag.StringVar(&flagPackageName, "package", "", "The package name for generated code.")
|
||||
flag.BoolVar(&flagPrintUsage, "help", false, "Show this help and exit.")
|
||||
flag.BoolVar(&flagPrintUsage, "h", false, "Same as -help.")
|
||||
|
||||
// All flags below are deprecated, and will be removed in a future release. Please do not
|
||||
// update their behavior.
|
||||
flag.StringVar(&flagGenerate, "generate", "types,client,server,spec",
|
||||
`Comma-separated list of code to generate; valid options: "types", "client", "chi-server", "server", "gin", "gorilla", "spec", "skip-fmt", "skip-prune", "fiber", "iris", "std-http".`)
|
||||
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(&flagIncludeOperationIDs, "include-operation-ids", "", "Only include operations with the given operation-ids. Comma-separated list of operation-ids.")
|
||||
flag.StringVar(&flagExcludeOperationIDs, "exclude-operation-ids", "", "Exclude operations with the given operation-ids. Comma-separated list of operation-ids.")
|
||||
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(&flagResponseTypeSuffix, "response-type-suffix", "", "The suffix used for responses types.")
|
||||
flag.BoolVar(&flagAliasTypes, "alias-types", false, "Alias type declarations of possible.")
|
||||
flag.BoolVar(&flagInitialismOverrides, "initialism-overrides", false, "Use initialism overrides.")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
if flagPrintUsage {
|
||||
flag.Usage()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if flagPrintVersion {
|
||||
bi, ok := debug.ReadBuildInfo()
|
||||
if !ok {
|
||||
fmt.Fprintln(os.Stderr, "error reading build info")
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println(bi.Main.Path + "/cmd/oapi-codegen")
|
||||
version := bi.Main.Version
|
||||
if len(noVCSVersionOverride) > 0 {
|
||||
version = noVCSVersionOverride
|
||||
}
|
||||
fmt.Println(version)
|
||||
return
|
||||
}
|
||||
|
||||
if flag.NArg() < 1 {
|
||||
errExit("Please specify a path to a OpenAPI 3.0 spec file\n")
|
||||
} else if flag.NArg() > 1 {
|
||||
errExit("Only one OpenAPI 3.0 spec file is accepted and it must be the last CLI argument\n")
|
||||
}
|
||||
|
||||
// We will try to infer whether the user has an old-style config, or a new
|
||||
// style. Start with the command line argument. If it's true, we know it's
|
||||
// old config style.
|
||||
var oldConfigStyle *bool
|
||||
if flagOldConfigStyle {
|
||||
oldConfigStyle = &flagOldConfigStyle
|
||||
}
|
||||
|
||||
// We don't know yet, so keep looking. Try to parse the configuration file,
|
||||
// if given.
|
||||
if oldConfigStyle == nil && (flagConfigFile != "") {
|
||||
configFile, err := os.ReadFile(flagConfigFile)
|
||||
if err != nil {
|
||||
errExit("error reading config file '%s': %v\n", flagConfigFile, err)
|
||||
}
|
||||
var oldConfig oldConfiguration
|
||||
oldErr := yaml.UnmarshalStrict(configFile, &oldConfig)
|
||||
|
||||
var newConfig configuration
|
||||
newErr := yaml.UnmarshalStrict(configFile, &newConfig)
|
||||
|
||||
// If one of the two files parses, but the other fails, we know the
|
||||
// answer.
|
||||
if oldErr != nil && newErr == nil {
|
||||
f := false
|
||||
oldConfigStyle = &f
|
||||
} else if oldErr == nil && newErr != nil {
|
||||
t := true
|
||||
oldConfigStyle = &t
|
||||
} else if oldErr != nil && newErr != nil {
|
||||
errExit("error parsing configuration style as old version or new version\n\nerror when parsing using old config version:\n%v\n\nerror when parsing using new config version:\n%v\n", oldErr, newErr)
|
||||
}
|
||||
// Else we fall through, and we still don't know, so we need to infer it from flags.
|
||||
}
|
||||
|
||||
if oldConfigStyle == nil {
|
||||
// If any deprecated flag is present, and config file structure is unknown,
|
||||
// the presence of the deprecated flag means we must be using the old
|
||||
// config style. It should work correctly if we go down the old path,
|
||||
// even if we have a simple config file readable as both types.
|
||||
deprecatedFlagNames := map[string]bool{
|
||||
"include-tags": true,
|
||||
"exclude-tags": true,
|
||||
"import-mapping": true,
|
||||
"exclude-schemas": true,
|
||||
"response-type-suffix": true,
|
||||
"alias-types": true,
|
||||
}
|
||||
hasDeprecatedFlag := false
|
||||
flag.Visit(func(f *flag.Flag) {
|
||||
if deprecatedFlagNames[f.Name] {
|
||||
hasDeprecatedFlag = true
|
||||
}
|
||||
})
|
||||
if hasDeprecatedFlag {
|
||||
t := true
|
||||
oldConfigStyle = &t
|
||||
} else {
|
||||
f := false
|
||||
oldConfigStyle = &f
|
||||
}
|
||||
}
|
||||
|
||||
var opts configuration
|
||||
if !*oldConfigStyle {
|
||||
// We simply read the configuration from disk.
|
||||
if flagConfigFile != "" {
|
||||
buf, err := os.ReadFile(flagConfigFile)
|
||||
if err != nil {
|
||||
errExit("error reading config file '%s': %v\n", flagConfigFile, err)
|
||||
}
|
||||
err = yaml.Unmarshal(buf, &opts)
|
||||
if err != nil {
|
||||
errExit("error parsing'%s' as YAML: %v\n", flagConfigFile, err)
|
||||
}
|
||||
} else {
|
||||
// In the case where no config file is provided, we assume some
|
||||
// defaults, so that when this is invoked very simply, it's similar
|
||||
// to old behavior.
|
||||
opts = configuration{
|
||||
Configuration: codegen.Configuration{
|
||||
Generate: codegen.GenerateOptions{
|
||||
EchoServer: true,
|
||||
Client: true,
|
||||
Models: true,
|
||||
EmbeddedSpec: true,
|
||||
},
|
||||
},
|
||||
OutputFile: flagOutputFile,
|
||||
}
|
||||
}
|
||||
|
||||
if err := updateConfigFromFlags(&opts); err != nil {
|
||||
errExit("error processing flags: %v\n", err)
|
||||
}
|
||||
} else {
|
||||
var oldConfig oldConfiguration
|
||||
if flagConfigFile != "" {
|
||||
buf, err := os.ReadFile(flagConfigFile)
|
||||
if err != nil {
|
||||
errExit("error reading config file '%s': %v\n", flagConfigFile, err)
|
||||
}
|
||||
err = yaml.Unmarshal(buf, &oldConfig)
|
||||
if err != nil {
|
||||
errExit("error parsing'%s' as YAML: %v\n", flagConfigFile, err)
|
||||
}
|
||||
}
|
||||
var err error
|
||||
opts, err = newConfigFromOldConfig(oldConfig)
|
||||
if err != nil {
|
||||
flag.PrintDefaults()
|
||||
errExit("error creating new config from old config: %v\n", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Ensure default values are set if user hasn't specified some needed
|
||||
// fields.
|
||||
opts.Configuration = opts.UpdateDefaults()
|
||||
|
||||
if err := detectPackageName(&opts); err != nil {
|
||||
errExit("%s\n", err)
|
||||
}
|
||||
|
||||
// Now, ensure that the config options are valid.
|
||||
if err := opts.Validate(); err != nil {
|
||||
errExit("configuration error: %v\n", err)
|
||||
}
|
||||
|
||||
// If the user asked to output configuration, output it to stdout and exit
|
||||
if flagOutputConfig {
|
||||
buf, err := yaml.Marshal(opts)
|
||||
if err != nil {
|
||||
errExit("error YAML marshaling configuration: %v\n", err)
|
||||
}
|
||||
fmt.Print(string(buf))
|
||||
return
|
||||
}
|
||||
|
||||
overlayOpts := util.LoadSwaggerWithOverlayOpts{
|
||||
Path: opts.OutputOptions.Overlay.Path,
|
||||
// default to strict, but can be overridden
|
||||
Strict: true,
|
||||
}
|
||||
|
||||
if opts.OutputOptions.Overlay.Strict != nil {
|
||||
overlayOpts.Strict = *opts.OutputOptions.Overlay.Strict
|
||||
}
|
||||
|
||||
swagger, err := util.LoadSwaggerWithOverlay(flag.Arg(0), overlayOpts)
|
||||
if err != nil {
|
||||
errExit("error loading swagger spec in %s\n: %s\n", flag.Arg(0), err)
|
||||
}
|
||||
|
||||
if strings.HasPrefix(swagger.OpenAPI, "3.1.") {
|
||||
fmt.Println("WARNING: You are using an OpenAPI 3.1.x specification, which is not yet supported by oapi-codegen (https://github.com/oapi-codegen/oapi-codegen/issues/373) and so some functionality may not be available. Until oapi-codegen supports OpenAPI 3.1, it is recommended to downgrade your spec to 3.0.x")
|
||||
}
|
||||
|
||||
if len(noVCSVersionOverride) > 0 {
|
||||
opts.Configuration.NoVCSVersionOverride = &noVCSVersionOverride
|
||||
}
|
||||
|
||||
code, err := codegen.Generate(swagger, opts.Configuration)
|
||||
if err != nil {
|
||||
errExit("error generating code: %s\n", err)
|
||||
}
|
||||
|
||||
if opts.OutputFile != "" {
|
||||
err = os.WriteFile(opts.OutputFile, []byte(code), 0o644)
|
||||
if err != nil {
|
||||
errExit("error writing generated code to file: %s\n", err)
|
||||
}
|
||||
} else {
|
||||
fmt.Print(code)
|
||||
}
|
||||
}
|
||||
|
||||
func loadTemplateOverrides(templatesDir string) (map[string]string, error) {
|
||||
templates := make(map[string]string)
|
||||
|
||||
if templatesDir == "" {
|
||||
return templates, nil
|
||||
}
|
||||
|
||||
files, err := os.ReadDir(templatesDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, f := range files {
|
||||
// Recursively load subdirectory files, using the path relative to the templates
|
||||
// directory as the key. This allows for overriding the files in the service-specific
|
||||
// directories (e.g. echo, chi, fiber, etc.).
|
||||
if f.IsDir() {
|
||||
subFiles, err := loadTemplateOverrides(path.Join(templatesDir, f.Name()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for subDir, subFile := range subFiles {
|
||||
templates[path.Join(f.Name(), subDir)] = subFile
|
||||
}
|
||||
continue
|
||||
}
|
||||
data, err := os.ReadFile(path.Join(templatesDir, f.Name()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
templates[f.Name()] = string(data)
|
||||
}
|
||||
|
||||
return templates, nil
|
||||
}
|
||||
|
||||
// detectPackageName detects and sets PackageName if not already set.
|
||||
func detectPackageName(cfg *configuration) error {
|
||||
if cfg.PackageName != "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
if cfg.OutputFile != "" {
|
||||
// Determine from the package name of the output file.
|
||||
dir := filepath.Dir(cfg.PackageName)
|
||||
cmd := exec.Command("go", "list", "-f", "{{.Name}}", dir)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
outStr := string(out)
|
||||
switch {
|
||||
case strings.Contains(outStr, "expected 'package', found 'EOF'"):
|
||||
// Redirecting the output to current directory which hasn't
|
||||
// written anything yet, ignore.
|
||||
case strings.HasPrefix(outStr, "no Go files in"):
|
||||
// No go files yet, ignore.
|
||||
default:
|
||||
// Unexpected failure report.
|
||||
return fmt.Errorf("detect package name for %q output: %q: %w", dir, string(out), err)
|
||||
}
|
||||
} else {
|
||||
cfg.PackageName = string(out)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to determining from the spec file name.
|
||||
parts := strings.Split(filepath.Base(flag.Arg(0)), ".")
|
||||
cfg.PackageName = codegen.LowercaseFirstCharacter(codegen.ToCamelCase(parts[0]))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// updateConfigFromFlags updates a loaded configuration from flags. Flags
|
||||
// override anything in the file. We generate errors for any unsupported
|
||||
// command line flags.
|
||||
func updateConfigFromFlags(cfg *configuration) error {
|
||||
if flagPackageName != "" {
|
||||
cfg.PackageName = flagPackageName
|
||||
}
|
||||
|
||||
if flagGenerate != "types,client,server,spec" {
|
||||
// Override generation and output options from generate command line flag.
|
||||
if err := generationTargets(&cfg.Configuration, util.ParseCommandLineList(flagGenerate)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if flagIncludeTags != "" {
|
||||
cfg.OutputOptions.IncludeTags = util.ParseCommandLineList(flagIncludeTags)
|
||||
}
|
||||
if flagExcludeTags != "" {
|
||||
cfg.OutputOptions.ExcludeTags = util.ParseCommandLineList(flagExcludeTags)
|
||||
}
|
||||
if flagIncludeOperationIDs != "" {
|
||||
cfg.OutputOptions.IncludeOperationIDs = util.ParseCommandLineList(flagIncludeOperationIDs)
|
||||
}
|
||||
if flagExcludeOperationIDs != "" {
|
||||
cfg.OutputOptions.ExcludeOperationIDs = util.ParseCommandLineList(flagExcludeOperationIDs)
|
||||
}
|
||||
|
||||
if flagTemplatesDir != "" {
|
||||
templates, err := loadTemplateOverrides(flagTemplatesDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("load templates from %q: %w", flagTemplatesDir, err)
|
||||
}
|
||||
cfg.OutputOptions.UserTemplates = templates
|
||||
}
|
||||
if flagImportMapping != "" {
|
||||
var err error
|
||||
cfg.ImportMapping, err = util.ParseCommandlineMap(flagImportMapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if flagExcludeSchemas != "" {
|
||||
cfg.OutputOptions.ExcludeSchemas = util.ParseCommandLineList(flagExcludeSchemas)
|
||||
}
|
||||
if flagResponseTypeSuffix != "" {
|
||||
cfg.OutputOptions.ResponseTypeSuffix = flagResponseTypeSuffix
|
||||
}
|
||||
if flagAliasTypes {
|
||||
return fmt.Errorf("--alias-types isn't supported any more")
|
||||
}
|
||||
|
||||
if cfg.OutputFile == "" {
|
||||
cfg.OutputFile = flagOutputFile
|
||||
}
|
||||
|
||||
cfg.OutputOptions.InitialismOverrides = flagInitialismOverrides
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// updateOldConfigFromFlags 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 updateOldConfigFromFlags(cfg oldConfiguration) oldConfiguration {
|
||||
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
|
||||
}
|
||||
|
||||
// generationTargets sets cfg options based on the generation targets.
|
||||
func generationTargets(cfg *codegen.Configuration, targets []string) error {
|
||||
opts := codegen.GenerateOptions{} // Blank to start with.
|
||||
for _, opt := range targets {
|
||||
switch opt {
|
||||
case "iris", "iris-server":
|
||||
opts.IrisServer = true
|
||||
case "chi-server", "chi":
|
||||
opts.ChiServer = true
|
||||
case "fiber-server", "fiber":
|
||||
opts.FiberServer = true
|
||||
case "server", "echo-server", "echo":
|
||||
opts.EchoServer = true
|
||||
case "gin", "gin-server":
|
||||
opts.GinServer = true
|
||||
case "gorilla", "gorilla-server":
|
||||
opts.GorillaServer = true
|
||||
case "std-http", "std-http-server":
|
||||
opts.StdHTTPServer = true
|
||||
case "strict-server":
|
||||
opts.Strict = true
|
||||
case "client":
|
||||
opts.Client = true
|
||||
case "types", "models":
|
||||
opts.Models = true
|
||||
case "spec", "embedded-spec":
|
||||
opts.EmbeddedSpec = true
|
||||
case "skip-fmt":
|
||||
cfg.OutputOptions.SkipFmt = true
|
||||
case "skip-prune":
|
||||
cfg.OutputOptions.SkipPrune = true
|
||||
default:
|
||||
return fmt.Errorf("unknown generate option %q", opt)
|
||||
}
|
||||
}
|
||||
cfg.Generate = opts
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func newConfigFromOldConfig(c oldConfiguration) (configuration, error) {
|
||||
// Take flags into account.
|
||||
cfg := updateOldConfigFromFlags(c)
|
||||
|
||||
// Now, copy over field by field, translating flags and old values as
|
||||
// necessary.
|
||||
opts := codegen.Configuration{
|
||||
PackageName: cfg.PackageName,
|
||||
}
|
||||
opts.OutputOptions.ResponseTypeSuffix = flagResponseTypeSuffix
|
||||
|
||||
if err := generationTargets(&opts, cfg.GenerateTargets); err != nil {
|
||||
return configuration{}, fmt.Errorf("generation targets: %w", err)
|
||||
}
|
||||
|
||||
opts.OutputOptions.IncludeTags = cfg.IncludeTags
|
||||
opts.OutputOptions.ExcludeTags = cfg.ExcludeTags
|
||||
opts.OutputOptions.ExcludeSchemas = cfg.ExcludeSchemas
|
||||
|
||||
templates, err := loadTemplateOverrides(cfg.TemplatesDir)
|
||||
if err != nil {
|
||||
return configuration{}, fmt.Errorf("loading template overrides: %w", err)
|
||||
}
|
||||
opts.OutputOptions.UserTemplates = templates
|
||||
|
||||
opts.ImportMapping = cfg.ImportMapping
|
||||
|
||||
opts.Compatibility = cfg.Compatibility
|
||||
|
||||
return configuration{
|
||||
Configuration: opts,
|
||||
OutputFile: cfg.OutputFile,
|
||||
}, nil
|
||||
}
|
||||
1193
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/codegen.go
generated
vendored
Normal file
1193
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/codegen.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
254
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/configuration.go
generated
vendored
Normal file
254
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/configuration.go
generated
vendored
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
package codegen
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type AdditionalImport struct {
|
||||
Alias string `yaml:"alias,omitempty"`
|
||||
Package string `yaml:"package"`
|
||||
}
|
||||
|
||||
// Configuration defines code generation customizations
|
||||
type Configuration struct {
|
||||
// PackageName to generate the code under
|
||||
PackageName string `yaml:"package"`
|
||||
// Generate specifies which supported output formats to generate
|
||||
Generate GenerateOptions `yaml:"generate,omitempty"`
|
||||
// CompatibilityOptions specifies backward compatibility settings for the code generator
|
||||
Compatibility CompatibilityOptions `yaml:"compatibility,omitempty"`
|
||||
// OutputOptions are used to modify the output code in some way.
|
||||
OutputOptions OutputOptions `yaml:"output-options,omitempty"`
|
||||
// ImportMapping specifies the golang package path for each external reference
|
||||
ImportMapping map[string]string `yaml:"import-mapping,omitempty"`
|
||||
// AdditionalImports defines any additional Go imports to add to the generated code
|
||||
AdditionalImports []AdditionalImport `yaml:"additional-imports,omitempty"`
|
||||
// NoVCSVersionOverride allows overriding the version of the application for cases where no Version Control System (VCS) is available when building, for instance when using a Nix derivation.
|
||||
// See documentation for how to use it in examples/no-vcs-version-override/README.md
|
||||
NoVCSVersionOverride *string `yaml:"-"`
|
||||
}
|
||||
|
||||
// Validate checks whether Configuration represent a valid configuration
|
||||
func (o Configuration) Validate() error {
|
||||
if o.PackageName == "" {
|
||||
return errors.New("package name must be specified")
|
||||
}
|
||||
|
||||
// Only one server type should be specified at a time.
|
||||
nServers := 0
|
||||
if o.Generate.IrisServer {
|
||||
nServers++
|
||||
}
|
||||
if o.Generate.ChiServer {
|
||||
nServers++
|
||||
}
|
||||
if o.Generate.FiberServer {
|
||||
nServers++
|
||||
}
|
||||
if o.Generate.EchoServer {
|
||||
nServers++
|
||||
}
|
||||
if o.Generate.GorillaServer {
|
||||
nServers++
|
||||
}
|
||||
if o.Generate.StdHTTPServer {
|
||||
nServers++
|
||||
}
|
||||
if o.Generate.GinServer {
|
||||
nServers++
|
||||
}
|
||||
if nServers > 1 {
|
||||
return errors.New("only one server type is supported at a time")
|
||||
}
|
||||
|
||||
var errs []error
|
||||
if problems := o.Generate.Validate(); problems != nil {
|
||||
for k, v := range problems {
|
||||
errs = append(errs, fmt.Errorf("`generate` configuration for %v was incorrect: %v", k, v))
|
||||
}
|
||||
}
|
||||
|
||||
if problems := o.Compatibility.Validate(); problems != nil {
|
||||
for k, v := range problems {
|
||||
errs = append(errs, fmt.Errorf("`compatibility-options` configuration for %v was incorrect: %v", k, v))
|
||||
}
|
||||
}
|
||||
|
||||
if problems := o.OutputOptions.Validate(); problems != nil {
|
||||
for k, v := range problems {
|
||||
errs = append(errs, fmt.Errorf("`output-options` configuration for %v was incorrect: %v", k, v))
|
||||
}
|
||||
}
|
||||
|
||||
err := errors.Join(errs...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to validate configuration: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateDefaults sets reasonable default values for unset fields in Configuration
|
||||
func (o Configuration) UpdateDefaults() Configuration {
|
||||
if reflect.ValueOf(o.Generate).IsZero() {
|
||||
o.Generate = GenerateOptions{
|
||||
EchoServer: true,
|
||||
Models: true,
|
||||
EmbeddedSpec: true,
|
||||
}
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
// GenerateOptions specifies which supported output formats to generate.
|
||||
type GenerateOptions struct {
|
||||
// IrisServer specifies whether to generate iris server boilerplate
|
||||
IrisServer bool `yaml:"iris-server,omitempty"`
|
||||
// ChiServer specifies whether to generate chi server boilerplate
|
||||
ChiServer bool `yaml:"chi-server,omitempty"`
|
||||
// FiberServer specifies whether to generate fiber server boilerplate
|
||||
FiberServer bool `yaml:"fiber-server,omitempty"`
|
||||
// EchoServer specifies whether to generate echo server boilerplate
|
||||
EchoServer bool `yaml:"echo-server,omitempty"`
|
||||
// GinServer specifies whether to generate gin server boilerplate
|
||||
GinServer bool `yaml:"gin-server,omitempty"`
|
||||
// GorillaServer specifies whether to generate Gorilla server boilerplate
|
||||
GorillaServer bool `yaml:"gorilla-server,omitempty"`
|
||||
// StdHTTPServer specifies whether to generate stdlib http server boilerplate
|
||||
StdHTTPServer bool `yaml:"std-http-server,omitempty"`
|
||||
// Strict specifies whether to generate strict server wrapper
|
||||
Strict bool `yaml:"strict-server,omitempty"`
|
||||
// Client specifies whether to generate client boilerplate
|
||||
Client bool `yaml:"client,omitempty"`
|
||||
// Models specifies whether to generate type definitions
|
||||
Models bool `yaml:"models,omitempty"`
|
||||
// EmbeddedSpec indicates whether to embed the swagger spec in the generated code
|
||||
EmbeddedSpec bool `yaml:"embedded-spec,omitempty"`
|
||||
}
|
||||
|
||||
func (oo GenerateOptions) Validate() map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CompatibilityOptions specifies backward compatibility settings for the
|
||||
// code generator.
|
||||
type CompatibilityOptions struct {
|
||||
// In the past, we merged schemas for `allOf` by inlining each schema
|
||||
// within the schema list. This approach, though, is incorrect because
|
||||
// `allOf` merges at the schema definition level, not at the resulting model
|
||||
// level. So, new behavior merges OpenAPI specs but generates different code
|
||||
// than we have in the past. Set OldMergeSchemas to true for the old behavior.
|
||||
// Please see https://github.com/oapi-codegen/oapi-codegen/issues/531
|
||||
OldMergeSchemas bool `yaml:"old-merge-schemas,omitempty"`
|
||||
// Enum values can generate conflicting typenames, so we've updated the
|
||||
// code for enum generation to avoid these conflicts, but it will result
|
||||
// in some enum types being renamed in existing code. Set OldEnumConflicts to true
|
||||
// to revert to old behavior. Please see:
|
||||
// Please see https://github.com/oapi-codegen/oapi-codegen/issues/549
|
||||
OldEnumConflicts bool `yaml:"old-enum-conflicts,omitempty"`
|
||||
// It was a mistake to generate a go type definition for every $ref in
|
||||
// the OpenAPI schema. New behavior uses type aliases where possible, but
|
||||
// this can generate code which breaks existing builds. Set OldAliasing to true
|
||||
// for old behavior.
|
||||
// Please see https://github.com/oapi-codegen/oapi-codegen/issues/549
|
||||
OldAliasing bool `yaml:"old-aliasing,omitempty"`
|
||||
// When an object contains no members, and only an additionalProperties specification,
|
||||
// it is flattened to a map
|
||||
DisableFlattenAdditionalProperties bool `yaml:"disable-flatten-additional-properties,omitempty"`
|
||||
// When an object property is both required and readOnly the go model is generated
|
||||
// as a pointer. Set DisableRequiredReadOnlyAsPointer to true to mark them as non pointer.
|
||||
// Please see https://github.com/oapi-codegen/oapi-codegen/issues/604
|
||||
DisableRequiredReadOnlyAsPointer bool `yaml:"disable-required-readonly-as-pointer,omitempty"`
|
||||
// When set to true, always prefix enum values with their type name instead of only
|
||||
// when typenames would be conflicting.
|
||||
AlwaysPrefixEnumValues bool `yaml:"always-prefix-enum-values,omitempty"`
|
||||
// Our generated code for Chi has historically inverted the order in which Chi middleware is
|
||||
// applied such that the last invoked middleware ends up executing first in the Chi chain
|
||||
// This resolves the behavior such that middlewares are chained in the order they are invoked.
|
||||
// Please see https://github.com/oapi-codegen/oapi-codegen/issues/786
|
||||
ApplyChiMiddlewareFirstToLast bool `yaml:"apply-chi-middleware-first-to-last,omitempty"`
|
||||
// Our generated code for gorilla/mux has historically inverted the order in which gorilla/mux middleware is
|
||||
// applied such that the last invoked middleware ends up executing first in the middlewares chain
|
||||
// This resolves the behavior such that middlewares are chained in the order they are invoked.
|
||||
// Please see https://github.com/oapi-codegen/oapi-codegen/issues/841
|
||||
ApplyGorillaMiddlewareFirstToLast bool `yaml:"apply-gorilla-middleware-first-to-last,omitempty"`
|
||||
// CircularReferenceLimit allows controlling the limit for circular reference checking.
|
||||
// In some OpenAPI specifications, we have a higher number of circular
|
||||
// references than is allowed out-of-the-box, but can be tuned to allow
|
||||
// traversing them.
|
||||
// Deprecated: In kin-openapi v0.126.0 (https://github.com/getkin/kin-openapi/tree/v0.126.0?tab=readme-ov-file#v01260) the Circular Reference Counter functionality was removed, instead resolving all references with backtracking, to avoid needing to provide a limit to reference counts.
|
||||
CircularReferenceLimit int `yaml:"circular-reference-limit"`
|
||||
// AllowUnexportedStructFieldNames makes it possible to output structs that have fields that are unexported.
|
||||
//
|
||||
// This is expected to be used in conjunction with `x-go-name` and `x-oapi-codegen-only-honour-go-name` to override the resulting output field name, and `x-oapi-codegen-extra-tags` to not produce JSON tags for `encoding/json`, such as:
|
||||
//
|
||||
// ```yaml
|
||||
// id:
|
||||
// type: string
|
||||
// x-go-name: accountIdentifier
|
||||
// x-oapi-codegen-extra-tags:
|
||||
// json: "-"
|
||||
// x-oapi-codegen-only-honour-go-name: true
|
||||
// ```
|
||||
//
|
||||
// NOTE that this can be confusing to users of your OpenAPI specification, who may see a field present and therefore be expecting to see/use it in the request/response, without understanding the nuance of how `oapi-codegen` generates the code.
|
||||
AllowUnexportedStructFieldNames bool `yaml:"allow-unexported-struct-field-names"`
|
||||
}
|
||||
|
||||
func (co CompatibilityOptions) Validate() map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// OutputOptions are used to modify the output code in some way.
|
||||
type OutputOptions struct {
|
||||
// Whether to skip go imports on the generated code
|
||||
SkipFmt bool `yaml:"skip-fmt,omitempty"`
|
||||
// Whether to skip pruning unused components on the generated code
|
||||
SkipPrune bool `yaml:"skip-prune,omitempty"`
|
||||
// Only include operations that have one of these tags. Ignored when empty.
|
||||
IncludeTags []string `yaml:"include-tags,omitempty"`
|
||||
// Exclude operations that have one of these tags. Ignored when empty.
|
||||
ExcludeTags []string `yaml:"exclude-tags,omitempty"`
|
||||
// Only include operations that have one of these operation-ids. Ignored when empty.
|
||||
IncludeOperationIDs []string `yaml:"include-operation-ids,omitempty"`
|
||||
// Exclude operations that have one of these operation-ids. Ignored when empty.
|
||||
ExcludeOperationIDs []string `yaml:"exclude-operation-ids,omitempty"`
|
||||
// Override built-in templates from user-provided files
|
||||
UserTemplates map[string]string `yaml:"user-templates,omitempty"`
|
||||
|
||||
// Exclude from generation schemas with given names. Ignored when empty.
|
||||
ExcludeSchemas []string `yaml:"exclude-schemas,omitempty"`
|
||||
// The suffix used for responses types
|
||||
ResponseTypeSuffix string `yaml:"response-type-suffix,omitempty"`
|
||||
// Override the default generated client type with the value
|
||||
ClientTypeName string `yaml:"client-type-name,omitempty"`
|
||||
// Whether to use the initialism overrides
|
||||
InitialismOverrides bool `yaml:"initialism-overrides,omitempty"`
|
||||
// Whether to generate nullable type for nullable fields
|
||||
NullableType bool `yaml:"nullable-type,omitempty"`
|
||||
|
||||
// DisableTypeAliasesForType allows defining which OpenAPI `type`s will explicitly not use type aliases
|
||||
// Currently supports:
|
||||
// "array"
|
||||
DisableTypeAliasesForType []string `yaml:"disable-type-aliases-for-type"`
|
||||
|
||||
// NameNormalizer is the method used to normalize Go names and types, for instance converting the text `MyApi` to `MyAPI`. Corresponds with the constants defined for `codegen.NameNormalizerFunction`
|
||||
NameNormalizer string `yaml:"name-normalizer,omitempty"`
|
||||
|
||||
// Overlay defines configuration for the OpenAPI Overlay (https://github.com/OAI/Overlay-Specification) to manipulate the OpenAPI specification before generation. This allows modifying the specification without needing to apply changes directly to it, making it easier to keep it up-to-date.
|
||||
Overlay OutputOptionsOverlay `yaml:"overlay"`
|
||||
}
|
||||
|
||||
func (oo OutputOptions) Validate() map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
type OutputOptionsOverlay struct {
|
||||
Path string `yaml:"path"`
|
||||
|
||||
// Strict defines whether the Overlay should be applied in a strict way, highlighting any actions that will not take any effect. This can, however, lead to more work when testing new actions in an Overlay, so can be turned off with this setting.
|
||||
// Defaults to true.
|
||||
Strict *bool `yaml:"strict,omitempty"`
|
||||
}
|
||||
113
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/extension.go
generated
vendored
Normal file
113
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/extension.go
generated
vendored
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
package codegen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const (
|
||||
// extPropGoType overrides the generated type definition.
|
||||
extPropGoType = "x-go-type"
|
||||
// extPropGoTypeSkipOptionalPointer specifies that optional fields should
|
||||
// be the type itself instead of a pointer to the type.
|
||||
extPropGoTypeSkipOptionalPointer = "x-go-type-skip-optional-pointer"
|
||||
// extPropGoImport specifies the module to import which provides above type
|
||||
extPropGoImport = "x-go-type-import"
|
||||
// extGoName is used to override a field name
|
||||
extGoName = "x-go-name"
|
||||
// extGoTypeName is used to override a generated typename for something.
|
||||
extGoTypeName = "x-go-type-name"
|
||||
extPropGoJsonIgnore = "x-go-json-ignore"
|
||||
extPropOmitEmpty = "x-omitempty"
|
||||
extPropExtraTags = "x-oapi-codegen-extra-tags"
|
||||
extEnumVarNames = "x-enum-varnames"
|
||||
extEnumNames = "x-enumNames"
|
||||
extDeprecationReason = "x-deprecated-reason"
|
||||
extOrder = "x-order"
|
||||
// extOapiCodegenOnlyHonourGoName is to be used to explicitly enforce the generation of a field as the `x-go-name` extension has describe it.
|
||||
// This is intended to be used alongside the `allow-unexported-struct-field-names` Compatibility option
|
||||
extOapiCodegenOnlyHonourGoName = "x-oapi-codegen-only-honour-go-name"
|
||||
)
|
||||
|
||||
func extString(extPropValue interface{}) (string, error) {
|
||||
str, ok := extPropValue.(string)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("failed to convert type: %T", extPropValue)
|
||||
}
|
||||
return str, nil
|
||||
}
|
||||
|
||||
func extTypeName(extPropValue interface{}) (string, error) {
|
||||
return extString(extPropValue)
|
||||
}
|
||||
|
||||
func extParsePropGoTypeSkipOptionalPointer(extPropValue interface{}) (bool, error) {
|
||||
goTypeSkipOptionalPointer, ok := extPropValue.(bool)
|
||||
if !ok {
|
||||
return false, fmt.Errorf("failed to convert type: %T", extPropValue)
|
||||
}
|
||||
return goTypeSkipOptionalPointer, nil
|
||||
}
|
||||
|
||||
func extParseGoFieldName(extPropValue interface{}) (string, error) {
|
||||
return extString(extPropValue)
|
||||
}
|
||||
|
||||
func extParseOmitEmpty(extPropValue interface{}) (bool, error) {
|
||||
omitEmpty, ok := extPropValue.(bool)
|
||||
if !ok {
|
||||
return false, fmt.Errorf("failed to convert type: %T", extPropValue)
|
||||
}
|
||||
return omitEmpty, nil
|
||||
}
|
||||
|
||||
func extExtraTags(extPropValue interface{}) (map[string]string, error) {
|
||||
tagsI, ok := extPropValue.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("failed to convert type: %T", extPropValue)
|
||||
}
|
||||
tags := make(map[string]string, len(tagsI))
|
||||
for k, v := range tagsI {
|
||||
vs, ok := v.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("failed to convert type: %T", v)
|
||||
}
|
||||
tags[k] = vs
|
||||
}
|
||||
return tags, nil
|
||||
}
|
||||
|
||||
func extParseGoJsonIgnore(extPropValue interface{}) (bool, error) {
|
||||
goJsonIgnore, ok := extPropValue.(bool)
|
||||
if !ok {
|
||||
return false, fmt.Errorf("failed to convert type: %T", extPropValue)
|
||||
}
|
||||
return goJsonIgnore, nil
|
||||
}
|
||||
|
||||
func extParseEnumVarNames(extPropValue interface{}) ([]string, error) {
|
||||
namesI, ok := extPropValue.([]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("failed to convert type: %T", extPropValue)
|
||||
}
|
||||
names := make([]string, len(namesI))
|
||||
for i, v := range namesI {
|
||||
vs, ok := v.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("failed to convert type: %T", v)
|
||||
}
|
||||
names[i] = vs
|
||||
}
|
||||
return names, nil
|
||||
}
|
||||
|
||||
func extParseDeprecationReason(extPropValue interface{}) (string, error) {
|
||||
return extString(extPropValue)
|
||||
}
|
||||
|
||||
func extParseOapiCodegenOnlyHonourGoName(extPropValue interface{}) (bool, error) {
|
||||
onlyHonourGoName, ok := extPropValue.(bool)
|
||||
if !ok {
|
||||
return false, fmt.Errorf("failed to convert type: %T", extPropValue)
|
||||
}
|
||||
return onlyHonourGoName, nil
|
||||
}
|
||||
80
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/externalref.go
generated
vendored
Normal file
80
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/externalref.go
generated
vendored
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
package codegen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ensureExternalRefsInRequestBodyDefinitions ensures that when an externalRef (`$ref` that points to a file that isn't the current spec) is encountered, we make sure we update our underlying `RefType` to make sure that we point to that type.
|
||||
// This only happens if we have a non-empty `ref` passed in, and that `ref` isn't pointing to something in our file
|
||||
// NOTE that the pointer here allows us to pass in a reference and edit in-place
|
||||
func ensureExternalRefsInRequestBodyDefinitions(defs *[]RequestBodyDefinition, ref string) {
|
||||
if ref == "" {
|
||||
return
|
||||
}
|
||||
|
||||
for i, rbd := range *defs {
|
||||
ensureExternalRefsInSchema(&rbd.Schema, ref)
|
||||
|
||||
// make sure we then update it in-place
|
||||
(*defs)[i] = rbd
|
||||
}
|
||||
}
|
||||
|
||||
// ensureExternalRefsInResponseDefinitions ensures that when an externalRef (`$ref` that points to a file that isn't the current spec) is encountered, we make sure we update our underlying `RefType` to make sure that we point to that type.
|
||||
// This only happens if we have a non-empty `ref` passed in, and that `ref` isn't pointing to something in our file
|
||||
// NOTE that the pointer here allows us to pass in a reference and edit in-place
|
||||
func ensureExternalRefsInResponseDefinitions(defs *[]ResponseDefinition, ref string) {
|
||||
if ref == "" {
|
||||
return
|
||||
}
|
||||
|
||||
for i, rd := range *defs {
|
||||
for j, rcd := range rd.Contents {
|
||||
ensureExternalRefsInSchema(&rcd.Schema, ref)
|
||||
|
||||
// make sure we then update it in-place
|
||||
rd.Contents[j] = rcd
|
||||
}
|
||||
|
||||
// make sure we then update it in-place
|
||||
(*defs)[i] = rd
|
||||
}
|
||||
}
|
||||
|
||||
// ensureExternalRefsInParameterDefinitions ensures that when an externalRef (`$ref` that points to a file that isn't the current spec) is encountered, we make sure we update our underlying `RefType` to make sure that we point to that type.
|
||||
// This only happens if we have a non-empty `ref` passed in, and that `ref` isn't pointing to something in our file
|
||||
// NOTE that the pointer here allows us to pass in a reference and edit in-place
|
||||
func ensureExternalRefsInParameterDefinitions(defs *[]ParameterDefinition, ref string) {
|
||||
if ref == "" {
|
||||
return
|
||||
}
|
||||
|
||||
for i, pd := range *defs {
|
||||
ensureExternalRefsInSchema(&pd.Schema, ref)
|
||||
|
||||
// make sure we then update it in-place
|
||||
(*defs)[i] = pd
|
||||
}
|
||||
}
|
||||
|
||||
// ensureExternalRefsInSchema ensures that when an externalRef (`$ref` that points to a file that isn't the current spec) is encountered, we make sure we update our underlying `RefType` to make sure that we point to that type.
|
||||
//
|
||||
// This only happens if we have a non-empty `ref` passed in, and that `ref` isn't pointing to something in our file
|
||||
//
|
||||
// NOTE that the pointer here allows us to pass in a reference and edit in-place
|
||||
func ensureExternalRefsInSchema(schema *Schema, ref string) {
|
||||
if ref == "" {
|
||||
return
|
||||
}
|
||||
|
||||
// if this is already defined as the start of a struct, we shouldn't inject **??**
|
||||
if strings.HasPrefix(schema.GoType, "struct {") {
|
||||
return
|
||||
}
|
||||
|
||||
parts := strings.SplitN(ref, "#", 2)
|
||||
if pack, ok := globalState.importMapping[parts[0]]; ok {
|
||||
schema.RefType = fmt.Sprintf("%s.%s", pack.Name, schema.GoType)
|
||||
}
|
||||
}
|
||||
88
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/filter.go
generated
vendored
Normal file
88
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/filter.go
generated
vendored
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
package codegen
|
||||
|
||||
import "github.com/getkin/kin-openapi/openapi3"
|
||||
|
||||
func sliceToMap(items []string) map[string]bool {
|
||||
m := make(map[string]bool, len(items))
|
||||
for _, item := range items {
|
||||
m[item] = true
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func filterOperationsByTag(swagger *openapi3.T, opts Configuration) {
|
||||
if len(opts.OutputOptions.ExcludeTags) > 0 {
|
||||
operationsWithTags(swagger.Paths, sliceToMap(opts.OutputOptions.ExcludeTags), true)
|
||||
}
|
||||
if len(opts.OutputOptions.IncludeTags) > 0 {
|
||||
operationsWithTags(swagger.Paths, sliceToMap(opts.OutputOptions.IncludeTags), false)
|
||||
}
|
||||
}
|
||||
|
||||
func operationsWithTags(paths *openapi3.Paths, tags map[string]bool, exclude bool) {
|
||||
if paths == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, pathItem := range paths.Map() {
|
||||
ops := pathItem.Operations()
|
||||
names := make([]string, 0, len(ops))
|
||||
for name, op := range ops {
|
||||
if operationHasTag(op, tags) == exclude {
|
||||
names = append(names, name)
|
||||
}
|
||||
}
|
||||
for _, name := range names {
|
||||
pathItem.SetOperation(name, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// operationHasTag returns true if the operation is tagged with any of tags
|
||||
func operationHasTag(op *openapi3.Operation, tags map[string]bool) bool {
|
||||
if op == nil {
|
||||
return false
|
||||
}
|
||||
for _, hasTag := range op.Tags {
|
||||
if tags[hasTag] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func filterOperationsByOperationID(swagger *openapi3.T, opts Configuration) {
|
||||
if len(opts.OutputOptions.ExcludeOperationIDs) > 0 {
|
||||
operationsWithOperationIDs(swagger.Paths, sliceToMap(opts.OutputOptions.ExcludeOperationIDs), true)
|
||||
}
|
||||
if len(opts.OutputOptions.IncludeOperationIDs) > 0 {
|
||||
operationsWithOperationIDs(swagger.Paths, sliceToMap(opts.OutputOptions.IncludeOperationIDs), false)
|
||||
}
|
||||
}
|
||||
|
||||
func operationsWithOperationIDs(paths *openapi3.Paths, operationIDs map[string]bool, exclude bool) {
|
||||
if paths == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, pathItem := range paths.Map() {
|
||||
ops := pathItem.Operations()
|
||||
names := make([]string, 0, len(ops))
|
||||
for name, op := range ops {
|
||||
if operationHasOperationID(op, operationIDs) == exclude {
|
||||
names = append(names, name)
|
||||
}
|
||||
}
|
||||
for _, name := range names {
|
||||
pathItem.SetOperation(name, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// operationHasOperationID returns true if the operation has operation id is included in operation ids
|
||||
func operationHasOperationID(op *openapi3.Operation, operationIDs map[string]bool) bool {
|
||||
if op == nil {
|
||||
return false
|
||||
}
|
||||
return operationIDs[op.OperationID]
|
||||
}
|
||||
77
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/inline.go
generated
vendored
Normal file
77
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/inline.go
generated
vendored
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright 2019 DeepMap, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"text/template"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
)
|
||||
|
||||
// GenerateInlinedSpec generates a gzipped, base64 encoded JSON representation of the
|
||||
// swagger definition, which we embed inside the generated code.
|
||||
func GenerateInlinedSpec(t *template.Template, importMapping importMap, swagger *openapi3.T) (string, error) {
|
||||
// ensure that any external file references are embedded into the embedded spec
|
||||
swagger.InternalizeRefs(context.Background(), nil)
|
||||
// Marshal to json
|
||||
encoded, err := swagger.MarshalJSON()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error marshaling swagger: %w", err)
|
||||
}
|
||||
|
||||
// gzip
|
||||
var buf bytes.Buffer
|
||||
zw, err := gzip.NewWriterLevel(&buf, gzip.BestCompression)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error creating gzip compressor: %w", err)
|
||||
}
|
||||
_, err = zw.Write(encoded)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error gzipping swagger file: %w", err)
|
||||
}
|
||||
err = zw.Close()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error gzipping swagger file: %w", err)
|
||||
}
|
||||
str := base64.StdEncoding.EncodeToString(buf.Bytes())
|
||||
|
||||
var parts []string
|
||||
const width = 80
|
||||
|
||||
// Chop up the string into an array of strings.
|
||||
for len(str) > width {
|
||||
part := str[0:width]
|
||||
parts = append(parts, part)
|
||||
str = str[width:]
|
||||
}
|
||||
if len(str) > 0 {
|
||||
parts = append(parts, str)
|
||||
}
|
||||
|
||||
return GenerateTemplates(
|
||||
[]string{"inline.tmpl"},
|
||||
t,
|
||||
struct {
|
||||
SpecParts []string
|
||||
ImportMapping importMap
|
||||
}{
|
||||
SpecParts: parts,
|
||||
ImportMapping: importMapping,
|
||||
})
|
||||
}
|
||||
249
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/merge_schemas.go
generated
vendored
Normal file
249
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/merge_schemas.go
generated
vendored
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
package codegen
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
)
|
||||
|
||||
// MergeSchemas merges all the fields in the schemas supplied into one giant schema.
|
||||
// The idea is that we merge all fields together into one schema.
|
||||
func MergeSchemas(allOf []*openapi3.SchemaRef, path []string) (Schema, error) {
|
||||
// If someone asked for the old way, for backward compatibility, return the
|
||||
// old style result.
|
||||
if globalState.options.Compatibility.OldMergeSchemas {
|
||||
return mergeSchemasV1(allOf, path)
|
||||
}
|
||||
return mergeSchemas(allOf, path)
|
||||
}
|
||||
|
||||
func mergeSchemas(allOf []*openapi3.SchemaRef, path []string) (Schema, error) {
|
||||
n := len(allOf)
|
||||
|
||||
if n == 1 {
|
||||
return GenerateGoSchema(allOf[0], path)
|
||||
}
|
||||
|
||||
schema, err := valueWithPropagatedRef(allOf[0])
|
||||
if err != nil {
|
||||
return Schema{}, err
|
||||
}
|
||||
|
||||
for i := 1; i < n; i++ {
|
||||
var err error
|
||||
oneOfSchema, err := valueWithPropagatedRef(allOf[i])
|
||||
if err != nil {
|
||||
return Schema{}, err
|
||||
}
|
||||
schema, err = mergeOpenapiSchemas(schema, oneOfSchema, true)
|
||||
if err != nil {
|
||||
return Schema{}, fmt.Errorf("error merging schemas for AllOf: %w", err)
|
||||
}
|
||||
}
|
||||
return GenerateGoSchema(openapi3.NewSchemaRef("", &schema), path)
|
||||
}
|
||||
|
||||
// valueWithPropagatedRef returns a copy of ref schema with its Properties refs
|
||||
// updated if ref itself is external. Otherwise, return ref.Value as-is.
|
||||
func valueWithPropagatedRef(ref *openapi3.SchemaRef) (openapi3.Schema, error) {
|
||||
if len(ref.Ref) == 0 || ref.Ref[0] == '#' {
|
||||
return *ref.Value, nil
|
||||
}
|
||||
|
||||
pathParts := strings.Split(ref.Ref, "#")
|
||||
if len(pathParts) < 1 || len(pathParts) > 2 {
|
||||
return openapi3.Schema{}, fmt.Errorf("unsupported reference: %s", ref.Ref)
|
||||
}
|
||||
remoteComponent := pathParts[0]
|
||||
|
||||
// remote ref
|
||||
schema := *ref.Value
|
||||
for _, value := range schema.Properties {
|
||||
if len(value.Ref) > 0 && value.Ref[0] == '#' {
|
||||
// local reference, should propagate remote
|
||||
value.Ref = remoteComponent + value.Ref
|
||||
}
|
||||
}
|
||||
|
||||
return schema, nil
|
||||
}
|
||||
|
||||
func mergeAllOf(allOf []*openapi3.SchemaRef) (openapi3.Schema, error) {
|
||||
var schema openapi3.Schema
|
||||
for _, schemaRef := range allOf {
|
||||
var err error
|
||||
schema, err = mergeOpenapiSchemas(schema, *schemaRef.Value, true)
|
||||
if err != nil {
|
||||
return openapi3.Schema{}, fmt.Errorf("error merging schemas for AllOf: %w", err)
|
||||
}
|
||||
}
|
||||
return schema, nil
|
||||
}
|
||||
|
||||
// mergeOpenapiSchemas merges two openAPI schemas and returns the schema
|
||||
// all of whose fields are composed.
|
||||
func mergeOpenapiSchemas(s1, s2 openapi3.Schema, allOf bool) (openapi3.Schema, error) {
|
||||
var result openapi3.Schema
|
||||
|
||||
result.Extensions = make(map[string]interface{})
|
||||
for k, v := range s1.Extensions {
|
||||
result.Extensions[k] = v
|
||||
}
|
||||
for k, v := range s2.Extensions {
|
||||
// TODO: Check for collisions
|
||||
result.Extensions[k] = v
|
||||
}
|
||||
|
||||
result.OneOf = append(s1.OneOf, s2.OneOf...)
|
||||
|
||||
// We are going to make AllOf transitive, so that merging an AllOf that
|
||||
// contains AllOf's will result in a flat object.
|
||||
var err error
|
||||
if s1.AllOf != nil {
|
||||
var merged openapi3.Schema
|
||||
merged, err = mergeAllOf(s1.AllOf)
|
||||
if err != nil {
|
||||
return openapi3.Schema{}, fmt.Errorf("error transitive merging AllOf on schema 1")
|
||||
}
|
||||
s1 = merged
|
||||
}
|
||||
if s2.AllOf != nil {
|
||||
var merged openapi3.Schema
|
||||
merged, err = mergeAllOf(s2.AllOf)
|
||||
if err != nil {
|
||||
return openapi3.Schema{}, fmt.Errorf("error transitive merging AllOf on schema 2")
|
||||
}
|
||||
s2 = merged
|
||||
}
|
||||
|
||||
result.AllOf = append(s1.AllOf, s2.AllOf...)
|
||||
|
||||
if s1.Type.Slice() != nil && s2.Type.Slice() != nil && !equalTypes(s1.Type, s2.Type) {
|
||||
return openapi3.Schema{}, fmt.Errorf("can not merge incompatible types: %v, %v", s1.Type.Slice(), s2.Type.Slice())
|
||||
}
|
||||
result.Type = s1.Type
|
||||
|
||||
if s1.Format != s2.Format {
|
||||
return openapi3.Schema{}, errors.New("can not merge incompatible formats")
|
||||
}
|
||||
result.Format = s1.Format
|
||||
|
||||
// For Enums, do we union, or intersect? This is a bit vague. I choose
|
||||
// to be more permissive and union.
|
||||
result.Enum = append(s1.Enum, s2.Enum...)
|
||||
|
||||
// I don't know how to handle two different defaults.
|
||||
if s1.Default != nil || s2.Default != nil {
|
||||
return openapi3.Schema{}, errors.New("merging two sets of defaults is undefined")
|
||||
}
|
||||
if s1.Default != nil {
|
||||
result.Default = s1.Default
|
||||
}
|
||||
if s2.Default != nil {
|
||||
result.Default = s2.Default
|
||||
}
|
||||
|
||||
// We skip Example
|
||||
// We skip ExternalDocs
|
||||
|
||||
// If two schemas disagree on any of these flags, we error out.
|
||||
if s1.UniqueItems != s2.UniqueItems {
|
||||
return openapi3.Schema{}, errors.New("merging two schemas with different UniqueItems")
|
||||
|
||||
}
|
||||
result.UniqueItems = s1.UniqueItems
|
||||
|
||||
if s1.ExclusiveMin != s2.ExclusiveMin {
|
||||
return openapi3.Schema{}, errors.New("merging two schemas with different ExclusiveMin")
|
||||
|
||||
}
|
||||
result.ExclusiveMin = s1.ExclusiveMin
|
||||
|
||||
if s1.ExclusiveMax != s2.ExclusiveMax {
|
||||
return openapi3.Schema{}, errors.New("merging two schemas with different ExclusiveMax")
|
||||
|
||||
}
|
||||
result.ExclusiveMax = s1.ExclusiveMax
|
||||
|
||||
if s1.Nullable != s2.Nullable {
|
||||
return openapi3.Schema{}, errors.New("merging two schemas with different Nullable")
|
||||
|
||||
}
|
||||
result.Nullable = s1.Nullable
|
||||
|
||||
if s1.ReadOnly != s2.ReadOnly {
|
||||
return openapi3.Schema{}, errors.New("merging two schemas with different ReadOnly")
|
||||
|
||||
}
|
||||
result.ReadOnly = s1.ReadOnly
|
||||
|
||||
if s1.WriteOnly != s2.WriteOnly {
|
||||
return openapi3.Schema{}, errors.New("merging two schemas with different WriteOnly")
|
||||
|
||||
}
|
||||
result.WriteOnly = s1.WriteOnly
|
||||
|
||||
if s1.AllowEmptyValue != s2.AllowEmptyValue {
|
||||
return openapi3.Schema{}, errors.New("merging two schemas with different AllowEmptyValue")
|
||||
|
||||
}
|
||||
result.AllowEmptyValue = s1.AllowEmptyValue
|
||||
|
||||
// Required. We merge these.
|
||||
result.Required = append(s1.Required, s2.Required...)
|
||||
|
||||
// We merge all properties
|
||||
result.Properties = make(map[string]*openapi3.SchemaRef)
|
||||
for k, v := range s1.Properties {
|
||||
result.Properties[k] = v
|
||||
}
|
||||
for k, v := range s2.Properties {
|
||||
// TODO: detect conflicts
|
||||
result.Properties[k] = v
|
||||
}
|
||||
|
||||
if isAdditionalPropertiesExplicitFalse(&s1) || isAdditionalPropertiesExplicitFalse(&s2) {
|
||||
result.WithoutAdditionalProperties()
|
||||
} else if s1.AdditionalProperties.Schema != nil {
|
||||
if s2.AdditionalProperties.Schema != nil {
|
||||
return openapi3.Schema{}, errors.New("merging two schemas with additional properties, this is unhandled")
|
||||
} else {
|
||||
result.AdditionalProperties.Schema = s1.AdditionalProperties.Schema
|
||||
}
|
||||
} else {
|
||||
if s2.AdditionalProperties.Schema != nil {
|
||||
result.AdditionalProperties.Schema = s2.AdditionalProperties.Schema
|
||||
} else {
|
||||
if s1.AdditionalProperties.Has != nil || s2.AdditionalProperties.Has != nil {
|
||||
result.WithAnyAdditionalProperties()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allow discriminators for allOf merges, but disallow for one/anyOfs.
|
||||
if !allOf && (s1.Discriminator != nil || s2.Discriminator != nil) {
|
||||
return openapi3.Schema{}, errors.New("merging two schemas with discriminators is not supported")
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func equalTypes(t1 *openapi3.Types, t2 *openapi3.Types) bool {
|
||||
s1 := t1.Slice()
|
||||
s2 := t2.Slice()
|
||||
|
||||
if len(s1) != len(s2) {
|
||||
return false
|
||||
}
|
||||
|
||||
// NOTE that ideally we'd use `slices.Equal` but as we're currently supporting Go 1.20+, we can't use it (yet https://github.com/oapi-codegen/oapi-codegen/issues/1634)
|
||||
for i := range s1 {
|
||||
if s1[i] != s2[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
111
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/merge_schemas_v1.go
generated
vendored
Normal file
111
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/merge_schemas_v1.go
generated
vendored
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
package codegen
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
)
|
||||
|
||||
func mergeSchemasV1(allOf []*openapi3.SchemaRef, path []string) (Schema, error) {
|
||||
var outSchema Schema
|
||||
for _, schemaOrRef := range allOf {
|
||||
ref := schemaOrRef.Ref
|
||||
|
||||
var refType string
|
||||
var err error
|
||||
if IsGoTypeReference(ref) {
|
||||
refType, err = RefPathToGoType(ref)
|
||||
if err != nil {
|
||||
return Schema{}, fmt.Errorf("error converting reference path to a go type: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
schema, err := GenerateGoSchema(schemaOrRef, path)
|
||||
if err != nil {
|
||||
return Schema{}, fmt.Errorf("error generating Go schema in allOf: %w", err)
|
||||
}
|
||||
schema.RefType = refType
|
||||
|
||||
for _, p := range schema.Properties {
|
||||
err = outSchema.AddProperty(p)
|
||||
if err != nil {
|
||||
return Schema{}, fmt.Errorf("error merging properties: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if schema.HasAdditionalProperties {
|
||||
if outSchema.HasAdditionalProperties {
|
||||
// Both this schema, and the aggregate schema have additional
|
||||
// properties, they must match.
|
||||
if schema.AdditionalPropertiesType.TypeDecl() != outSchema.AdditionalPropertiesType.TypeDecl() {
|
||||
return Schema{}, errors.New("additional properties in allOf have incompatible types")
|
||||
}
|
||||
} else {
|
||||
// We're switching from having no additional properties to having
|
||||
// them
|
||||
outSchema.HasAdditionalProperties = true
|
||||
outSchema.AdditionalPropertiesType = schema.AdditionalPropertiesType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now, we generate the struct which merges together all the fields.
|
||||
var err error
|
||||
outSchema.GoType, err = GenStructFromAllOf(allOf, path)
|
||||
if err != nil {
|
||||
return Schema{}, fmt.Errorf("unable to generate aggregate type for AllOf: %w", err)
|
||||
}
|
||||
return outSchema, nil
|
||||
}
|
||||
|
||||
// GenStructFromAllOf generates an object that is the union of the objects in the
|
||||
// input array. In the case of Ref objects, we use an embedded struct, otherwise,
|
||||
// we inline the fields.
|
||||
func GenStructFromAllOf(allOf []*openapi3.SchemaRef, path []string) (string, error) {
|
||||
// Start out with struct {
|
||||
objectParts := []string{"struct {"}
|
||||
for _, schemaOrRef := range allOf {
|
||||
ref := schemaOrRef.Ref
|
||||
if IsGoTypeReference(ref) {
|
||||
// We have a referenced type, we will generate an inlined struct
|
||||
// member.
|
||||
// struct {
|
||||
// InlinedMember
|
||||
// ...
|
||||
// }
|
||||
goType, err := RefPathToGoType(ref)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
objectParts = append(objectParts,
|
||||
fmt.Sprintf(" // Embedded struct due to allOf(%s)", ref))
|
||||
objectParts = append(objectParts,
|
||||
fmt.Sprintf(" %s `yaml:\",inline\"`", goType))
|
||||
} else {
|
||||
// Inline all the fields from the schema into the output struct,
|
||||
// just like in the simple case of generating an object.
|
||||
goSchema, err := GenerateGoSchema(schemaOrRef, path)
|
||||
if err != nil {
|
||||
return "", 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, "}")
|
||||
return strings.Join(objectParts, "\n"), nil
|
||||
}
|
||||
1099
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/operations.go
generated
vendored
Normal file
1099
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/operations.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
489
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/prune.go
generated
vendored
Normal file
489
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/prune.go
generated
vendored
Normal file
|
|
@ -0,0 +1,489 @@
|
|||
package codegen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
)
|
||||
|
||||
func stringInSlice(a string, list []string) bool {
|
||||
for _, b := range list {
|
||||
if b == a {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type RefWrapper struct {
|
||||
Ref string
|
||||
HasValue bool
|
||||
SourceRef interface{}
|
||||
}
|
||||
|
||||
func walkSwagger(swagger *openapi3.T, doFn func(RefWrapper) (bool, error)) error {
|
||||
if swagger == nil || swagger.Paths == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, p := range swagger.Paths.Map() {
|
||||
for _, param := range p.Parameters {
|
||||
_ = walkParameterRef(param, doFn)
|
||||
}
|
||||
for _, op := range p.Operations() {
|
||||
_ = walkOperation(op, doFn)
|
||||
}
|
||||
}
|
||||
|
||||
_ = walkComponents(swagger.Components, doFn)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkOperation(op *openapi3.Operation, doFn func(RefWrapper) (bool, error)) error {
|
||||
// Not a valid ref, ignore it and continue
|
||||
if op == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, param := range op.Parameters {
|
||||
_ = walkParameterRef(param, doFn)
|
||||
}
|
||||
|
||||
_ = walkRequestBodyRef(op.RequestBody, doFn)
|
||||
|
||||
if op.Responses != nil {
|
||||
for _, response := range op.Responses.Map() {
|
||||
_ = walkResponseRef(response, doFn)
|
||||
}
|
||||
}
|
||||
|
||||
for _, callback := range op.Callbacks {
|
||||
_ = walkCallbackRef(callback, doFn)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkComponents(components *openapi3.Components, doFn func(RefWrapper) (bool, error)) error {
|
||||
// Not a valid ref, ignore it and continue
|
||||
if components == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, schema := range components.Schemas {
|
||||
_ = walkSchemaRef(schema, doFn)
|
||||
}
|
||||
|
||||
for _, param := range components.Parameters {
|
||||
_ = walkParameterRef(param, doFn)
|
||||
}
|
||||
|
||||
for _, header := range components.Headers {
|
||||
_ = walkHeaderRef(header, doFn)
|
||||
}
|
||||
|
||||
for _, requestBody := range components.RequestBodies {
|
||||
_ = walkRequestBodyRef(requestBody, doFn)
|
||||
}
|
||||
|
||||
for _, response := range components.Responses {
|
||||
_ = walkResponseRef(response, doFn)
|
||||
}
|
||||
|
||||
for _, securityScheme := range components.SecuritySchemes {
|
||||
_ = walkSecuritySchemeRef(securityScheme, doFn)
|
||||
}
|
||||
|
||||
for _, example := range components.Examples {
|
||||
_ = walkExampleRef(example, doFn)
|
||||
}
|
||||
|
||||
for _, link := range components.Links {
|
||||
_ = walkLinkRef(link, doFn)
|
||||
}
|
||||
|
||||
for _, callback := range components.Callbacks {
|
||||
_ = walkCallbackRef(callback, doFn)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkSchemaRef(ref *openapi3.SchemaRef, doFn func(RefWrapper) (bool, error)) error {
|
||||
// Not a valid ref, ignore it and continue
|
||||
if ref == nil {
|
||||
return nil
|
||||
}
|
||||
refWrapper := RefWrapper{Ref: ref.Ref, HasValue: ref.Value != nil, SourceRef: ref}
|
||||
shouldContinue, err := doFn(refWrapper)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !shouldContinue {
|
||||
return nil
|
||||
}
|
||||
if ref.Value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, ref := range ref.Value.OneOf {
|
||||
_ = walkSchemaRef(ref, doFn)
|
||||
}
|
||||
|
||||
for _, ref := range ref.Value.AnyOf {
|
||||
_ = walkSchemaRef(ref, doFn)
|
||||
}
|
||||
|
||||
for _, ref := range ref.Value.AllOf {
|
||||
_ = walkSchemaRef(ref, doFn)
|
||||
}
|
||||
|
||||
_ = walkSchemaRef(ref.Value.Not, doFn)
|
||||
_ = walkSchemaRef(ref.Value.Items, doFn)
|
||||
|
||||
for _, ref := range ref.Value.Properties {
|
||||
_ = walkSchemaRef(ref, doFn)
|
||||
}
|
||||
|
||||
_ = walkSchemaRef(ref.Value.AdditionalProperties.Schema, doFn)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkParameterRef(ref *openapi3.ParameterRef, doFn func(RefWrapper) (bool, error)) error {
|
||||
// Not a valid ref, ignore it and continue
|
||||
if ref == nil {
|
||||
return nil
|
||||
}
|
||||
refWrapper := RefWrapper{Ref: ref.Ref, HasValue: ref.Value != nil, SourceRef: ref}
|
||||
shouldContinue, err := doFn(refWrapper)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !shouldContinue {
|
||||
return nil
|
||||
}
|
||||
if ref.Value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
_ = walkSchemaRef(ref.Value.Schema, doFn)
|
||||
|
||||
for _, example := range ref.Value.Examples {
|
||||
_ = walkExampleRef(example, doFn)
|
||||
}
|
||||
|
||||
for _, mediaType := range ref.Value.Content {
|
||||
if mediaType == nil {
|
||||
continue
|
||||
}
|
||||
_ = walkSchemaRef(mediaType.Schema, doFn)
|
||||
|
||||
for _, example := range mediaType.Examples {
|
||||
_ = walkExampleRef(example, doFn)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkRequestBodyRef(ref *openapi3.RequestBodyRef, doFn func(RefWrapper) (bool, error)) error {
|
||||
// Not a valid ref, ignore it and continue
|
||||
if ref == nil {
|
||||
return nil
|
||||
}
|
||||
refWrapper := RefWrapper{Ref: ref.Ref, HasValue: ref.Value != nil, SourceRef: ref}
|
||||
shouldContinue, err := doFn(refWrapper)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !shouldContinue {
|
||||
return nil
|
||||
}
|
||||
if ref.Value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, mediaType := range ref.Value.Content {
|
||||
if mediaType == nil {
|
||||
continue
|
||||
}
|
||||
_ = walkSchemaRef(mediaType.Schema, doFn)
|
||||
|
||||
for _, example := range mediaType.Examples {
|
||||
_ = walkExampleRef(example, doFn)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkResponseRef(ref *openapi3.ResponseRef, doFn func(RefWrapper) (bool, error)) error {
|
||||
// Not a valid ref, ignore it and continue
|
||||
if ref == nil {
|
||||
return nil
|
||||
}
|
||||
refWrapper := RefWrapper{Ref: ref.Ref, HasValue: ref.Value != nil, SourceRef: ref}
|
||||
shouldContinue, err := doFn(refWrapper)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !shouldContinue {
|
||||
return nil
|
||||
}
|
||||
if ref.Value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, header := range ref.Value.Headers {
|
||||
_ = walkHeaderRef(header, doFn)
|
||||
}
|
||||
|
||||
for _, mediaType := range ref.Value.Content {
|
||||
if mediaType == nil {
|
||||
continue
|
||||
}
|
||||
_ = walkSchemaRef(mediaType.Schema, doFn)
|
||||
|
||||
for _, example := range mediaType.Examples {
|
||||
_ = walkExampleRef(example, doFn)
|
||||
}
|
||||
}
|
||||
|
||||
for _, link := range ref.Value.Links {
|
||||
_ = walkLinkRef(link, doFn)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkCallbackRef(ref *openapi3.CallbackRef, doFn func(RefWrapper) (bool, error)) error {
|
||||
// Not a valid ref, ignore it and continue
|
||||
if ref == nil {
|
||||
return nil
|
||||
}
|
||||
refWrapper := RefWrapper{Ref: ref.Ref, HasValue: ref.Value != nil, SourceRef: ref}
|
||||
shouldContinue, err := doFn(refWrapper)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !shouldContinue {
|
||||
return nil
|
||||
}
|
||||
if ref.Value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, pathItem := range ref.Value.Map() {
|
||||
for _, parameter := range pathItem.Parameters {
|
||||
_ = walkParameterRef(parameter, doFn)
|
||||
}
|
||||
_ = walkOperation(pathItem.Connect, doFn)
|
||||
_ = walkOperation(pathItem.Delete, doFn)
|
||||
_ = walkOperation(pathItem.Get, doFn)
|
||||
_ = walkOperation(pathItem.Head, doFn)
|
||||
_ = walkOperation(pathItem.Options, doFn)
|
||||
_ = walkOperation(pathItem.Patch, doFn)
|
||||
_ = walkOperation(pathItem.Post, doFn)
|
||||
_ = walkOperation(pathItem.Put, doFn)
|
||||
_ = walkOperation(pathItem.Trace, doFn)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkHeaderRef(ref *openapi3.HeaderRef, doFn func(RefWrapper) (bool, error)) error {
|
||||
// Not a valid ref, ignore it and continue
|
||||
if ref == nil {
|
||||
return nil
|
||||
}
|
||||
refWrapper := RefWrapper{Ref: ref.Ref, HasValue: ref.Value != nil, SourceRef: ref}
|
||||
shouldContinue, err := doFn(refWrapper)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !shouldContinue {
|
||||
return nil
|
||||
}
|
||||
if ref.Value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
_ = walkSchemaRef(ref.Value.Schema, doFn)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkSecuritySchemeRef(ref *openapi3.SecuritySchemeRef, doFn func(RefWrapper) (bool, error)) error {
|
||||
// Not a valid ref, ignore it and continue
|
||||
if ref == nil {
|
||||
return nil
|
||||
}
|
||||
refWrapper := RefWrapper{Ref: ref.Ref, HasValue: ref.Value != nil, SourceRef: ref}
|
||||
shouldContinue, err := doFn(refWrapper)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !shouldContinue {
|
||||
return nil
|
||||
}
|
||||
if ref.Value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NOTE: `SecuritySchemeRef`s don't contain any children that can contain refs
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkLinkRef(ref *openapi3.LinkRef, doFn func(RefWrapper) (bool, error)) error {
|
||||
// Not a valid ref, ignore it and continue
|
||||
if ref == nil {
|
||||
return nil
|
||||
}
|
||||
refWrapper := RefWrapper{Ref: ref.Ref, HasValue: ref.Value != nil, SourceRef: ref}
|
||||
shouldContinue, err := doFn(refWrapper)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !shouldContinue {
|
||||
return nil
|
||||
}
|
||||
if ref.Value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkExampleRef(ref *openapi3.ExampleRef, doFn func(RefWrapper) (bool, error)) error {
|
||||
// Not a valid ref, ignore it and continue
|
||||
if ref == nil {
|
||||
return nil
|
||||
}
|
||||
refWrapper := RefWrapper{Ref: ref.Ref, HasValue: ref.Value != nil, SourceRef: ref}
|
||||
shouldContinue, err := doFn(refWrapper)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !shouldContinue {
|
||||
return nil
|
||||
}
|
||||
if ref.Value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NOTE: `ExampleRef`s don't contain any children that can contain refs
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func findComponentRefs(swagger *openapi3.T) []string {
|
||||
refs := []string{}
|
||||
|
||||
_ = walkSwagger(swagger, func(ref RefWrapper) (bool, error) {
|
||||
if ref.Ref != "" {
|
||||
refs = append(refs, ref.Ref)
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
|
||||
return refs
|
||||
}
|
||||
|
||||
func removeOrphanedComponents(swagger *openapi3.T, refs []string) int {
|
||||
if swagger.Components == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
countRemoved := 0
|
||||
|
||||
for key := range swagger.Components.Schemas {
|
||||
ref := fmt.Sprintf("#/components/schemas/%s", key)
|
||||
if !stringInSlice(ref, refs) {
|
||||
countRemoved++
|
||||
delete(swagger.Components.Schemas, key)
|
||||
}
|
||||
}
|
||||
|
||||
for key := range swagger.Components.Parameters {
|
||||
ref := fmt.Sprintf("#/components/parameters/%s", key)
|
||||
if !stringInSlice(ref, refs) {
|
||||
countRemoved++
|
||||
delete(swagger.Components.Parameters, key)
|
||||
}
|
||||
}
|
||||
|
||||
// securitySchemes are an exception. definitions in securitySchemes
|
||||
// are referenced directly by name. and not by $ref
|
||||
|
||||
// for key, _ := range swagger.Components.SecuritySchemes {
|
||||
// ref := fmt.Sprintf("#/components/securitySchemes/%s", key)
|
||||
// if !stringInSlice(ref, refs) {
|
||||
// countRemoved++
|
||||
// delete(swagger.Components.SecuritySchemes, key)
|
||||
// }
|
||||
// }
|
||||
|
||||
for key := range swagger.Components.RequestBodies {
|
||||
ref := fmt.Sprintf("#/components/requestBodies/%s", key)
|
||||
if !stringInSlice(ref, refs) {
|
||||
countRemoved++
|
||||
delete(swagger.Components.RequestBodies, key)
|
||||
}
|
||||
}
|
||||
|
||||
for key := range swagger.Components.Responses {
|
||||
ref := fmt.Sprintf("#/components/responses/%s", key)
|
||||
if !stringInSlice(ref, refs) {
|
||||
countRemoved++
|
||||
delete(swagger.Components.Responses, key)
|
||||
}
|
||||
}
|
||||
|
||||
for key := range swagger.Components.Headers {
|
||||
ref := fmt.Sprintf("#/components/headers/%s", key)
|
||||
if !stringInSlice(ref, refs) {
|
||||
countRemoved++
|
||||
delete(swagger.Components.Headers, key)
|
||||
}
|
||||
}
|
||||
|
||||
for key := range swagger.Components.Examples {
|
||||
ref := fmt.Sprintf("#/components/examples/%s", key)
|
||||
if !stringInSlice(ref, refs) {
|
||||
countRemoved++
|
||||
delete(swagger.Components.Examples, key)
|
||||
}
|
||||
}
|
||||
|
||||
for key := range swagger.Components.Links {
|
||||
ref := fmt.Sprintf("#/components/links/%s", key)
|
||||
if !stringInSlice(ref, refs) {
|
||||
countRemoved++
|
||||
delete(swagger.Components.Links, key)
|
||||
}
|
||||
}
|
||||
|
||||
for key := range swagger.Components.Callbacks {
|
||||
ref := fmt.Sprintf("#/components/callbacks/%s", key)
|
||||
if !stringInSlice(ref, refs) {
|
||||
countRemoved++
|
||||
delete(swagger.Components.Callbacks, key)
|
||||
}
|
||||
}
|
||||
|
||||
return countRemoved
|
||||
}
|
||||
|
||||
func pruneUnusedComponents(swagger *openapi3.T) {
|
||||
for {
|
||||
refs := findComponentRefs(swagger)
|
||||
countRemoved := removeOrphanedComponents(swagger, refs)
|
||||
if countRemoved < 1 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
891
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/schema.go
generated
vendored
Normal file
891
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/schema.go
generated
vendored
Normal file
|
|
@ -0,0 +1,891 @@
|
|||
package codegen
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
)
|
||||
|
||||
// Schema describes an OpenAPI schema, with lots of helper fields to use in the
|
||||
// templating engine.
|
||||
type Schema struct {
|
||||
GoType string // The Go type needed to represent the schema
|
||||
RefType string // If the type has a type name, this is set
|
||||
|
||||
ArrayType *Schema // The schema of array element
|
||||
|
||||
EnumValues map[string]string // Enum values
|
||||
|
||||
Properties []Property // For an object, the fields with names
|
||||
HasAdditionalProperties bool // Whether we support additional properties
|
||||
AdditionalPropertiesType *Schema // And if we do, their type
|
||||
AdditionalTypes []TypeDefinition // We may need to generate auxiliary helper types, stored here
|
||||
|
||||
SkipOptionalPointer bool // Some types don't need a * in front when they're optional
|
||||
|
||||
Description string // The description of the element
|
||||
|
||||
UnionElements []UnionElement // Possible elements of oneOf/anyOf union
|
||||
Discriminator *Discriminator // Describes which value is stored in a union
|
||||
|
||||
// If this is set, the schema will declare a type via alias, eg,
|
||||
// `type Foo = bool`. If this is not set, we will define this type via
|
||||
// type definition `type Foo bool`
|
||||
//
|
||||
// Can be overriden by the OutputOptions#DisableTypeAliasesForType field
|
||||
DefineViaAlias bool
|
||||
|
||||
// The original OpenAPIv3 Schema.
|
||||
OAPISchema *openapi3.Schema
|
||||
}
|
||||
|
||||
func (s Schema) IsRef() bool {
|
||||
return s.RefType != ""
|
||||
}
|
||||
|
||||
func (s Schema) IsExternalRef() bool {
|
||||
if !s.IsRef() {
|
||||
return false
|
||||
}
|
||||
return strings.Contains(s.RefType, ".")
|
||||
}
|
||||
|
||||
func (s Schema) TypeDecl() string {
|
||||
if s.IsRef() {
|
||||
return s.RefType
|
||||
}
|
||||
return s.GoType
|
||||
}
|
||||
|
||||
// AddProperty adds a new property to the current Schema, and returns an error
|
||||
// if it collides. Two identical fields will not collide, but two properties by
|
||||
// the same name, but different definition, will collide. It's safe to merge the
|
||||
// fields of two schemas with overlapping properties if those properties are
|
||||
// identical.
|
||||
func (s *Schema) AddProperty(p Property) error {
|
||||
// Scan all existing properties for a conflict
|
||||
for _, e := range s.Properties {
|
||||
if e.JsonFieldName == p.JsonFieldName && !PropertiesEqual(e, p) {
|
||||
return fmt.Errorf("property '%s' already exists with a different type", e.JsonFieldName)
|
||||
}
|
||||
}
|
||||
s.Properties = append(s.Properties, p)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s Schema) GetAdditionalTypeDefs() []TypeDefinition {
|
||||
return s.AdditionalTypes
|
||||
}
|
||||
|
||||
type Property struct {
|
||||
Description string
|
||||
JsonFieldName string
|
||||
Schema Schema
|
||||
Required bool
|
||||
Nullable bool
|
||||
ReadOnly bool
|
||||
WriteOnly bool
|
||||
NeedsFormTag bool
|
||||
Extensions map[string]interface{}
|
||||
Deprecated bool
|
||||
}
|
||||
|
||||
func (p Property) GoFieldName() string {
|
||||
goFieldName := p.JsonFieldName
|
||||
if extension, ok := p.Extensions[extGoName]; ok {
|
||||
if extGoFieldName, err := extParseGoFieldName(extension); err == nil {
|
||||
goFieldName = extGoFieldName
|
||||
}
|
||||
}
|
||||
|
||||
if globalState.options.Compatibility.AllowUnexportedStructFieldNames {
|
||||
if extension, ok := p.Extensions[extOapiCodegenOnlyHonourGoName]; ok {
|
||||
if extOapiCodegenOnlyHonourGoName, err := extParseOapiCodegenOnlyHonourGoName(extension); err == nil {
|
||||
if extOapiCodegenOnlyHonourGoName {
|
||||
return goFieldName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SchemaNameToTypeName(goFieldName)
|
||||
}
|
||||
|
||||
func (p Property) GoTypeDef() string {
|
||||
typeDef := p.Schema.TypeDecl()
|
||||
if globalState.options.OutputOptions.NullableType && p.Nullable {
|
||||
return "nullable.Nullable[" + typeDef + "]"
|
||||
}
|
||||
if !p.Schema.SkipOptionalPointer &&
|
||||
(!p.Required || p.Nullable ||
|
||||
(p.ReadOnly && (!p.Required || !globalState.options.Compatibility.DisableRequiredReadOnlyAsPointer)) ||
|
||||
p.WriteOnly) {
|
||||
|
||||
typeDef = "*" + typeDef
|
||||
}
|
||||
return typeDef
|
||||
}
|
||||
|
||||
// EnumDefinition holds type information for enum
|
||||
type EnumDefinition struct {
|
||||
// Schema is the scheme of a type which has a list of enum values, eg, the
|
||||
// "container" of the enum.
|
||||
Schema Schema
|
||||
// TypeName is the name of the enum's type, usually aliased from something.
|
||||
TypeName string
|
||||
// ValueWrapper wraps the value. It's used to conditionally apply quotes
|
||||
// around strings.
|
||||
ValueWrapper string
|
||||
// PrefixTypeName determines if the enum value is prefixed with its TypeName.
|
||||
// This is set to true when this enum conflicts with another in terms of
|
||||
// TypeNames or when explicitly requested via the
|
||||
// `compatibility.always-prefix-enum-values` option.
|
||||
PrefixTypeName bool
|
||||
}
|
||||
|
||||
// GetValues generates enum names in a way to minimize global conflicts
|
||||
func (e *EnumDefinition) GetValues() map[string]string {
|
||||
// in case there are no conflicts, it's safe to use the values as-is
|
||||
if !e.PrefixTypeName {
|
||||
return e.Schema.EnumValues
|
||||
}
|
||||
// If we do have conflicts, we will prefix the enum's typename to the values.
|
||||
newValues := make(map[string]string, len(e.Schema.EnumValues))
|
||||
for k, v := range e.Schema.EnumValues {
|
||||
newName := e.TypeName + UppercaseFirstCharacter(k)
|
||||
newValues[newName] = v
|
||||
}
|
||||
return newValues
|
||||
}
|
||||
|
||||
type Constants struct {
|
||||
// SecuritySchemeProviderNames holds all provider names for security schemes.
|
||||
SecuritySchemeProviderNames []string
|
||||
// EnumDefinitions holds type and value information for all enums
|
||||
EnumDefinitions []EnumDefinition
|
||||
}
|
||||
|
||||
// TypeDefinition describes a Go type definition in generated code.
|
||||
//
|
||||
// Let's use this example schema:
|
||||
// components:
|
||||
//
|
||||
// schemas:
|
||||
// Person:
|
||||
// type: object
|
||||
// properties:
|
||||
// name:
|
||||
// type: string
|
||||
type TypeDefinition struct {
|
||||
// The name of the type, eg, type <...> Person
|
||||
TypeName string
|
||||
|
||||
// The name of the corresponding JSON description, as it will sometimes
|
||||
// differ due to invalid characters.
|
||||
JsonName string
|
||||
|
||||
// This is the Schema wrapper is used to populate the type description
|
||||
Schema Schema
|
||||
}
|
||||
|
||||
// ResponseTypeDefinition is an extension of TypeDefinition, specifically for
|
||||
// response unmarshaling in ClientWithResponses.
|
||||
type ResponseTypeDefinition struct {
|
||||
TypeDefinition
|
||||
// The content type name where this is used, eg, application/json
|
||||
ContentTypeName string
|
||||
|
||||
// The type name of a response model.
|
||||
ResponseName string
|
||||
|
||||
AdditionalTypeDefinitions []TypeDefinition
|
||||
}
|
||||
|
||||
func (t *TypeDefinition) IsAlias() bool {
|
||||
return !globalState.options.Compatibility.OldAliasing && t.Schema.DefineViaAlias
|
||||
}
|
||||
|
||||
type Discriminator struct {
|
||||
// maps discriminator value to go type
|
||||
Mapping map[string]string
|
||||
|
||||
// JSON property name that holds the discriminator
|
||||
Property string
|
||||
}
|
||||
|
||||
func (d *Discriminator) JSONTag() string {
|
||||
return fmt.Sprintf("`json:\"%s\"`", d.Property)
|
||||
}
|
||||
|
||||
func (d *Discriminator) PropertyName() string {
|
||||
return SchemaNameToTypeName(d.Property)
|
||||
}
|
||||
|
||||
// UnionElement describe union element, based on prefix externalRef\d+ and real ref name from external schema.
|
||||
type UnionElement string
|
||||
|
||||
// String returns externalRef\d+ and real ref name from external schema, like externalRef0.SomeType.
|
||||
func (u UnionElement) String() string {
|
||||
return string(u)
|
||||
}
|
||||
|
||||
// Method generate union method name for template functions `As/From/Merge`.
|
||||
func (u UnionElement) Method() string {
|
||||
var method string
|
||||
for _, part := range strings.Split(string(u), `.`) {
|
||||
method += UppercaseFirstCharacter(part)
|
||||
}
|
||||
return method
|
||||
}
|
||||
|
||||
func PropertiesEqual(a, b Property) bool {
|
||||
return a.JsonFieldName == b.JsonFieldName && a.Schema.TypeDecl() == b.Schema.TypeDecl() && a.Required == b.Required
|
||||
}
|
||||
|
||||
func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) {
|
||||
// Add a fallback value in case the sref is nil.
|
||||
// i.e. the parent schema defines a type:array, but the array has
|
||||
// no items defined. Therefore, we have at least valid Go-Code.
|
||||
if sref == nil {
|
||||
return Schema{GoType: "interface{}"}, nil
|
||||
}
|
||||
|
||||
schema := sref.Value
|
||||
|
||||
// If Ref is set on the SchemaRef, it means that this type is actually a reference to
|
||||
// another type. We're not de-referencing, so simply use the referenced type.
|
||||
if IsGoTypeReference(sref.Ref) {
|
||||
// Convert the reference path to Go type
|
||||
refType, err := RefPathToGoType(sref.Ref)
|
||||
if err != nil {
|
||||
return Schema{}, fmt.Errorf("error turning reference (%s) into a Go type: %s",
|
||||
sref.Ref, err)
|
||||
}
|
||||
return Schema{
|
||||
GoType: refType,
|
||||
Description: schema.Description,
|
||||
DefineViaAlias: true,
|
||||
OAPISchema: schema,
|
||||
}, nil
|
||||
}
|
||||
|
||||
outSchema := Schema{
|
||||
Description: schema.Description,
|
||||
OAPISchema: schema,
|
||||
}
|
||||
|
||||
// AllOf is interesting, and useful. It's the union of a number of other
|
||||
// schemas. A common usage is to create a union of an object with an ID,
|
||||
// so that in a RESTful paradigm, the Create operation can return
|
||||
// (object, id), so that other operations can refer to (id)
|
||||
if schema.AllOf != nil {
|
||||
mergedSchema, err := MergeSchemas(schema.AllOf, path)
|
||||
if err != nil {
|
||||
return Schema{}, fmt.Errorf("error merging schemas: %w", err)
|
||||
}
|
||||
mergedSchema.OAPISchema = schema
|
||||
return mergedSchema, nil
|
||||
}
|
||||
|
||||
// Check x-go-type, which will completely override the definition of this
|
||||
// schema with the provided type.
|
||||
if extension, ok := schema.Extensions[extPropGoType]; ok {
|
||||
typeName, err := extTypeName(extension)
|
||||
if err != nil {
|
||||
return outSchema, fmt.Errorf("invalid value for %q: %w", extPropGoType, err)
|
||||
}
|
||||
outSchema.GoType = typeName
|
||||
outSchema.DefineViaAlias = true
|
||||
|
||||
return outSchema, nil
|
||||
}
|
||||
|
||||
// Check x-go-type-skip-optional-pointer, which will override if the type
|
||||
// should be a pointer or not when the field is optional.
|
||||
if extension, ok := schema.Extensions[extPropGoTypeSkipOptionalPointer]; ok {
|
||||
skipOptionalPointer, err := extParsePropGoTypeSkipOptionalPointer(extension)
|
||||
if err != nil {
|
||||
return outSchema, fmt.Errorf("invalid value for %q: %w", extPropGoTypeSkipOptionalPointer, err)
|
||||
}
|
||||
outSchema.SkipOptionalPointer = skipOptionalPointer
|
||||
}
|
||||
|
||||
// Schema type and format, eg. string / binary
|
||||
t := schema.Type
|
||||
// Handle objects and empty schemas first as a special case
|
||||
if t.Slice() == nil || t.Is("object") {
|
||||
var outType string
|
||||
|
||||
if len(schema.Properties) == 0 && !SchemaHasAdditionalProperties(schema) && schema.AnyOf == nil && schema.OneOf == nil {
|
||||
// If the object has no properties or additional properties, we
|
||||
// have some special cases for its type.
|
||||
if t.Is("object") {
|
||||
// We have an object with no properties. This is a generic object
|
||||
// expressed as a map.
|
||||
outType = "map[string]interface{}"
|
||||
} else { // t == ""
|
||||
// If we don't even have the object designator, we're a completely
|
||||
// generic type.
|
||||
outType = "interface{}"
|
||||
}
|
||||
outSchema.GoType = outType
|
||||
outSchema.DefineViaAlias = true
|
||||
} else {
|
||||
// When we define an object, we want it to be a type definition,
|
||||
// not a type alias, eg, "type Foo struct {...}"
|
||||
outSchema.DefineViaAlias = false
|
||||
|
||||
// If the schema has additional properties, we need to special case
|
||||
// a lot of behaviors.
|
||||
outSchema.HasAdditionalProperties = SchemaHasAdditionalProperties(schema)
|
||||
|
||||
// Until we have a concrete additional properties type, we default to
|
||||
// any schema.
|
||||
outSchema.AdditionalPropertiesType = &Schema{
|
||||
GoType: "interface{}",
|
||||
}
|
||||
|
||||
// If additional properties are defined, we will override the default
|
||||
// above with the specific definition.
|
||||
if schema.AdditionalProperties.Schema != nil {
|
||||
additionalSchema, err := GenerateGoSchema(schema.AdditionalProperties.Schema, path)
|
||||
if err != nil {
|
||||
return Schema{}, fmt.Errorf("error generating type for additional properties: %w", err)
|
||||
}
|
||||
if additionalSchema.HasAdditionalProperties || len(additionalSchema.UnionElements) != 0 {
|
||||
// If we have fields present which have additional properties or union values,
|
||||
// but are not a pre-defined type, we need to define a type
|
||||
// for them, which will be based on the field names we followed
|
||||
// to get to the type.
|
||||
typeName := PathToTypeName(append(path, "AdditionalProperties"))
|
||||
|
||||
typeDef := TypeDefinition{
|
||||
TypeName: typeName,
|
||||
JsonName: strings.Join(append(path, "AdditionalProperties"), "."),
|
||||
Schema: additionalSchema,
|
||||
}
|
||||
additionalSchema.RefType = typeName
|
||||
additionalSchema.AdditionalTypes = append(additionalSchema.AdditionalTypes, typeDef)
|
||||
}
|
||||
outSchema.AdditionalPropertiesType = &additionalSchema
|
||||
outSchema.AdditionalTypes = append(outSchema.AdditionalTypes, additionalSchema.AdditionalTypes...)
|
||||
}
|
||||
|
||||
// If the schema has no properties, and only additional properties, we will
|
||||
// early-out here and generate a map[string]<schema> instead of an object
|
||||
// that contains this map. We skip over anyOf/oneOf here because they can
|
||||
// introduce properties. allOf was handled above.
|
||||
if !globalState.options.Compatibility.DisableFlattenAdditionalProperties &&
|
||||
len(schema.Properties) == 0 && schema.AnyOf == nil && schema.OneOf == nil {
|
||||
// We have a dictionary here. Returns the goType to be just a map from
|
||||
// string to the property type. HasAdditionalProperties=false means
|
||||
// that we won't generate custom json.Marshaler and json.Unmarshaler functions,
|
||||
// since we don't need them for a simple map.
|
||||
outSchema.HasAdditionalProperties = false
|
||||
outSchema.GoType = fmt.Sprintf("map[string]%s", additionalPropertiesType(outSchema))
|
||||
return outSchema, nil
|
||||
}
|
||||
|
||||
// We've got an object with some properties.
|
||||
for _, pName := range SortedSchemaKeys(schema.Properties) {
|
||||
p := schema.Properties[pName]
|
||||
propertyPath := append(path, pName)
|
||||
pSchema, err := GenerateGoSchema(p, propertyPath)
|
||||
if err != nil {
|
||||
return Schema{}, fmt.Errorf("error generating Go schema for property '%s': %w", pName, err)
|
||||
}
|
||||
|
||||
required := StringInArray(pName, schema.Required)
|
||||
|
||||
if (pSchema.HasAdditionalProperties || len(pSchema.UnionElements) != 0) && pSchema.RefType == "" {
|
||||
// If we have fields present which have additional properties or union values,
|
||||
// but are not a pre-defined type, we need to define a type
|
||||
// for them, which will be based on the field names we followed
|
||||
// to get to the type.
|
||||
typeName := PathToTypeName(propertyPath)
|
||||
|
||||
typeDef := TypeDefinition{
|
||||
TypeName: typeName,
|
||||
JsonName: strings.Join(propertyPath, "."),
|
||||
Schema: pSchema,
|
||||
}
|
||||
pSchema.AdditionalTypes = append(pSchema.AdditionalTypes, typeDef)
|
||||
|
||||
pSchema.RefType = typeName
|
||||
}
|
||||
description := ""
|
||||
if p.Value != nil {
|
||||
description = p.Value.Description
|
||||
}
|
||||
prop := Property{
|
||||
JsonFieldName: pName,
|
||||
Schema: pSchema,
|
||||
Required: required,
|
||||
Description: description,
|
||||
Nullable: p.Value.Nullable,
|
||||
ReadOnly: p.Value.ReadOnly,
|
||||
WriteOnly: p.Value.WriteOnly,
|
||||
Extensions: p.Value.Extensions,
|
||||
Deprecated: p.Value.Deprecated,
|
||||
}
|
||||
outSchema.Properties = append(outSchema.Properties, prop)
|
||||
if len(pSchema.AdditionalTypes) > 0 {
|
||||
outSchema.AdditionalTypes = append(outSchema.AdditionalTypes, pSchema.AdditionalTypes...)
|
||||
}
|
||||
}
|
||||
|
||||
if schema.AnyOf != nil {
|
||||
if err := generateUnion(&outSchema, schema.AnyOf, schema.Discriminator, path); err != nil {
|
||||
return Schema{}, fmt.Errorf("error generating type for anyOf: %w", err)
|
||||
}
|
||||
}
|
||||
if schema.OneOf != nil {
|
||||
if err := generateUnion(&outSchema, schema.OneOf, schema.Discriminator, path); err != nil {
|
||||
return Schema{}, fmt.Errorf("error generating type for oneOf: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
outSchema.GoType = GenStructFromSchema(outSchema)
|
||||
}
|
||||
|
||||
// Check for x-go-type-name. It behaves much like x-go-type, however, it will
|
||||
// create a type definition for the named type, and use the named type in place
|
||||
// of this schema.
|
||||
if extension, ok := schema.Extensions[extGoTypeName]; ok {
|
||||
typeName, err := extTypeName(extension)
|
||||
if err != nil {
|
||||
return outSchema, fmt.Errorf("invalid value for %q: %w", extGoTypeName, err)
|
||||
}
|
||||
|
||||
newTypeDef := TypeDefinition{
|
||||
TypeName: typeName,
|
||||
Schema: outSchema,
|
||||
}
|
||||
outSchema = Schema{
|
||||
Description: newTypeDef.Schema.Description,
|
||||
GoType: typeName,
|
||||
DefineViaAlias: true,
|
||||
AdditionalTypes: append(outSchema.AdditionalTypes, newTypeDef),
|
||||
}
|
||||
}
|
||||
|
||||
return outSchema, nil
|
||||
} else if len(schema.Enum) > 0 {
|
||||
err := oapiSchemaToGoType(schema, path, &outSchema)
|
||||
// Enums need to be typed, so that the values aren't interchangeable,
|
||||
// so no matter what schema conversion thinks, we need to define a
|
||||
// new type.
|
||||
outSchema.DefineViaAlias = false
|
||||
|
||||
if err != nil {
|
||||
return Schema{}, fmt.Errorf("error resolving primitive type: %w", err)
|
||||
}
|
||||
enumValues := make([]string, len(schema.Enum))
|
||||
for i, enumValue := range schema.Enum {
|
||||
enumValues[i] = fmt.Sprintf("%v", enumValue)
|
||||
}
|
||||
|
||||
enumNames := enumValues
|
||||
for _, key := range []string{extEnumVarNames, extEnumNames} {
|
||||
if extension, ok := schema.Extensions[key]; ok {
|
||||
if extEnumNames, err := extParseEnumVarNames(extension); err == nil {
|
||||
enumNames = extEnumNames
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sanitizedValues := SanitizeEnumNames(enumNames, enumValues)
|
||||
outSchema.EnumValues = make(map[string]string, len(sanitizedValues))
|
||||
|
||||
for k, v := range sanitizedValues {
|
||||
var enumName string
|
||||
if v == "" {
|
||||
enumName = "Empty"
|
||||
} else {
|
||||
enumName = k
|
||||
}
|
||||
if globalState.options.Compatibility.OldEnumConflicts {
|
||||
outSchema.EnumValues[SchemaNameToTypeName(PathToTypeName(append(path, enumName)))] = v
|
||||
} else {
|
||||
outSchema.EnumValues[SchemaNameToTypeName(k)] = v
|
||||
}
|
||||
}
|
||||
if len(path) > 1 { // handle additional type only on non-toplevel types
|
||||
// Allow overriding autogenerated enum type names, since these may
|
||||
// cause conflicts - see https://github.com/oapi-codegen/oapi-codegen/issues/832
|
||||
var typeName string
|
||||
if extension, ok := schema.Extensions[extGoTypeName]; ok {
|
||||
typeName, err = extString(extension)
|
||||
if err != nil {
|
||||
return outSchema, fmt.Errorf("invalid value for %q: %w", extGoTypeName, err)
|
||||
}
|
||||
} else {
|
||||
typeName = SchemaNameToTypeName(PathToTypeName(path))
|
||||
}
|
||||
|
||||
typeDef := TypeDefinition{
|
||||
TypeName: typeName,
|
||||
JsonName: strings.Join(path, "."),
|
||||
Schema: outSchema,
|
||||
}
|
||||
outSchema.AdditionalTypes = append(outSchema.AdditionalTypes, typeDef)
|
||||
outSchema.RefType = typeName
|
||||
}
|
||||
} else {
|
||||
err := oapiSchemaToGoType(schema, path, &outSchema)
|
||||
if err != nil {
|
||||
return Schema{}, fmt.Errorf("error resolving primitive type: %w", err)
|
||||
}
|
||||
}
|
||||
return outSchema, nil
|
||||
}
|
||||
|
||||
// oapiSchemaToGoType converts an OpenApi schema into a Go type definition for
|
||||
// all non-object types.
|
||||
func oapiSchemaToGoType(schema *openapi3.Schema, path []string, outSchema *Schema) error {
|
||||
f := schema.Format
|
||||
t := schema.Type
|
||||
|
||||
if t.Is("array") {
|
||||
// For arrays, we'll get the type of the Items and throw a
|
||||
// [] in front of it.
|
||||
arrayType, err := GenerateGoSchema(schema.Items, path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error generating type for array: %w", err)
|
||||
}
|
||||
if (arrayType.HasAdditionalProperties || len(arrayType.UnionElements) != 0) && arrayType.RefType == "" {
|
||||
// If we have items which have additional properties or union values,
|
||||
// but are not a pre-defined type, we need to define a type
|
||||
// for them, which will be based on the field names we followed
|
||||
// to get to the type.
|
||||
typeName := PathToTypeName(append(path, "Item"))
|
||||
|
||||
typeDef := TypeDefinition{
|
||||
TypeName: typeName,
|
||||
JsonName: strings.Join(append(path, "Item"), "."),
|
||||
Schema: arrayType,
|
||||
}
|
||||
arrayType.AdditionalTypes = append(arrayType.AdditionalTypes, typeDef)
|
||||
|
||||
arrayType.RefType = typeName
|
||||
}
|
||||
outSchema.ArrayType = &arrayType
|
||||
outSchema.GoType = "[]" + arrayType.TypeDecl()
|
||||
outSchema.AdditionalTypes = arrayType.AdditionalTypes
|
||||
outSchema.Properties = arrayType.Properties
|
||||
outSchema.DefineViaAlias = true
|
||||
if sliceContains(globalState.options.OutputOptions.DisableTypeAliasesForType, "array") {
|
||||
outSchema.DefineViaAlias = false
|
||||
}
|
||||
|
||||
} else if t.Is("integer") {
|
||||
// We default to int if format doesn't ask for something else.
|
||||
if f == "int64" {
|
||||
outSchema.GoType = "int64"
|
||||
} else if f == "int32" {
|
||||
outSchema.GoType = "int32"
|
||||
} else if f == "int16" {
|
||||
outSchema.GoType = "int16"
|
||||
} else if f == "int8" {
|
||||
outSchema.GoType = "int8"
|
||||
} else if f == "int" {
|
||||
outSchema.GoType = "int"
|
||||
} else if f == "uint64" {
|
||||
outSchema.GoType = "uint64"
|
||||
} else if f == "uint32" {
|
||||
outSchema.GoType = "uint32"
|
||||
} else if f == "uint16" {
|
||||
outSchema.GoType = "uint16"
|
||||
} else if f == "uint8" {
|
||||
outSchema.GoType = "uint8"
|
||||
} else if f == "uint" {
|
||||
outSchema.GoType = "uint"
|
||||
} else {
|
||||
outSchema.GoType = "int"
|
||||
}
|
||||
outSchema.DefineViaAlias = true
|
||||
} else if t.Is("number") {
|
||||
// We default to float for "number"
|
||||
if f == "double" {
|
||||
outSchema.GoType = "float64"
|
||||
} else if f == "float" || f == "" {
|
||||
outSchema.GoType = "float32"
|
||||
} else {
|
||||
return fmt.Errorf("invalid number format: %s", f)
|
||||
}
|
||||
outSchema.DefineViaAlias = true
|
||||
} else if t.Is("boolean") {
|
||||
if f != "" {
|
||||
return fmt.Errorf("invalid format (%s) for boolean", f)
|
||||
}
|
||||
outSchema.GoType = "bool"
|
||||
outSchema.DefineViaAlias = true
|
||||
} else if t.Is("string") {
|
||||
// Special case string formats here.
|
||||
switch f {
|
||||
case "byte":
|
||||
outSchema.GoType = "[]byte"
|
||||
case "email":
|
||||
outSchema.GoType = "openapi_types.Email"
|
||||
case "date":
|
||||
outSchema.GoType = "openapi_types.Date"
|
||||
case "date-time":
|
||||
outSchema.GoType = "time.Time"
|
||||
case "json":
|
||||
outSchema.GoType = "json.RawMessage"
|
||||
outSchema.SkipOptionalPointer = true
|
||||
case "uuid":
|
||||
outSchema.GoType = "openapi_types.UUID"
|
||||
case "binary":
|
||||
outSchema.GoType = "openapi_types.File"
|
||||
default:
|
||||
// All unrecognized formats are simply a regular string.
|
||||
outSchema.GoType = "string"
|
||||
}
|
||||
outSchema.DefineViaAlias = true
|
||||
} else {
|
||||
return fmt.Errorf("unhandled Schema type: %v", t)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SchemaDescriptor describes a Schema, a type definition.
|
||||
type SchemaDescriptor struct {
|
||||
Fields []FieldDescriptor
|
||||
HasAdditionalProperties bool
|
||||
AdditionalPropertiesType string
|
||||
}
|
||||
|
||||
type FieldDescriptor struct {
|
||||
Required bool // Is the schema required? If not, we'll pass by pointer
|
||||
GoType string // The Go type needed to represent the json type.
|
||||
GoName string // The Go compatible type name for the type
|
||||
JsonName string // The json type name for the type
|
||||
IsRef bool // Is this schema a reference to predefined object?
|
||||
}
|
||||
|
||||
// GenFieldsFromProperties produce corresponding field names with JSON annotations,
|
||||
// given a list of schema descriptors
|
||||
func GenFieldsFromProperties(props []Property) []string {
|
||||
var fields []string
|
||||
for i, p := range props {
|
||||
field := ""
|
||||
|
||||
goFieldName := p.GoFieldName()
|
||||
|
||||
// Add a comment to a field in case we have one, otherwise skip.
|
||||
if p.Description != "" {
|
||||
// Separate the comment from a previous-defined, unrelated field.
|
||||
// Make sure the actual field is separated by a newline.
|
||||
if i != 0 {
|
||||
field += "\n"
|
||||
}
|
||||
field += fmt.Sprintf("%s\n", StringWithTypeNameToGoComment(p.Description, p.GoFieldName()))
|
||||
}
|
||||
|
||||
if p.Deprecated {
|
||||
// This comment has to be on its own line for godoc & IDEs to pick up
|
||||
var deprecationReason string
|
||||
if extension, ok := p.Extensions[extDeprecationReason]; ok {
|
||||
if extOmitEmpty, err := extParseDeprecationReason(extension); err == nil {
|
||||
deprecationReason = extOmitEmpty
|
||||
}
|
||||
}
|
||||
|
||||
field += fmt.Sprintf("%s\n", DeprecationComment(deprecationReason))
|
||||
}
|
||||
|
||||
// Check x-go-type-skip-optional-pointer, which will override if the type
|
||||
// should be a pointer or not when the field is optional.
|
||||
if extension, ok := p.Extensions[extPropGoTypeSkipOptionalPointer]; ok {
|
||||
if skipOptionalPointer, err := extParsePropGoTypeSkipOptionalPointer(extension); err == nil {
|
||||
p.Schema.SkipOptionalPointer = skipOptionalPointer
|
||||
}
|
||||
}
|
||||
|
||||
field += fmt.Sprintf(" %s %s", goFieldName, p.GoTypeDef())
|
||||
|
||||
shouldOmitEmpty := (!p.Required || p.ReadOnly || p.WriteOnly) &&
|
||||
(!p.Required || !p.ReadOnly || !globalState.options.Compatibility.DisableRequiredReadOnlyAsPointer)
|
||||
|
||||
omitEmpty := !p.Nullable && shouldOmitEmpty
|
||||
|
||||
if p.Nullable && globalState.options.OutputOptions.NullableType {
|
||||
omitEmpty = shouldOmitEmpty
|
||||
}
|
||||
|
||||
// Support x-omitempty
|
||||
if extOmitEmptyValue, ok := p.Extensions[extPropOmitEmpty]; ok {
|
||||
if extOmitEmpty, err := extParseOmitEmpty(extOmitEmptyValue); err == nil {
|
||||
omitEmpty = extOmitEmpty
|
||||
}
|
||||
}
|
||||
|
||||
fieldTags := make(map[string]string)
|
||||
|
||||
if !omitEmpty {
|
||||
fieldTags["json"] = p.JsonFieldName
|
||||
if p.NeedsFormTag {
|
||||
fieldTags["form"] = p.JsonFieldName
|
||||
}
|
||||
} else {
|
||||
fieldTags["json"] = p.JsonFieldName + ",omitempty"
|
||||
if p.NeedsFormTag {
|
||||
fieldTags["form"] = p.JsonFieldName + ",omitempty"
|
||||
}
|
||||
}
|
||||
|
||||
// Support x-go-json-ignore
|
||||
if extension, ok := p.Extensions[extPropGoJsonIgnore]; ok {
|
||||
if goJsonIgnore, err := extParseGoJsonIgnore(extension); err == nil && goJsonIgnore {
|
||||
fieldTags["json"] = "-"
|
||||
}
|
||||
}
|
||||
|
||||
// Support x-oapi-codegen-extra-tags
|
||||
if extension, ok := p.Extensions[extPropExtraTags]; ok {
|
||||
if tags, err := extExtraTags(extension); err == nil {
|
||||
keys := SortedMapKeys(tags)
|
||||
for _, k := range keys {
|
||||
fieldTags[k] = tags[k]
|
||||
}
|
||||
}
|
||||
}
|
||||
// Convert the fieldTags map into Go field annotations.
|
||||
keys := SortedMapKeys(fieldTags)
|
||||
tags := make([]string, len(keys))
|
||||
for i, k := range keys {
|
||||
tags[i] = fmt.Sprintf(`%s:"%s"`, k, fieldTags[k])
|
||||
}
|
||||
field += "`" + strings.Join(tags, " ") + "`"
|
||||
fields = append(fields, field)
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
func additionalPropertiesType(schema Schema) string {
|
||||
addPropsType := schema.AdditionalPropertiesType.GoType
|
||||
if schema.AdditionalPropertiesType.RefType != "" {
|
||||
addPropsType = schema.AdditionalPropertiesType.RefType
|
||||
}
|
||||
if schema.AdditionalPropertiesType.OAPISchema != nil && schema.AdditionalPropertiesType.OAPISchema.Nullable {
|
||||
addPropsType = "*" + addPropsType
|
||||
}
|
||||
return addPropsType
|
||||
}
|
||||
|
||||
func GenStructFromSchema(schema Schema) string {
|
||||
// Start out with struct {
|
||||
objectParts := []string{"struct {"}
|
||||
// Append all the field definitions
|
||||
objectParts = append(objectParts, GenFieldsFromProperties(schema.Properties)...)
|
||||
// Close the struct
|
||||
if schema.HasAdditionalProperties {
|
||||
objectParts = append(objectParts,
|
||||
fmt.Sprintf("AdditionalProperties map[string]%s `json:\"-\"`",
|
||||
additionalPropertiesType(schema)))
|
||||
}
|
||||
if len(schema.UnionElements) != 0 {
|
||||
objectParts = append(objectParts, "union json.RawMessage")
|
||||
}
|
||||
objectParts = append(objectParts, "}")
|
||||
return strings.Join(objectParts, "\n")
|
||||
}
|
||||
|
||||
// This constructs a Go type for a parameter, looking at either the schema or
|
||||
// the content, whichever is available
|
||||
func paramToGoType(param *openapi3.Parameter, path []string) (Schema, error) {
|
||||
if param.Content == nil && param.Schema == nil {
|
||||
return Schema{}, fmt.Errorf("parameter '%s' has no schema or content", param.Name)
|
||||
}
|
||||
|
||||
// We can process the schema through the generic schema processor
|
||||
if param.Schema != nil {
|
||||
return GenerateGoSchema(param.Schema, path)
|
||||
}
|
||||
|
||||
// At this point, we have a content type. We know how to deal with
|
||||
// application/json, but if multiple formats are present, we can't do anything,
|
||||
// so we'll return the parameter as a string, not bothering to decode it.
|
||||
if len(param.Content) > 1 {
|
||||
return Schema{
|
||||
GoType: "string",
|
||||
Description: StringToGoComment(param.Description),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Otherwise, look for application/json in there
|
||||
mt, found := param.Content["application/json"]
|
||||
if !found {
|
||||
// If we don't have json, it's a string
|
||||
return Schema{
|
||||
GoType: "string",
|
||||
Description: StringToGoComment(param.Description),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// For json, we go through the standard schema mechanism
|
||||
return GenerateGoSchema(mt.Schema, path)
|
||||
}
|
||||
|
||||
func generateUnion(outSchema *Schema, elements openapi3.SchemaRefs, discriminator *openapi3.Discriminator, path []string) error {
|
||||
if discriminator != nil {
|
||||
outSchema.Discriminator = &Discriminator{
|
||||
Property: discriminator.PropertyName,
|
||||
Mapping: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
refToGoTypeMap := make(map[string]string)
|
||||
for i, element := range elements {
|
||||
elementPath := append(path, fmt.Sprint(i))
|
||||
elementSchema, err := GenerateGoSchema(element, elementPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if element.Ref == "" {
|
||||
elementName := SchemaNameToTypeName(PathToTypeName(elementPath))
|
||||
if elementSchema.TypeDecl() == elementName {
|
||||
elementSchema.GoType = elementName
|
||||
} else {
|
||||
td := TypeDefinition{Schema: elementSchema, TypeName: elementName}
|
||||
outSchema.AdditionalTypes = append(outSchema.AdditionalTypes, td)
|
||||
elementSchema.GoType = td.TypeName
|
||||
}
|
||||
outSchema.AdditionalTypes = append(outSchema.AdditionalTypes, elementSchema.AdditionalTypes...)
|
||||
} else {
|
||||
refToGoTypeMap[element.Ref] = elementSchema.GoType
|
||||
}
|
||||
|
||||
if discriminator != nil {
|
||||
if len(discriminator.Mapping) != 0 && element.Ref == "" {
|
||||
return errors.New("ambiguous discriminator.mapping: please replace inlined object with $ref")
|
||||
}
|
||||
|
||||
// Explicit mapping.
|
||||
var mapped bool
|
||||
for k, v := range discriminator.Mapping {
|
||||
if v == element.Ref {
|
||||
outSchema.Discriminator.Mapping[k] = elementSchema.GoType
|
||||
mapped = true
|
||||
break
|
||||
}
|
||||
}
|
||||
// Implicit mapping.
|
||||
if !mapped {
|
||||
outSchema.Discriminator.Mapping[RefPathToObjName(element.Ref)] = elementSchema.GoType
|
||||
}
|
||||
}
|
||||
outSchema.UnionElements = append(outSchema.UnionElements, UnionElement(elementSchema.GoType))
|
||||
}
|
||||
|
||||
if (outSchema.Discriminator != nil) && len(outSchema.Discriminator.Mapping) != len(elements) {
|
||||
return errors.New("discriminator: not all schemas were mapped")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
326
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/template_helpers.go
generated
vendored
Normal file
326
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/template_helpers.go
generated
vendored
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
// Copyright 2019 DeepMap, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/oapi-codegen/oapi-codegen/v2/pkg/util"
|
||||
)
|
||||
|
||||
const (
|
||||
// These allow the case statements to be sorted later:
|
||||
prefixLeastSpecific = "9"
|
||||
|
||||
defaultClientTypeName = "Client"
|
||||
)
|
||||
|
||||
var (
|
||||
contentTypesJSON = []string{"application/json", "text/x-json", "application/problem+json"}
|
||||
contentTypesHalJSON = []string{"application/hal+json"}
|
||||
contentTypesYAML = []string{"application/yaml", "application/x-yaml", "text/yaml", "text/x-yaml"}
|
||||
contentTypesXML = []string{"application/xml", "text/xml", "application/problems+xml"}
|
||||
|
||||
responseTypeSuffix = "Response"
|
||||
|
||||
titleCaser = cases.Title(language.English)
|
||||
)
|
||||
|
||||
// genParamArgs takes an array of Parameter definition, and generates a valid
|
||||
// Go parameter declaration from them, eg:
|
||||
// ", foo int, bar string, baz float32". The preceding comma is there to save
|
||||
// a lot of work in the template engine.
|
||||
func genParamArgs(params []ParameterDefinition) string {
|
||||
if len(params) == 0 {
|
||||
return ""
|
||||
}
|
||||
parts := make([]string, len(params))
|
||||
for i, p := range params {
|
||||
paramName := p.GoVariableName()
|
||||
parts[i] = fmt.Sprintf("%s %s", paramName, p.TypeDef())
|
||||
}
|
||||
return ", " + strings.Join(parts, ", ")
|
||||
}
|
||||
|
||||
// genParamTypes is much like the one above, except it only produces the
|
||||
// types of the parameters for a type declaration. It would produce this
|
||||
// from the same input as above:
|
||||
// ", int, string, float32".
|
||||
func genParamTypes(params []ParameterDefinition) string {
|
||||
if len(params) == 0 {
|
||||
return ""
|
||||
}
|
||||
parts := make([]string, len(params))
|
||||
for i, p := range params {
|
||||
parts[i] = p.TypeDef()
|
||||
}
|
||||
return ", " + strings.Join(parts, ", ")
|
||||
}
|
||||
|
||||
// This is another variation of the function above which generates only the
|
||||
// parameter names:
|
||||
// ", foo, bar, baz"
|
||||
func genParamNames(params []ParameterDefinition) string {
|
||||
if len(params) == 0 {
|
||||
return ""
|
||||
}
|
||||
parts := make([]string, len(params))
|
||||
for i, p := range params {
|
||||
parts[i] = p.GoVariableName()
|
||||
}
|
||||
return ", " + strings.Join(parts, ", ")
|
||||
}
|
||||
|
||||
// genResponsePayload generates the payload returned at the end of each client request function
|
||||
func genResponsePayload(operationID string) string {
|
||||
var buffer = bytes.NewBufferString("")
|
||||
|
||||
// Here is where we build up a response:
|
||||
fmt.Fprintf(buffer, "&%s{\n", genResponseTypeName(operationID))
|
||||
fmt.Fprintf(buffer, "Body: bodyBytes,\n")
|
||||
fmt.Fprintf(buffer, "HTTPResponse: rsp,\n")
|
||||
fmt.Fprintf(buffer, "}")
|
||||
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
// genResponseUnmarshal generates unmarshaling steps for structured response payloads
|
||||
func genResponseUnmarshal(op *OperationDefinition) string {
|
||||
var handledCaseClauses = make(map[string]string)
|
||||
var unhandledCaseClauses = make(map[string]string)
|
||||
|
||||
// Get the type definitions from the operation:
|
||||
typeDefinitions, err := op.GetResponseTypeDefinitions()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if len(typeDefinitions) == 0 {
|
||||
// No types.
|
||||
return ""
|
||||
}
|
||||
|
||||
// Add a case for each possible response:
|
||||
buffer := new(bytes.Buffer)
|
||||
responses := op.Spec.Responses
|
||||
for _, typeDefinition := range typeDefinitions {
|
||||
|
||||
responseRef := responses.Value(typeDefinition.ResponseName)
|
||||
if responseRef == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// We can't do much without a value:
|
||||
if responseRef.Value == nil {
|
||||
fmt.Fprintf(os.Stderr, "Response %s.%s has nil value\n", op.OperationId, typeDefinition.ResponseName)
|
||||
continue
|
||||
}
|
||||
|
||||
// If there is no content-type then we have no unmarshaling to do:
|
||||
if len(responseRef.Value.Content) == 0 {
|
||||
caseAction := "break // No content-type"
|
||||
caseClauseKey := "case " + getConditionOfResponseName("rsp.StatusCode", typeDefinition.ResponseName) + ":"
|
||||
unhandledCaseClauses[prefixLeastSpecific+caseClauseKey] = fmt.Sprintf("%s\n%s\n", caseClauseKey, caseAction)
|
||||
continue
|
||||
}
|
||||
|
||||
// If we made it this far then we need to handle unmarshaling for each content-type:
|
||||
SortedMapKeys := SortedMapKeys(responseRef.Value.Content)
|
||||
jsonCount := 0
|
||||
for _, contentTypeName := range SortedMapKeys {
|
||||
if StringInArray(contentTypeName, contentTypesJSON) || util.IsMediaTypeJson(contentTypeName) {
|
||||
jsonCount++
|
||||
}
|
||||
}
|
||||
|
||||
for _, contentTypeName := range SortedMapKeys {
|
||||
|
||||
// We get "interface{}" when using "anyOf" or "oneOf" (which doesn't work with Go types):
|
||||
if typeDefinition.TypeName == "interface{}" {
|
||||
// Unable to unmarshal this, so we leave it out:
|
||||
continue
|
||||
}
|
||||
|
||||
// Add content-types here (json / yaml / xml etc):
|
||||
switch {
|
||||
|
||||
// JSON:
|
||||
case StringInArray(contentTypeName, contentTypesJSON) || util.IsMediaTypeJson(contentTypeName):
|
||||
if typeDefinition.ContentTypeName == contentTypeName {
|
||||
caseAction := fmt.Sprintf("var dest %s\n"+
|
||||
"if err := json.Unmarshal(bodyBytes, &dest); err != nil { \n"+
|
||||
" return nil, err \n"+
|
||||
"}\n"+
|
||||
"response.%s = &dest",
|
||||
typeDefinition.Schema.TypeDecl(),
|
||||
typeDefinition.TypeName)
|
||||
|
||||
if jsonCount > 1 {
|
||||
caseKey, caseClause := buildUnmarshalCaseStrict(typeDefinition, caseAction, contentTypeName)
|
||||
handledCaseClauses[caseKey] = caseClause
|
||||
} else {
|
||||
caseKey, caseClause := buildUnmarshalCase(typeDefinition, caseAction, "json")
|
||||
handledCaseClauses[caseKey] = caseClause
|
||||
}
|
||||
}
|
||||
|
||||
// YAML:
|
||||
case StringInArray(contentTypeName, contentTypesYAML):
|
||||
if typeDefinition.ContentTypeName == contentTypeName {
|
||||
caseAction := fmt.Sprintf("var dest %s\n"+
|
||||
"if err := yaml.Unmarshal(bodyBytes, &dest); err != nil { \n"+
|
||||
" return nil, err \n"+
|
||||
"}\n"+
|
||||
"response.%s = &dest",
|
||||
typeDefinition.Schema.TypeDecl(),
|
||||
typeDefinition.TypeName)
|
||||
caseKey, caseClause := buildUnmarshalCase(typeDefinition, caseAction, "yaml")
|
||||
handledCaseClauses[caseKey] = caseClause
|
||||
}
|
||||
|
||||
// XML:
|
||||
case StringInArray(contentTypeName, contentTypesXML):
|
||||
if typeDefinition.ContentTypeName == contentTypeName {
|
||||
caseAction := fmt.Sprintf("var dest %s\n"+
|
||||
"if err := xml.Unmarshal(bodyBytes, &dest); err != nil { \n"+
|
||||
" return nil, err \n"+
|
||||
"}\n"+
|
||||
"response.%s = &dest",
|
||||
typeDefinition.Schema.TypeDecl(),
|
||||
typeDefinition.TypeName)
|
||||
caseKey, caseClause := buildUnmarshalCase(typeDefinition, caseAction, "xml")
|
||||
handledCaseClauses[caseKey] = caseClause
|
||||
}
|
||||
|
||||
// Everything else:
|
||||
default:
|
||||
caseAction := fmt.Sprintf("// Content-type (%s) unsupported", contentTypeName)
|
||||
caseClauseKey := "case " + getConditionOfResponseName("rsp.StatusCode", typeDefinition.ResponseName) + ":"
|
||||
unhandledCaseClauses[prefixLeastSpecific+caseClauseKey] = fmt.Sprintf("%s\n%s\n", caseClauseKey, caseAction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(handledCaseClauses)+len(unhandledCaseClauses) == 0 {
|
||||
// switch would be empty.
|
||||
return ""
|
||||
}
|
||||
|
||||
// Now build the switch statement in order of most-to-least specific:
|
||||
// See: https://github.com/oapi-codegen/oapi-codegen/issues/127 for why we handle this in two separate
|
||||
// groups.
|
||||
fmt.Fprintf(buffer, "switch {\n")
|
||||
for _, caseClauseKey := range SortedMapKeys(handledCaseClauses) {
|
||||
|
||||
fmt.Fprintf(buffer, "%s\n", handledCaseClauses[caseClauseKey])
|
||||
}
|
||||
for _, caseClauseKey := range SortedMapKeys(unhandledCaseClauses) {
|
||||
|
||||
fmt.Fprintf(buffer, "%s\n", unhandledCaseClauses[caseClauseKey])
|
||||
}
|
||||
fmt.Fprintf(buffer, "}\n")
|
||||
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
// buildUnmarshalCase builds an unmarshaling case clause for different content-types:
|
||||
func buildUnmarshalCase(typeDefinition ResponseTypeDefinition, caseAction string, contentType string) (caseKey string, caseClause string) {
|
||||
caseKey = fmt.Sprintf("%s.%s.%s", prefixLeastSpecific, contentType, typeDefinition.ResponseName)
|
||||
caseClauseKey := getConditionOfResponseName("rsp.StatusCode", typeDefinition.ResponseName)
|
||||
caseClause = fmt.Sprintf("case strings.Contains(rsp.Header.Get(\"%s\"), \"%s\") && %s:\n%s\n", "Content-Type", contentType, caseClauseKey, caseAction)
|
||||
return caseKey, caseClause
|
||||
}
|
||||
|
||||
func buildUnmarshalCaseStrict(typeDefinition ResponseTypeDefinition, caseAction string, contentType string) (caseKey string, caseClause string) {
|
||||
caseKey = fmt.Sprintf("%s.%s.%s", prefixLeastSpecific, contentType, typeDefinition.ResponseName)
|
||||
caseClauseKey := getConditionOfResponseName("rsp.StatusCode", typeDefinition.ResponseName)
|
||||
caseClause = fmt.Sprintf("case rsp.Header.Get(\"%s\") == \"%s\" && %s:\n%s\n", "Content-Type", contentType, caseClauseKey, caseAction)
|
||||
return caseKey, caseClause
|
||||
}
|
||||
|
||||
// genResponseTypeName creates the name of generated response types (given the operationID):
|
||||
func genResponseTypeName(operationID string) string {
|
||||
return fmt.Sprintf("%s%s", UppercaseFirstCharacter(operationID), responseTypeSuffix)
|
||||
}
|
||||
|
||||
func getResponseTypeDefinitions(op *OperationDefinition) []ResponseTypeDefinition {
|
||||
td, err := op.GetResponseTypeDefinitions()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return td
|
||||
}
|
||||
|
||||
// Return the statusCode comparison clause from the response name.
|
||||
func getConditionOfResponseName(statusCodeVar, responseName string) string {
|
||||
switch responseName {
|
||||
case "default":
|
||||
return "true"
|
||||
case "1XX", "2XX", "3XX", "4XX", "5XX":
|
||||
return fmt.Sprintf("%s / 100 == %s", statusCodeVar, responseName[:1])
|
||||
default:
|
||||
return fmt.Sprintf("%s == %s", statusCodeVar, responseName)
|
||||
}
|
||||
}
|
||||
|
||||
// This outputs a string array
|
||||
func toStringArray(sarr []string) string {
|
||||
s := strings.Join(sarr, `","`)
|
||||
if len(s) > 0 {
|
||||
s = `"` + s + `"`
|
||||
}
|
||||
return `[]string{` + s + `}`
|
||||
}
|
||||
|
||||
func stripNewLines(s string) string {
|
||||
r := strings.NewReplacer("\n", "")
|
||||
return r.Replace(s)
|
||||
}
|
||||
|
||||
// TemplateFunctions is passed to the template engine, and we can call each
|
||||
// function here by keyName from the template code.
|
||||
var TemplateFunctions = template.FuncMap{
|
||||
"genParamArgs": genParamArgs,
|
||||
"genParamTypes": genParamTypes,
|
||||
"genParamNames": genParamNames,
|
||||
"genParamFmtString": ReplacePathParamsWithStr,
|
||||
"swaggerUriToIrisUri": SwaggerUriToIrisUri,
|
||||
"swaggerUriToEchoUri": SwaggerUriToEchoUri,
|
||||
"swaggerUriToFiberUri": SwaggerUriToFiberUri,
|
||||
"swaggerUriToChiUri": SwaggerUriToChiUri,
|
||||
"swaggerUriToGinUri": SwaggerUriToGinUri,
|
||||
"swaggerUriToGorillaUri": SwaggerUriToGorillaUri,
|
||||
"swaggerUriToStdHttpUri": SwaggerUriToStdHttpUri,
|
||||
"lcFirst": LowercaseFirstCharacter,
|
||||
"ucFirst": UppercaseFirstCharacter,
|
||||
"ucFirstWithPkgName": UppercaseFirstCharacterWithPkgName,
|
||||
"camelCase": ToCamelCase,
|
||||
"genResponsePayload": genResponsePayload,
|
||||
"genResponseTypeName": genResponseTypeName,
|
||||
"genResponseUnmarshal": genResponseUnmarshal,
|
||||
"getResponseTypeDefinitions": getResponseTypeDefinitions,
|
||||
"toStringArray": toStringArray,
|
||||
"lower": strings.ToLower,
|
||||
"title": titleCaser.String,
|
||||
"stripNewLines": stripNewLines,
|
||||
"sanitizeGoIdentity": SanitizeGoIdentity,
|
||||
"toGoComment": StringWithTypeNameToGoComment,
|
||||
}
|
||||
72
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/additional-properties.tmpl
generated
vendored
Normal file
72
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/additional-properties.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
{{range .Types}}{{$addType := .Schema.AdditionalPropertiesType.TypeDecl}}
|
||||
|
||||
// Getter for additional properties for {{.TypeName}}. Returns the specified
|
||||
// element and whether it was found
|
||||
func (a {{.TypeName}}) Get(fieldName string) (value {{$addType}}, found bool) {
|
||||
if a.AdditionalProperties != nil {
|
||||
value, found = a.AdditionalProperties[fieldName]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Setter for additional properties for {{.TypeName}}
|
||||
func (a *{{.TypeName}}) Set(fieldName string, value {{$addType}}) {
|
||||
if a.AdditionalProperties == nil {
|
||||
a.AdditionalProperties = make(map[string]{{$addType}})
|
||||
}
|
||||
a.AdditionalProperties[fieldName] = value
|
||||
}
|
||||
|
||||
{{if eq 0 (len .Schema.UnionElements) -}}
|
||||
// Override default JSON handling for {{.TypeName}} to handle AdditionalProperties
|
||||
func (a *{{.TypeName}}) UnmarshalJSON(b []byte) error {
|
||||
object := make(map[string]json.RawMessage)
|
||||
err := json.Unmarshal(b, &object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
{{range .Schema.Properties}}
|
||||
if raw, found := object["{{.JsonFieldName}}"]; found {
|
||||
err = json.Unmarshal(raw, &a.{{.GoFieldName}})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading '{{.JsonFieldName}}': %w", err)
|
||||
}
|
||||
delete(object, "{{.JsonFieldName}}")
|
||||
}
|
||||
{{end}}
|
||||
if len(object) != 0 {
|
||||
a.AdditionalProperties = make(map[string]{{$addType}})
|
||||
for fieldName, fieldBuf := range object {
|
||||
var fieldVal {{$addType}}
|
||||
err := json.Unmarshal(fieldBuf, &fieldVal)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error unmarshaling field %s: %w", fieldName, err)
|
||||
}
|
||||
a.AdditionalProperties[fieldName] = fieldVal
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Override default JSON handling for {{.TypeName}} to handle AdditionalProperties
|
||||
func (a {{.TypeName}}) MarshalJSON() ([]byte, error) {
|
||||
var err error
|
||||
object := make(map[string]json.RawMessage)
|
||||
{{range .Schema.Properties}}
|
||||
{{if not .Required}}if a.{{.GoFieldName}} != nil { {{end}}
|
||||
object["{{.JsonFieldName}}"], err = json.Marshal(a.{{.GoFieldName}})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error marshaling '{{.JsonFieldName}}': %w", err)
|
||||
}
|
||||
{{if not .Required}} }{{end}}
|
||||
{{end}}
|
||||
for fieldName, field := range a.AdditionalProperties {
|
||||
object[fieldName], err = json.Marshal(field)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error marshaling '%s': %w", fieldName, err)
|
||||
}
|
||||
}
|
||||
return json.Marshal(object)
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
50
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/chi/chi-handler.tmpl
generated
vendored
Normal file
50
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/chi/chi-handler.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
// Handler creates http.Handler with routing matching OpenAPI spec.
|
||||
func Handler(si ServerInterface) http.Handler {
|
||||
return HandlerWithOptions(si, ChiServerOptions{})
|
||||
}
|
||||
|
||||
type ChiServerOptions struct {
|
||||
BaseURL string
|
||||
BaseRouter chi.Router
|
||||
Middlewares []MiddlewareFunc
|
||||
ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error)
|
||||
}
|
||||
|
||||
// HandlerFromMux creates http.Handler with routing matching OpenAPI spec based on the provided mux.
|
||||
func HandlerFromMux(si ServerInterface, r chi.Router) http.Handler {
|
||||
return HandlerWithOptions(si, ChiServerOptions {
|
||||
BaseRouter: r,
|
||||
})
|
||||
}
|
||||
|
||||
func HandlerFromMuxWithBaseURL(si ServerInterface, r chi.Router, baseURL string) http.Handler {
|
||||
return HandlerWithOptions(si, ChiServerOptions {
|
||||
BaseURL: baseURL,
|
||||
BaseRouter: r,
|
||||
})
|
||||
}
|
||||
|
||||
// HandlerWithOptions creates http.Handler with additional options
|
||||
func HandlerWithOptions(si ServerInterface, options ChiServerOptions) http.Handler {
|
||||
r := options.BaseRouter
|
||||
|
||||
if r == nil {
|
||||
r = chi.NewRouter()
|
||||
}
|
||||
if options.ErrorHandlerFunc == nil {
|
||||
options.ErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
{{if .}}wrapper := ServerInterfaceWrapper{
|
||||
Handler: si,
|
||||
HandlerMiddlewares: options.Middlewares,
|
||||
ErrorHandlerFunc: options.ErrorHandlerFunc,
|
||||
}
|
||||
{{end}}
|
||||
{{range .}}r.Group(func(r chi.Router) {
|
||||
r.{{.Method | lower | title }}(options.BaseURL+"{{.Path | swaggerUriToChiUri}}", wrapper.{{.OperationId}})
|
||||
})
|
||||
{{end}}
|
||||
return r
|
||||
}
|
||||
17
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/chi/chi-interface.tmpl
generated
vendored
Normal file
17
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/chi/chi-interface.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// 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}}
|
||||
}
|
||||
|
||||
// Unimplemented server implementation that returns http.StatusNotImplemented for each endpoint.
|
||||
|
||||
type Unimplemented struct {}
|
||||
{{range .}}{{.SummaryAsComment }}
|
||||
// ({{.Method}} {{.Path}})
|
||||
func (_ Unimplemented) {{.OperationId}}(w http.ResponseWriter, r *http.Request{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params {{.OperationId}}Params{{end}}) {
|
||||
w.WriteHeader(http.StatusNotImplemented)
|
||||
}
|
||||
{{end}}
|
||||
266
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/chi/chi-middleware.tmpl
generated
vendored
Normal file
266
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/chi/chi-middleware.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
// ServerInterfaceWrapper converts contexts to parameters.
|
||||
type ServerInterfaceWrapper struct {
|
||||
Handler ServerInterface
|
||||
HandlerMiddlewares []MiddlewareFunc
|
||||
ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error)
|
||||
}
|
||||
|
||||
type MiddlewareFunc func(http.Handler) http.Handler
|
||||
|
||||
{{range .}}{{$opid := .OperationId}}
|
||||
|
||||
// {{$opid}} operation middleware
|
||||
func (siw *ServerInterfaceWrapper) {{$opid}}(w http.ResponseWriter, r *http.Request) {
|
||||
{{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 {
|
||||
siw.ErrorHandlerFunc(w, r, &UnmarshalingParamError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindStyledParameterWithOptions("{{.Style}}", "{{.ParamName}}", chi.URLParam(r, "{{.ParamName}}"), &{{$varName}}, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: {{.Explode}}, Required: {{.Required}}})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{end}}
|
||||
|
||||
{{if .SecurityDefinitions -}}
|
||||
ctx := r.Context()
|
||||
{{range .SecurityDefinitions}}
|
||||
ctx = context.WithValue(ctx, {{.ProviderName | sanitizeGoIdentity | ucFirst}}Scopes, {{toStringArray .Scopes}})
|
||||
{{end}}
|
||||
r = r.WithContext(ctx)
|
||||
{{end}}
|
||||
|
||||
{{if .RequiresParamObject}}
|
||||
// Parameter object where we will unmarshal all parameters from the context
|
||||
var params {{.OperationId}}Params
|
||||
|
||||
{{range $paramIdx, $param := .QueryParams}}
|
||||
{{- if (or (or .Required .IsPassThrough) (or .IsJson .IsStyled)) -}}
|
||||
// ------------- {{if .Required}}Required{{else}}Optional{{end}} query parameter "{{.ParamName}}" -------------
|
||||
{{ end }}
|
||||
{{ if (or (or .Required .IsPassThrough) .IsJson) }}
|
||||
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 {
|
||||
siw.ErrorHandlerFunc(w, r, &UnmarshalingParamError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
}{{if .Required}} else {
|
||||
siw.ErrorHandlerFunc(w, r, &RequiredParamError{ParamName: "{{.ParamName}}"})
|
||||
return
|
||||
}{{end}}
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindQueryParameter("{{.Style}}", {{.Explode}}, {{.Required}}, "{{.ParamName}}", r.URL.Query(), ¶ms.{{.GoName}})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "{{.ParamName}}", Err: err})
|
||||
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 {
|
||||
siw.ErrorHandlerFunc(w, r, &TooManyValuesForParamError{ParamName: "{{.ParamName}}", Count: n})
|
||||
return
|
||||
}
|
||||
|
||||
{{if .IsPassThrough}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}valueList[0]
|
||||
{{end}}
|
||||
|
||||
{{if .IsJson}}
|
||||
err = json.Unmarshal([]byte(valueList[0]), &{{.GoName}})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &UnmarshalingParamError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindStyledParameterWithOptions("{{.Style}}", "{{.ParamName}}", valueList[0], &{{.GoName}}, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: {{.Explode}}, Required: {{.Required}}})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}{{.GoName}}
|
||||
|
||||
} {{if .Required}}else {
|
||||
err := fmt.Errorf("Header parameter {{.ParamName}} is required, but not found")
|
||||
siw.ErrorHandlerFunc(w, r, &RequiredHeaderError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}{{end}}
|
||||
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range .CookieParams}}
|
||||
{
|
||||
var cookie *http.Cookie
|
||||
|
||||
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 {
|
||||
err = fmt.Errorf("Error unescaping cookie parameter '{{.ParamName}}'")
|
||||
siw.ErrorHandlerFunc(w, r, &UnescapedCookieParamError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(decoded), &value)
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &UnmarshalingParamError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
|
||||
{{- if .IsStyled}}
|
||||
var value {{.TypeDef}}
|
||||
err = runtime.BindStyledParameterWithOptions("simple", "{{.ParamName}}", cookie.Value, &value, runtime.BindStyledParameterOptions{Explode: {{.Explode}}, Required: {{.Required}}})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
|
||||
}
|
||||
|
||||
{{- if .Required}} else {
|
||||
siw.ErrorHandlerFunc(w, r, &RequiredParamError{ParamName: "{{.ParamName}}"})
|
||||
return
|
||||
}
|
||||
{{- end}}
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
siw.Handler.{{.OperationId}}(w, r{{genParamNames .PathParams}}{{if .RequiresParamObject}}, params{{end}})
|
||||
}))
|
||||
|
||||
{{if opts.Compatibility.ApplyChiMiddlewareFirstToLast}}
|
||||
for i := len(siw.HandlerMiddlewares) -1; i >= 0; i-- {
|
||||
handler = siw.HandlerMiddlewares[i](handler)
|
||||
}
|
||||
{{else}}
|
||||
for _, middleware := range siw.HandlerMiddlewares {
|
||||
handler = middleware(handler)
|
||||
}
|
||||
{{end}}
|
||||
|
||||
handler.ServeHTTP(w, r)
|
||||
}
|
||||
{{end}}
|
||||
|
||||
type UnescapedCookieParamError struct {
|
||||
ParamName string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *UnescapedCookieParamError) Error() string {
|
||||
return fmt.Sprintf("error unescaping cookie parameter '%s'", e.ParamName)
|
||||
}
|
||||
|
||||
func (e *UnescapedCookieParamError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
type UnmarshalingParamError struct {
|
||||
ParamName string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *UnmarshalingParamError) Error() string {
|
||||
return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error())
|
||||
}
|
||||
|
||||
func (e *UnmarshalingParamError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
type RequiredParamError struct {
|
||||
ParamName string
|
||||
}
|
||||
|
||||
func (e *RequiredParamError) Error() string {
|
||||
return fmt.Sprintf("Query argument %s is required, but not found", e.ParamName)
|
||||
}
|
||||
|
||||
type RequiredHeaderError struct {
|
||||
ParamName string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *RequiredHeaderError) Error() string {
|
||||
return fmt.Sprintf("Header parameter %s is required, but not found", e.ParamName)
|
||||
}
|
||||
|
||||
func (e *RequiredHeaderError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
type InvalidParamFormatError struct {
|
||||
ParamName string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *InvalidParamFormatError) Error() string {
|
||||
return fmt.Sprintf("Invalid format for parameter %s: %s", e.ParamName, e.Err.Error())
|
||||
}
|
||||
|
||||
func (e *InvalidParamFormatError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
type TooManyValuesForParamError struct {
|
||||
ParamName string
|
||||
Count int
|
||||
}
|
||||
|
||||
func (e *TooManyValuesForParamError) Error() string {
|
||||
return fmt.Sprintf("Expected one value for %s, got %d", e.ParamName, e.Count)
|
||||
}
|
||||
127
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/client-with-responses.tmpl
generated
vendored
Normal file
127
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/client-with-responses.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
// ClientWithResponses builds on ClientInterface to offer response payloads
|
||||
type ClientWithResponses struct {
|
||||
ClientInterface
|
||||
}
|
||||
|
||||
// NewClientWithResponses creates a new ClientWithResponses, which wraps
|
||||
// Client with return type handling
|
||||
func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithResponses, error) {
|
||||
client, err := NewClient(server, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ClientWithResponses{client}, nil
|
||||
}
|
||||
|
||||
{{$clientTypeName := opts.OutputOptions.ClientTypeName -}}
|
||||
|
||||
// WithBaseURL overrides the baseURL.
|
||||
func WithBaseURL(baseURL string) ClientOption {
|
||||
return func(c *{{ $clientTypeName }}) error {
|
||||
newBaseURL, err := url.Parse(baseURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.Server = newBaseURL.String()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ClientWithResponsesInterface is the interface specification for the client with responses above.
|
||||
type ClientWithResponsesInterface interface {
|
||||
{{range . -}}
|
||||
{{$hasParams := .RequiresParamObject -}}
|
||||
{{$pathParams := .PathParams -}}
|
||||
{{$opid := .OperationId -}}
|
||||
// {{$opid}}{{if .HasBody}}WithBody{{end}}WithResponse request{{if .HasBody}} with any body{{end}}
|
||||
{{$opid}}{{if .HasBody}}WithBody{{end}}WithResponse(ctx context.Context{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params *{{$opid}}Params{{end}}{{if .HasBody}}, contentType string, body io.Reader{{end}}, reqEditors... RequestEditorFn) (*{{genResponseTypeName $opid}}, error)
|
||||
{{range .Bodies}}
|
||||
{{if .IsSupportedByClient -}}
|
||||
{{$opid}}{{.Suffix}}WithResponse(ctx context.Context{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}, body {{$opid}}{{.NameTag}}RequestBody, reqEditors... RequestEditorFn) (*{{genResponseTypeName $opid}}, error)
|
||||
{{end -}}
|
||||
{{end}}{{/* range .Bodies */}}
|
||||
{{end}}{{/* range . $opid := .OperationId */}}
|
||||
}
|
||||
|
||||
{{range .}}{{$opid := .OperationId}}{{$op := .}}
|
||||
{{$responseTypeDefinitions := getResponseTypeDefinitions .}}
|
||||
type {{genResponseTypeName $opid | ucFirst}} struct {
|
||||
Body []byte
|
||||
HTTPResponse *http.Response
|
||||
{{- range $responseTypeDefinitions}}
|
||||
{{.TypeName}} *{{.Schema.TypeDecl}}
|
||||
{{- end}}
|
||||
}
|
||||
|
||||
{{- range $responseTypeDefinitions}}
|
||||
{{- range .AdditionalTypeDefinitions}}
|
||||
type {{.TypeName}} {{if .IsAlias }}={{end}} {{.Schema.TypeDecl}}
|
||||
{{- end}}
|
||||
{{- end}}
|
||||
|
||||
// Status returns HTTPResponse.Status
|
||||
func (r {{genResponseTypeName $opid | ucFirst}}) Status() string {
|
||||
if r.HTTPResponse != nil {
|
||||
return r.HTTPResponse.Status
|
||||
}
|
||||
return http.StatusText(0)
|
||||
}
|
||||
|
||||
// StatusCode returns HTTPResponse.StatusCode
|
||||
func (r {{genResponseTypeName $opid | ucFirst}}) StatusCode() int {
|
||||
if r.HTTPResponse != nil {
|
||||
return r.HTTPResponse.StatusCode
|
||||
}
|
||||
return 0
|
||||
}
|
||||
{{end}}
|
||||
|
||||
|
||||
{{range .}}
|
||||
{{$opid := .OperationId -}}
|
||||
{{/* Generate client methods (with responses)*/}}
|
||||
|
||||
// {{$opid}}{{if .HasBody}}WithBody{{end}}WithResponse request{{if .HasBody}} with arbitrary body{{end}} returning *{{genResponseTypeName $opid}}
|
||||
func (c *ClientWithResponses) {{$opid}}{{if .HasBody}}WithBody{{end}}WithResponse(ctx context.Context{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params *{{$opid}}Params{{end}}{{if .HasBody}}, contentType string, body io.Reader{{end}}, reqEditors... RequestEditorFn) (*{{genResponseTypeName $opid}}, error){
|
||||
rsp, err := c.{{$opid}}{{if .HasBody}}WithBody{{end}}(ctx{{genParamNames .PathParams}}{{if .RequiresParamObject}}, params{{end}}{{if .HasBody}}, contentType, body{{end}}, reqEditors...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return Parse{{genResponseTypeName $opid | ucFirst}}(rsp)
|
||||
}
|
||||
|
||||
{{$hasParams := .RequiresParamObject -}}
|
||||
{{$pathParams := .PathParams -}}
|
||||
{{$bodyRequired := .BodyRequired -}}
|
||||
{{range .Bodies}}
|
||||
{{if .IsSupportedByClient -}}
|
||||
func (c *ClientWithResponses) {{$opid}}{{.Suffix}}WithResponse(ctx context.Context{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}, body {{$opid}}{{.NameTag}}RequestBody, reqEditors... RequestEditorFn) (*{{genResponseTypeName $opid}}, error) {
|
||||
rsp, err := c.{{$opid}}{{.Suffix}}(ctx{{genParamNames $pathParams}}{{if $hasParams}}, params{{end}}, body, reqEditors...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return Parse{{genResponseTypeName $opid | ucFirst}}(rsp)
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{end}}{{/* operations */}}
|
||||
|
||||
{{/* Generate parse functions for responses*/}}
|
||||
{{range .}}{{$opid := .OperationId}}
|
||||
|
||||
// Parse{{genResponseTypeName $opid | ucFirst}} parses an HTTP response from a {{$opid}}WithResponse call
|
||||
func Parse{{genResponseTypeName $opid | ucFirst}}(rsp *http.Response) (*{{genResponseTypeName $opid}}, error) {
|
||||
bodyBytes, err := io.ReadAll(rsp.Body)
|
||||
defer func() { _ = rsp.Body.Close() }()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response := {{genResponsePayload $opid}}
|
||||
|
||||
{{genResponseUnmarshal .}}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
{{end}}{{/* range . $opid := .OperationId */}}
|
||||
312
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/client.tmpl
generated
vendored
Normal file
312
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/client.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,312 @@
|
|||
// RequestEditorFn is the function signature for the RequestEditor callback function
|
||||
type RequestEditorFn func(ctx context.Context, req *http.Request) error
|
||||
|
||||
// Doer performs HTTP requests.
|
||||
//
|
||||
// The standard http.Client implements this interface.
|
||||
type HttpRequestDoer interface {
|
||||
Do(req *http.Request) (*http.Response, error)
|
||||
}
|
||||
|
||||
{{$clientTypeName := opts.OutputOptions.ClientTypeName -}}
|
||||
|
||||
// {{ $clientTypeName }} which conforms to the OpenAPI3 specification for this service.
|
||||
type {{ $clientTypeName }} struct {
|
||||
// The endpoint of the server conforming to this interface, with scheme,
|
||||
// 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
|
||||
// customized settings, such as certificate chains.
|
||||
Client HttpRequestDoer
|
||||
|
||||
// A list of callbacks for modifying requests which are generated before sending over
|
||||
// the network.
|
||||
RequestEditors []RequestEditorFn
|
||||
}
|
||||
|
||||
// ClientOption allows setting custom parameters during construction
|
||||
type ClientOption func(*{{ $clientTypeName }}) error
|
||||
|
||||
// Creates a new {{ $clientTypeName }}, with reasonable defaults
|
||||
func NewClient(server string, opts ...ClientOption) (*{{ $clientTypeName }}, error) {
|
||||
// create a client with sane default values
|
||||
client := {{ $clientTypeName }}{
|
||||
Server: server,
|
||||
}
|
||||
// mutate client and add all optional params
|
||||
for _, o := range opts {
|
||||
if err := o(&client); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// ensure the server URL always has a trailing slash
|
||||
if !strings.HasSuffix(client.Server, "/") {
|
||||
client.Server += "/"
|
||||
}
|
||||
// create httpClient, if not already present
|
||||
if client.Client == nil {
|
||||
client.Client = &http.Client{}
|
||||
}
|
||||
return &client, nil
|
||||
}
|
||||
|
||||
// WithHTTPClient allows overriding the default Doer, which is
|
||||
// automatically created using http.Client. This is useful for tests.
|
||||
func WithHTTPClient(doer HttpRequestDoer) ClientOption {
|
||||
return func(c *{{ $clientTypeName }}) error {
|
||||
c.Client = doer
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithRequestEditorFn allows setting up a callback function, which will be
|
||||
// called right before sending the request. This can be used to mutate the request.
|
||||
func WithRequestEditorFn(fn RequestEditorFn) ClientOption {
|
||||
return func(c *{{ $clientTypeName }}) error {
|
||||
c.RequestEditors = append(c.RequestEditors, fn)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// The interface specification for the client above.
|
||||
type ClientInterface interface {
|
||||
{{range . -}}
|
||||
{{$hasParams := .RequiresParamObject -}}
|
||||
{{$pathParams := .PathParams -}}
|
||||
{{$opid := .OperationId -}}
|
||||
// {{$opid}}{{if .HasBody}}WithBody{{end}} request{{if .HasBody}} with any body{{end}}
|
||||
{{$opid}}{{if .HasBody}}WithBody{{end}}(ctx context.Context{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}{{if .HasBody}}, contentType string, body io.Reader{{end}}, reqEditors... RequestEditorFn) (*http.Response, error)
|
||||
{{range .Bodies}}
|
||||
{{if .IsSupportedByClient -}}
|
||||
{{$opid}}{{.Suffix}}(ctx context.Context{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}, body {{$opid}}{{.NameTag}}RequestBody, reqEditors... RequestEditorFn) (*http.Response, error)
|
||||
{{end -}}
|
||||
{{end}}{{/* range .Bodies */}}
|
||||
{{end}}{{/* range . $opid := .OperationId */}}
|
||||
}
|
||||
|
||||
|
||||
{{/* Generate client methods */}}
|
||||
{{range . -}}
|
||||
{{$hasParams := .RequiresParamObject -}}
|
||||
{{$pathParams := .PathParams -}}
|
||||
{{$opid := .OperationId -}}
|
||||
|
||||
func (c *{{ $clientTypeName }}) {{$opid}}{{if .HasBody}}WithBody{{end}}(ctx context.Context{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}{{if .HasBody}}, contentType string, body io.Reader{{end}}, reqEditors... RequestEditorFn) (*http.Response, error) {
|
||||
req, err := New{{$opid}}Request{{if .HasBody}}WithBody{{end}}(c.Server{{genParamNames .PathParams}}{{if $hasParams}}, params{{end}}{{if .HasBody}}, contentType, body{{end}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req = req.WithContext(ctx)
|
||||
if err := c.applyEditors(ctx, req, reqEditors); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.Client.Do(req)
|
||||
}
|
||||
|
||||
{{range .Bodies}}
|
||||
{{if .IsSupportedByClient -}}
|
||||
func (c *{{ $clientTypeName }}) {{$opid}}{{.Suffix}}(ctx context.Context{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}, body {{$opid}}{{.NameTag}}RequestBody, reqEditors... RequestEditorFn) (*http.Response, error) {
|
||||
req, err := New{{$opid}}Request{{.Suffix}}(c.Server{{genParamNames $pathParams}}{{if $hasParams}}, params{{end}}, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req = req.WithContext(ctx)
|
||||
if err := c.applyEditors(ctx, req, reqEditors); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.Client.Do(req)
|
||||
}
|
||||
{{end -}}{{/* if .IsSupported */}}
|
||||
{{end}}{{/* range .Bodies */}}
|
||||
{{end}}
|
||||
|
||||
{{/* Generate request builders */}}
|
||||
{{range .}}
|
||||
{{$hasParams := .RequiresParamObject -}}
|
||||
{{$pathParams := .PathParams -}}
|
||||
{{$bodyRequired := .BodyRequired -}}
|
||||
{{$opid := .OperationId -}}
|
||||
|
||||
{{range .Bodies}}
|
||||
{{if .IsSupportedByClient -}}
|
||||
// New{{$opid}}Request{{.Suffix}} calls the generic {{$opid}} builder with {{.ContentType}} body
|
||||
func New{{$opid}}Request{{.Suffix}}(server string{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}, body {{$opid}}{{.NameTag}}RequestBody) (*http.Request, error) {
|
||||
var bodyReader io.Reader
|
||||
{{if .IsJSON -}}
|
||||
buf, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bodyReader = bytes.NewReader(buf)
|
||||
{{else if eq .NameTag "Formdata" -}}
|
||||
bodyStr, err := runtime.MarshalForm(body, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bodyReader = strings.NewReader(bodyStr.Encode())
|
||||
{{else if eq .NameTag "Text" -}}
|
||||
bodyReader = strings.NewReader(string(body))
|
||||
{{end -}}
|
||||
return New{{$opid}}RequestWithBody(server{{genParamNames $pathParams}}{{if $hasParams}}, params{{end}}, "{{.ContentType}}", bodyReader)
|
||||
}
|
||||
{{end -}}
|
||||
{{end}}
|
||||
|
||||
// New{{$opid}}Request{{if .HasBody}}WithBody{{end}} generates requests for {{$opid}}{{if .HasBody}} with any type of body{{end}}
|
||||
func New{{$opid}}Request{{if .HasBody}}WithBody{{end}}(server string{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}{{if .HasBody}}, contentType string, body io.Reader{{end}}) (*http.Request, error) {
|
||||
var err error
|
||||
{{range $paramIdx, $param := .PathParams}}
|
||||
var pathParam{{$paramIdx}} string
|
||||
{{if .IsPassThrough}}
|
||||
pathParam{{$paramIdx}} = {{.GoVariableName}}
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
var pathParamBuf{{$paramIdx}} []byte
|
||||
pathParamBuf{{$paramIdx}}, err = json.Marshal({{.GoVariableName}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pathParam{{$paramIdx}} = string(pathParamBuf{{$paramIdx}})
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
pathParam{{$paramIdx}}, err = runtime.StyleParamWithLocation("{{.Style}}", {{.Explode}}, "{{.ParamName}}", runtime.ParamLocationPath, {{.GoVariableName}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
serverURL, err := url.Parse(server)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
operationPath := fmt.Sprintf("{{genParamFmtString .Path}}"{{range $paramIdx, $param := .PathParams}}, pathParam{{$paramIdx}}{{end}})
|
||||
if operationPath[0] == '/' {
|
||||
operationPath = "." + operationPath
|
||||
}
|
||||
|
||||
queryURL, err := serverURL.Parse(operationPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
{{if .QueryParams}}
|
||||
if params != nil {
|
||||
queryValues := queryURL.Query()
|
||||
{{range $paramIdx, $param := .QueryParams}}
|
||||
{{if not .Required}} if params.{{.GoName}} != nil { {{end}}
|
||||
{{if .IsPassThrough}}
|
||||
queryValues.Add("{{.ParamName}}", {{if not .Required}}*{{end}}params.{{.GoName}})
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
if queryParamBuf, err := json.Marshal({{if not .Required}}*{{end}}params.{{.GoName}}); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
queryValues.Add("{{.ParamName}}", string(queryParamBuf))
|
||||
}
|
||||
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
if queryFrag, err := runtime.StyleParamWithLocation("{{.Style}}", {{.Explode}}, "{{.ParamName}}", runtime.ParamLocationQuery, {{if not .Required}}*{{end}}params.{{.GoName}}); err != nil {
|
||||
return nil, err
|
||||
} else if parsed, err := url.ParseQuery(queryFrag); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
for k, v := range parsed {
|
||||
for _, v2 := range v {
|
||||
queryValues.Add(k, v2)
|
||||
}
|
||||
}
|
||||
}
|
||||
{{end}}
|
||||
{{if not .Required}}}{{end}}
|
||||
{{end}}
|
||||
queryURL.RawQuery = queryValues.Encode()
|
||||
}
|
||||
{{end}}{{/* if .QueryParams */}}
|
||||
req, err := http.NewRequest("{{.Method}}", queryURL.String(), {{if .HasBody}}body{{else}}nil{{end}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
{{if .HasBody}}req.Header.Add("Content-Type", contentType){{end}}
|
||||
{{ if .HeaderParams }}
|
||||
if params != nil {
|
||||
{{range $paramIdx, $param := .HeaderParams}}
|
||||
{{if not .Required}} if params.{{.GoName}} != nil { {{end}}
|
||||
var headerParam{{$paramIdx}} string
|
||||
{{if .IsPassThrough}}
|
||||
headerParam{{$paramIdx}} = {{if not .Required}}*{{end}}params.{{.GoName}}
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
var headerParamBuf{{$paramIdx}} []byte
|
||||
headerParamBuf{{$paramIdx}}, err = json.Marshal({{if not .Required}}*{{end}}params.{{.GoName}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
headerParam{{$paramIdx}} = string(headerParamBuf{{$paramIdx}})
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
headerParam{{$paramIdx}}, err = runtime.StyleParamWithLocation("{{.Style}}", {{.Explode}}, "{{.ParamName}}", runtime.ParamLocationHeader, {{if not .Required}}*{{end}}params.{{.GoName}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
{{end}}
|
||||
req.Header.Set("{{.ParamName}}", headerParam{{$paramIdx}})
|
||||
{{if not .Required}}}{{end}}
|
||||
{{end}}
|
||||
}
|
||||
{{- end }}{{/* if .HeaderParams */}}
|
||||
|
||||
{{ if .CookieParams }}
|
||||
if params != nil {
|
||||
{{range $paramIdx, $param := .CookieParams}}
|
||||
{{if not .Required}} if params.{{.GoName}} != nil { {{end}}
|
||||
var cookieParam{{$paramIdx}} string
|
||||
{{if .IsPassThrough}}
|
||||
cookieParam{{$paramIdx}} = {{if not .Required}}*{{end}}params.{{.GoName}}
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
var cookieParamBuf{{$paramIdx}} []byte
|
||||
cookieParamBuf{{$paramIdx}}, err = json.Marshal({{if not .Required}}*{{end}}params.{{.GoName}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cookieParam{{$paramIdx}} = url.QueryEscape(string(cookieParamBuf{{$paramIdx}}))
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
cookieParam{{$paramIdx}}, err = runtime.StyleParamWithLocation("simple", {{.Explode}}, "{{.ParamName}}", runtime.ParamLocationCookie, {{if not .Required}}*{{end}}params.{{.GoName}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
{{end}}
|
||||
cookie{{$paramIdx}} := &http.Cookie{
|
||||
Name:"{{.ParamName}}",
|
||||
Value:cookieParam{{$paramIdx}},
|
||||
}
|
||||
req.AddCookie(cookie{{$paramIdx}})
|
||||
{{if not .Required}}}{{end}}
|
||||
{{ end -}}
|
||||
}
|
||||
{{- end }}{{/* if .CookieParams */}}
|
||||
return req, nil
|
||||
}
|
||||
|
||||
{{end}}{{/* Range */}}
|
||||
|
||||
func (c *{{ $clientTypeName }}) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error {
|
||||
for _, r := range c.RequestEditors {
|
||||
if err := r(ctx, req); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, r := range additionalEditors {
|
||||
if err := r(ctx, req); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
15
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/constants.tmpl
generated
vendored
Normal file
15
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/constants.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{{- if gt (len .SecuritySchemeProviderNames) 0 }}
|
||||
const (
|
||||
{{range $ProviderName := .SecuritySchemeProviderNames}}
|
||||
{{- $ProviderName | sanitizeGoIdentity | ucFirst}}Scopes = "{{$ProviderName}}.Scopes"
|
||||
{{end}}
|
||||
)
|
||||
{{end}}
|
||||
{{range $Enum := .EnumDefinitions}}
|
||||
// Defines values for {{$Enum.TypeName}}.
|
||||
const (
|
||||
{{range $name, $value := $Enum.GetValues}}
|
||||
{{$name}} {{$Enum.TypeName}} = {{$Enum.ValueWrapper}}{{$value}}{{$Enum.ValueWrapper -}}
|
||||
{{end}}
|
||||
)
|
||||
{{end}}
|
||||
7
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/echo/echo-interface.tmpl
generated
vendored
Normal file
7
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/echo/echo-interface.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
// ServerInterface represents all server handlers.
|
||||
type ServerInterface interface {
|
||||
{{range .}}{{.SummaryAsComment }}
|
||||
// ({{.Method}} {{.Path}})
|
||||
{{.OperationId}}(ctx echo.Context{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params {{.OperationId}}Params{{end}}) error
|
||||
{{end}}
|
||||
}
|
||||
33
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/echo/echo-register.tmpl
generated
vendored
Normal file
33
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/echo/echo-register.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
|
||||
|
||||
// This is a simple interface which specifies echo.Route addition functions which
|
||||
// are present on both echo.Echo and echo.Group, since we want to allow using
|
||||
// either of them for path registration
|
||||
type EchoRouter interface {
|
||||
CONNECT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
DELETE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
GET(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
HEAD(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
OPTIONS(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
PATCH(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
POST(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
PUT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
TRACE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
}
|
||||
|
||||
// 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}}(baseURL + "{{.Path | swaggerUriToEchoUri}}", wrapper.{{.OperationId}})
|
||||
{{end}}
|
||||
}
|
||||
131
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/echo/echo-wrappers.tmpl
generated
vendored
Normal file
131
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/echo/echo-wrappers.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
// ServerInterfaceWrapper converts echo contexts to parameters.
|
||||
type ServerInterfaceWrapper struct {
|
||||
Handler ServerInterface
|
||||
}
|
||||
|
||||
{{range .}}{{$opid := .OperationId}}// {{$opid}} converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) {{.OperationId}} (ctx echo.Context) error {
|
||||
var err error
|
||||
{{range .PathParams}}// ------------- Path parameter "{{.ParamName}}" -------------
|
||||
var {{$varName := .GoVariableName}}{{$varName}} {{.TypeDef}}
|
||||
{{if .IsPassThrough}}
|
||||
{{$varName}} = ctx.Param("{{.ParamName}}")
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
err = json.Unmarshal([]byte(ctx.Param("{{.ParamName}}")), &{{$varName}})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Error unmarshaling parameter '{{.ParamName}}' as JSON")
|
||||
}
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindStyledParameterWithOptions("{{.Style}}", "{{.ParamName}}", ctx.Param("{{.ParamName}}"), &{{$varName}}, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: {{.Explode}}, Required: {{.Required}}})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err))
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range .SecurityDefinitions}}
|
||||
ctx.Set({{.ProviderName | sanitizeGoIdentity | ucFirst}}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 (or (or .Required .IsPassThrough) (or .IsJson .IsStyled)) -}}
|
||||
// ------------- {{if .Required}}Required{{else}}Optional{{end}} query parameter "{{.ParamName}}" -------------
|
||||
{{ end }}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindQueryParameter("{{.Style}}", {{.Explode}}, {{.Required}}, "{{.ParamName}}", ctx.QueryParams(), ¶ms.{{.GoName}})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err))
|
||||
}
|
||||
{{else}}
|
||||
if paramValue := ctx.QueryParam("{{.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 {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Error unmarshaling parameter '{{.ParamName}}' as JSON")
|
||||
}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
}{{if .Required}} else {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Query argument {{.ParamName}} is required, but not found"))
|
||||
}{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if .HeaderParams}}
|
||||
headers := ctx.Request().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 {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Expected one value for {{.ParamName}}, got %d", n))
|
||||
}
|
||||
{{if .IsPassThrough}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}valueList[0]
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
err = json.Unmarshal([]byte(valueList[0]), &{{.GoName}})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Error unmarshaling parameter '{{.ParamName}}' as JSON")
|
||||
}
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindStyledParameterWithOptions("{{.Style}}", "{{.ParamName}}", valueList[0], &{{.GoName}}, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: {{.Explode}}, Required: {{.Required}}})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err))
|
||||
}
|
||||
{{end}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}{{.GoName}}
|
||||
} {{if .Required}}else {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Header parameter {{.ParamName}} is required, but not found"))
|
||||
}{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range .CookieParams}}
|
||||
if cookie, err := ctx.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 {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Error unescaping cookie parameter '{{.ParamName}}'")
|
||||
}
|
||||
err = json.Unmarshal([]byte(decoded), &value)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Error unmarshaling parameter '{{.ParamName}}' as JSON")
|
||||
}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
var value {{.TypeDef}}
|
||||
err = runtime.BindStyledParameterWithOptions("simple", "{{.ParamName}}", cookie.Value, &value, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationCookie, Explode: {{.Explode}}, Required: {{.Required}}})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err))
|
||||
}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
}{{if .Required}} else {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Query argument {{.ParamName}} is required, but not found"))
|
||||
}{{end}}
|
||||
|
||||
{{end}}{{/* .CookieParams */}}
|
||||
|
||||
{{end}}{{/* .RequiresParamObject */}}
|
||||
// Invoke the callback with all the unmarshaled arguments
|
||||
err = w.Handler.{{.OperationId}}(ctx{{genParamNames .PathParams}}{{if .RequiresParamObject}}, params{{end}})
|
||||
return err
|
||||
}
|
||||
{{end}}
|
||||
25
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/fiber/fiber-handler.tmpl
generated
vendored
Normal file
25
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/fiber/fiber-handler.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// FiberServerOptions provides options for the Fiber server.
|
||||
type FiberServerOptions struct {
|
||||
BaseURL string
|
||||
Middlewares []MiddlewareFunc
|
||||
}
|
||||
|
||||
// RegisterHandlers creates http.Handler with routing matching OpenAPI spec.
|
||||
func RegisterHandlers(router fiber.Router, si ServerInterface) {
|
||||
RegisterHandlersWithOptions(router, si, FiberServerOptions{})
|
||||
}
|
||||
|
||||
// RegisterHandlersWithOptions creates http.Handler with additional options
|
||||
func RegisterHandlersWithOptions(router fiber.Router, si ServerInterface, options FiberServerOptions) {
|
||||
{{if .}}wrapper := ServerInterfaceWrapper{
|
||||
Handler: si,
|
||||
}
|
||||
|
||||
for _, m := range options.Middlewares {
|
||||
router.Use(fiber.Handler(m))
|
||||
}
|
||||
{{end}}
|
||||
{{range .}}
|
||||
router.{{.Method | lower | title }}(options.BaseURL+"{{.Path | swaggerUriToFiberUri}}", wrapper.{{.OperationId}})
|
||||
{{end}}
|
||||
}
|
||||
7
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/fiber/fiber-interface.tmpl
generated
vendored
Normal file
7
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/fiber/fiber-interface.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
// ServerInterface represents all server handlers.
|
||||
type ServerInterface interface {
|
||||
{{range .}}{{.SummaryAsComment }}
|
||||
// ({{.Method}} {{.Path}})
|
||||
{{.OperationId}}(c *fiber.Ctx{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params {{.OperationId}}Params{{end}}) error
|
||||
{{end}}
|
||||
}
|
||||
169
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/fiber/fiber-middleware.tmpl
generated
vendored
Normal file
169
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/fiber/fiber-middleware.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
// ServerInterfaceWrapper converts contexts to parameters.
|
||||
type ServerInterfaceWrapper struct {
|
||||
Handler ServerInterface
|
||||
}
|
||||
|
||||
type MiddlewareFunc fiber.Handler
|
||||
|
||||
{{range .}}{{$opid := .OperationId}}
|
||||
|
||||
// {{$opid}} operation middleware
|
||||
func (siw *ServerInterfaceWrapper) {{$opid}}(c *fiber.Ctx) error {
|
||||
|
||||
{{if or .RequiresParamObject (gt (len .PathParams) 0) }}
|
||||
var err error
|
||||
{{end}}
|
||||
|
||||
{{range .PathParams}}// ------------- Path parameter "{{.ParamName}}" -------------
|
||||
var {{$varName := .GoVariableName}}{{$varName}} {{.TypeDef}}
|
||||
|
||||
{{if .IsPassThrough}}
|
||||
{{$varName}} = c.Query("{{.ParamName}}")
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
err = json.Unmarshal([]byte(c.Query("{{.ParamName}}")), &{{$varName}})
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Errorf("Error unmarshaling parameter '{{.ParamName}}' as JSON: %w", err).Error())
|
||||
}
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindStyledParameterWithOptions("{{.Style}}", "{{.ParamName}}", c.Params("{{.ParamName}}"), &{{$varName}}, runtime.BindStyledParameterOptions{Explode: {{.Explode}}, Required: {{.Required}}})
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Errorf("Invalid format for parameter {{.ParamName}}: %w", err).Error())
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{end}}
|
||||
|
||||
{{range .SecurityDefinitions}}
|
||||
c.Context().SetUserValue({{.ProviderName | ucFirst}}Scopes, {{toStringArray .Scopes}})
|
||||
{{end}}
|
||||
|
||||
{{if .RequiresParamObject}}
|
||||
// Parameter object where we will unmarshal all parameters from the context
|
||||
var params {{.OperationId}}Params
|
||||
|
||||
{{if .QueryParams}}
|
||||
var query url.Values
|
||||
query, err = url.ParseQuery(string(c.Request().URI().QueryString()))
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Errorf("Invalid format for query string: %w", err).Error())
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{range $paramIdx, $param := .QueryParams}}
|
||||
{{- if (or (or .Required .IsPassThrough) (or .IsJson .IsStyled)) -}}
|
||||
// ------------- {{if .Required}}Required{{else}}Optional{{end}} query parameter "{{.ParamName}}" -------------
|
||||
{{ end }}
|
||||
{{ if (or (or .Required .IsPassThrough) .IsJson) }}
|
||||
if paramValue := c.Query("{{.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 {
|
||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Errorf("Error unmarshaling parameter '{{.ParamName}}' as JSON: %w", err).Error())
|
||||
}
|
||||
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
}{{if .Required}} else {
|
||||
err = fmt.Errorf("Query argument {{.ParamName}} is required, but not found")
|
||||
c.Status(fiber.StatusBadRequest).JSON(err)
|
||||
return err
|
||||
}{{end}}
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindQueryParameter("{{.Style}}", {{.Explode}}, {{.Required}}, "{{.ParamName}}", query, ¶ms.{{.GoName}})
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Errorf("Invalid format for parameter {{.ParamName}}: %w", err).Error())
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if .HeaderParams}}
|
||||
headers := c.GetReqHeaders()
|
||||
|
||||
{{range .HeaderParams}}// ------------- {{if .Required}}Required{{else}}Optional{{end}} header parameter "{{.ParamName}}" -------------
|
||||
if value, found := headers[http.CanonicalHeaderKey("{{.ParamName}}")]; found {
|
||||
var {{.GoName}} {{.TypeDef}}
|
||||
|
||||
{{if .IsPassThrough}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
|
||||
{{if .IsJson}}
|
||||
err = json.Unmarshal([]byte(value), &{{.GoName}})
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Errorf("Error unmarshaling parameter '{{.ParamName}}' as JSON: %w", err).Error())
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindStyledParameterWithOptions("{{.Style}}", "{{.ParamName}}", value, &{{.GoName}}, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: {{.Explode}}, Required: {{.Required}}})
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Errorf("Invalid format for parameter {{.ParamName}}: %w", err).Error())
|
||||
}
|
||||
{{end}}
|
||||
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}{{.GoName}}
|
||||
|
||||
} {{if .Required}}else {
|
||||
err = fmt.Errorf("Header parameter {{.ParamName}} is required, but not found: %w", err)
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}{{end}}
|
||||
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range .CookieParams}}
|
||||
var cookie string
|
||||
|
||||
if cookie = c.Cookies("{{.ParamName}}"); cookie == "" {
|
||||
|
||||
{{- if .IsPassThrough}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}cookie
|
||||
{{end}}
|
||||
|
||||
{{- if .IsJson}}
|
||||
var value {{.TypeDef}}
|
||||
var decoded string
|
||||
decoded, err := url.QueryUnescape(cookie)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Errorf("Error unescaping cookie parameter '{{.ParamName}}': %w", err).Error())
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(decoded), &value)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Errorf("Error unmarshaling parameter '{{.ParamName}}' as JSON: %w", err).Error())
|
||||
}
|
||||
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
|
||||
{{- if .IsStyled}}
|
||||
var value {{.TypeDef}}
|
||||
err = runtime.BindStyledParameterWithOptions("simple", "{{.ParamName}}", cookie, &value, runtime.BindStyledParameterOptions{Explode: {{.Explode}}, Required: {{.Required}}})
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Errorf("Invalid format for parameter {{.ParamName}}: %w", err).Error())
|
||||
}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
|
||||
}
|
||||
|
||||
{{- if .Required}} else {
|
||||
err = fmt.Errorf("Query argument {{.ParamName}} is required, but not found")
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
{{- end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
return siw.Handler.{{.OperationId}}(c{{genParamNames .PathParams}}{{if .RequiresParamObject}}, params{{end}})
|
||||
}
|
||||
{{end}}
|
||||
7
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/gin/gin-interface.tmpl
generated
vendored
Normal file
7
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/gin/gin-interface.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
// ServerInterface represents all server handlers.
|
||||
type ServerInterface interface {
|
||||
{{range .}}{{.SummaryAsComment }}
|
||||
// ({{.Method}} {{.Path}})
|
||||
{{.OperationId}}(c *gin.Context{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params {{.OperationId}}Params{{end}})
|
||||
{{end}}
|
||||
}
|
||||
33
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/gin/gin-register.tmpl
generated
vendored
Normal file
33
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/gin/gin-register.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// GinServerOptions provides options for the Gin server.
|
||||
type GinServerOptions struct {
|
||||
BaseURL string
|
||||
Middlewares []MiddlewareFunc
|
||||
ErrorHandler func(*gin.Context, error, int)
|
||||
}
|
||||
|
||||
// RegisterHandlers creates http.Handler with routing matching OpenAPI spec.
|
||||
func RegisterHandlers(router gin.IRouter, si ServerInterface) {
|
||||
RegisterHandlersWithOptions(router, si, GinServerOptions{})
|
||||
}
|
||||
|
||||
// RegisterHandlersWithOptions creates http.Handler with additional options
|
||||
func RegisterHandlersWithOptions(router gin.IRouter, si ServerInterface, options GinServerOptions) {
|
||||
{{- if . -}}
|
||||
errorHandler := options.ErrorHandler
|
||||
if errorHandler == nil {
|
||||
errorHandler = func(c *gin.Context, err error, statusCode int) {
|
||||
c.JSON(statusCode, gin.H{"msg": err.Error()})
|
||||
}
|
||||
}
|
||||
|
||||
wrapper := ServerInterfaceWrapper{
|
||||
Handler: si,
|
||||
HandlerMiddlewares: options.Middlewares,
|
||||
ErrorHandler: errorHandler,
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{range . -}}
|
||||
router.{{.Method }}(options.BaseURL+"{{.Path | swaggerUriToGinUri }}", wrapper.{{.OperationId}})
|
||||
{{end -}}
|
||||
}
|
||||
186
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/gin/gin-wrappers.tmpl
generated
vendored
Normal file
186
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/gin/gin-wrappers.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
// ServerInterfaceWrapper converts contexts to parameters.
|
||||
type ServerInterfaceWrapper struct {
|
||||
Handler ServerInterface
|
||||
HandlerMiddlewares []MiddlewareFunc
|
||||
ErrorHandler func(*gin.Context, error, int)
|
||||
}
|
||||
|
||||
type MiddlewareFunc func(c *gin.Context)
|
||||
|
||||
{{range .}}{{$opid := .OperationId}}
|
||||
|
||||
// {{$opid}} operation middleware
|
||||
func (siw *ServerInterfaceWrapper) {{$opid}}(c *gin.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}} = c.Query("{{.ParamName}}")
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
err = json.Unmarshal([]byte(c.Query("{{.ParamName}}")), &{{$varName}})
|
||||
if err != nil {
|
||||
siw.ErrorHandler(c, fmt.Errorf("Error unmarshaling parameter '{{.ParamName}}' as JSON"), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindStyledParameterWithOptions("{{.Style}}", "{{.ParamName}}", c.Param("{{.ParamName}}"), &{{$varName}}, runtime.BindStyledParameterOptions{Explode: {{.Explode}}, Required: {{.Required}}})
|
||||
if err != nil {
|
||||
siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter {{.ParamName}}: %w", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{end}}
|
||||
|
||||
{{range .SecurityDefinitions}}
|
||||
c.Set({{.ProviderName | sanitizeGoIdentity | ucFirst}}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 (or (or .Required .IsPassThrough) (or .IsJson .IsStyled)) -}}
|
||||
// ------------- {{if .Required}}Required{{else}}Optional{{end}} query parameter "{{.ParamName}}" -------------
|
||||
{{ end }}
|
||||
{{ if (or (or .Required .IsPassThrough) .IsJson) }}
|
||||
if paramValue := c.Query("{{.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 {
|
||||
siw.ErrorHandler(c, fmt.Errorf("Error unmarshaling parameter '{{.ParamName}}' as JSON: %w", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
}{{if .Required}} else {
|
||||
siw.ErrorHandler(c, fmt.Errorf("Query argument {{.ParamName}} is required, but not found"), http.StatusBadRequest)
|
||||
return
|
||||
}{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindQueryParameter("{{.Style}}", {{.Explode}}, {{.Required}}, "{{.ParamName}}", c.Request.URL.Query(), ¶ms.{{.GoName}})
|
||||
if err != nil {
|
||||
siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter {{.ParamName}}: %w", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if .HeaderParams}}
|
||||
headers := c.Request.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 {
|
||||
siw.ErrorHandler(c, fmt.Errorf("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 {
|
||||
siw.ErrorHandler(c, fmt.Errorf("Error unmarshaling parameter '{{.ParamName}}' as JSON"), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindStyledParameterWithOptions("{{.Style}}", "{{.ParamName}}", valueList[0], &{{.GoName}}, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: {{.Explode}}, Required: {{.Required}}})
|
||||
if err != nil {
|
||||
siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter {{.ParamName}}: %w", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}{{.GoName}}
|
||||
|
||||
} {{if .Required}}else {
|
||||
siw.ErrorHandler(c, fmt.Errorf("Header parameter {{.ParamName}} is required, but not found"), http.StatusBadRequest)
|
||||
return
|
||||
}{{end}}
|
||||
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range .CookieParams}}
|
||||
{
|
||||
var cookie string
|
||||
|
||||
if cookie, err = c.Cookie("{{.ParamName}}"); err == nil {
|
||||
|
||||
{{- if .IsPassThrough}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}cookie
|
||||
{{end}}
|
||||
|
||||
{{- if .IsJson}}
|
||||
var value {{.TypeDef}}
|
||||
var decoded string
|
||||
decoded, err := url.QueryUnescape(cookie)
|
||||
if err != nil {
|
||||
siw.ErrorHandler(c, fmt.Errorf("Error unescaping cookie parameter '{{.ParamName}}'"), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(decoded), &value)
|
||||
if err != nil {
|
||||
siw.ErrorHandler(c, fmt.Errorf("Error unmarshaling parameter '{{.ParamName}}' as JSON"), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
|
||||
{{- if .IsStyled}}
|
||||
var value {{.TypeDef}}
|
||||
err = runtime.BindStyledParameterWithOptions("simple", "{{.ParamName}}", cookie, &value, runtime.BindStyledParameterOptions{Explode: {{.Explode}}, Required: {{.Required}}})
|
||||
if err != nil {
|
||||
siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter {{.ParamName}}: %w", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
|
||||
}
|
||||
|
||||
{{- if .Required}} else {
|
||||
siw.ErrorHandler(c, fmt.Errorf("Query argument {{.ParamName}} is required, but not found"), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
{{- end}}
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
for _, middleware := range siw.HandlerMiddlewares {
|
||||
middleware(c)
|
||||
if c.IsAborted() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
siw.Handler.{{.OperationId}}(c{{genParamNames .PathParams}}{{if .RequiresParamObject}}, params{{end}})
|
||||
}
|
||||
{{end}}
|
||||
7
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/gorilla/gorilla-interface.tmpl
generated
vendored
Normal file
7
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/gorilla/gorilla-interface.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
// 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}}
|
||||
}
|
||||
266
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/gorilla/gorilla-middleware.tmpl
generated
vendored
Normal file
266
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/gorilla/gorilla-middleware.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
// ServerInterfaceWrapper converts contexts to parameters.
|
||||
type ServerInterfaceWrapper struct {
|
||||
Handler ServerInterface
|
||||
HandlerMiddlewares []MiddlewareFunc
|
||||
ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error)
|
||||
}
|
||||
|
||||
type MiddlewareFunc func(http.Handler) http.Handler
|
||||
|
||||
{{range .}}{{$opid := .OperationId}}
|
||||
|
||||
// {{$opid}} operation middleware
|
||||
func (siw *ServerInterfaceWrapper) {{$opid}}(w http.ResponseWriter, r *http.Request) {
|
||||
{{if or .RequiresParamObject (gt (len .PathParams) 0) }}
|
||||
var err error
|
||||
{{end}}
|
||||
|
||||
{{range .PathParams}}// ------------- Path parameter "{{.ParamName}}" -------------
|
||||
var {{$varName := .GoVariableName}}{{$varName}} {{.TypeDef}}
|
||||
|
||||
{{if .IsPassThrough}}
|
||||
{{$varName}} = mux.Vars(r)["{{.ParamName}}"]
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
err = json.Unmarshal([]byte(mux.Vars(r)["{{.ParamName}}"]), &{{$varName}})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &UnmarshalingParamError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindStyledParameterWithOptions("{{.Style}}", "{{.ParamName}}", mux.Vars(r)["{{.ParamName}}"], &{{$varName}}, runtime.BindStyledParameterOptions{Explode: {{.Explode}}, Required: {{.Required}}})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{end}}
|
||||
|
||||
{{if .SecurityDefinitions -}}
|
||||
ctx := r.Context()
|
||||
{{range .SecurityDefinitions}}
|
||||
ctx = context.WithValue(ctx, {{.ProviderName | sanitizeGoIdentity | ucFirst}}Scopes, {{toStringArray .Scopes}})
|
||||
{{end}}
|
||||
r = r.WithContext(ctx)
|
||||
{{end}}
|
||||
|
||||
{{if .RequiresParamObject}}
|
||||
// Parameter object where we will unmarshal all parameters from the context
|
||||
var params {{.OperationId}}Params
|
||||
|
||||
{{range $paramIdx, $param := .QueryParams}}
|
||||
{{- if (or (or .Required .IsPassThrough) (or .IsJson .IsStyled)) -}}
|
||||
// ------------- {{if .Required}}Required{{else}}Optional{{end}} query parameter "{{.ParamName}}" -------------
|
||||
{{ end }}
|
||||
{{ if (or (or .Required .IsPassThrough) .IsJson) }}
|
||||
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 {
|
||||
siw.ErrorHandlerFunc(w, r, &UnmarshalingParamError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
}{{if .Required}} else {
|
||||
siw.ErrorHandlerFunc(w, r, &RequiredParamError{ParamName: "{{.ParamName}}"})
|
||||
return
|
||||
}{{end}}
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindQueryParameter("{{.Style}}", {{.Explode}}, {{.Required}}, "{{.ParamName}}", r.URL.Query(), ¶ms.{{.GoName}})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "{{.ParamName}}", Err: err})
|
||||
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 {
|
||||
siw.ErrorHandlerFunc(w, r, &TooManyValuesForParamError{ParamName: "{{.ParamName}}", Count: n})
|
||||
return
|
||||
}
|
||||
|
||||
{{if .IsPassThrough}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}valueList[0]
|
||||
{{end}}
|
||||
|
||||
{{if .IsJson}}
|
||||
err = json.Unmarshal([]byte(valueList[0]), &{{.GoName}})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &UnmarshalingParamError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindStyledParameterWithOptions("{{.Style}}", "{{.ParamName}}", valueList[0], &{{.GoName}}, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: {{.Explode}}, Required: {{.Required}}})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}{{.GoName}}
|
||||
|
||||
} {{if .Required}}else {
|
||||
err = fmt.Errorf("Header parameter {{.ParamName}} is required, but not found")
|
||||
siw.ErrorHandlerFunc(w, r, &RequiredHeaderError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}{{end}}
|
||||
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range .CookieParams}}
|
||||
{
|
||||
var cookie *http.Cookie
|
||||
|
||||
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 {
|
||||
err = fmt.Errorf("Error unescaping cookie parameter '{{.ParamName}}'")
|
||||
siw.ErrorHandlerFunc(w, r, &UnescapedCookieParamError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(decoded), &value)
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &UnmarshalingParamError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
|
||||
{{- if .IsStyled}}
|
||||
var value {{.TypeDef}}
|
||||
err = runtime.BindStyledParameterWithOptions("simple", "{{.ParamName}}", cookie.Value, &value, runtime.BindStyledParameterOptions{Explode: {{.Explode}}, Required: {{.Required}}})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
|
||||
}
|
||||
|
||||
{{- if .Required}} else {
|
||||
siw.ErrorHandlerFunc(w, r, &RequiredParamError{ParamName: "{{.ParamName}}"})
|
||||
return
|
||||
}
|
||||
{{- end}}
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
siw.Handler.{{.OperationId}}(w, r{{genParamNames .PathParams}}{{if .RequiresParamObject}}, params{{end}})
|
||||
}))
|
||||
|
||||
{{if opts.Compatibility.ApplyGorillaMiddlewareFirstToLast}}
|
||||
for i := len(siw.HandlerMiddlewares) -1; i >= 0; i-- {
|
||||
handler = siw.HandlerMiddlewares[i](handler)
|
||||
}
|
||||
{{else}}
|
||||
for _, middleware := range siw.HandlerMiddlewares {
|
||||
handler = middleware(handler)
|
||||
}
|
||||
{{end}}
|
||||
|
||||
handler.ServeHTTP(w, r)
|
||||
}
|
||||
{{end}}
|
||||
|
||||
type UnescapedCookieParamError struct {
|
||||
ParamName string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *UnescapedCookieParamError) Error() string {
|
||||
return fmt.Sprintf("error unescaping cookie parameter '%s'", e.ParamName)
|
||||
}
|
||||
|
||||
func (e *UnescapedCookieParamError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
type UnmarshalingParamError struct {
|
||||
ParamName string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *UnmarshalingParamError) Error() string {
|
||||
return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error())
|
||||
}
|
||||
|
||||
func (e *UnmarshalingParamError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
type RequiredParamError struct {
|
||||
ParamName string
|
||||
}
|
||||
|
||||
func (e *RequiredParamError) Error() string {
|
||||
return fmt.Sprintf("Query argument %s is required, but not found", e.ParamName)
|
||||
}
|
||||
|
||||
type RequiredHeaderError struct {
|
||||
ParamName string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *RequiredHeaderError) Error() string {
|
||||
return fmt.Sprintf("Header parameter %s is required, but not found", e.ParamName)
|
||||
}
|
||||
|
||||
func (e *RequiredHeaderError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
type InvalidParamFormatError struct {
|
||||
ParamName string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *InvalidParamFormatError) Error() string {
|
||||
return fmt.Sprintf("Invalid format for parameter %s: %s", e.ParamName, e.Err.Error())
|
||||
}
|
||||
|
||||
func (e *InvalidParamFormatError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
type TooManyValuesForParamError struct {
|
||||
ParamName string
|
||||
Count int
|
||||
}
|
||||
|
||||
func (e *TooManyValuesForParamError) Error() string {
|
||||
return fmt.Sprintf("Expected one value for %s, got %d", e.ParamName, e.Count)
|
||||
}
|
||||
49
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/gorilla/gorilla-register.tmpl
generated
vendored
Normal file
49
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/gorilla/gorilla-register.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// Handler creates http.Handler with routing matching OpenAPI spec.
|
||||
func Handler(si ServerInterface) http.Handler {
|
||||
return HandlerWithOptions(si, GorillaServerOptions{})
|
||||
}
|
||||
|
||||
type GorillaServerOptions struct {
|
||||
BaseURL string
|
||||
BaseRouter *mux.Router
|
||||
Middlewares []MiddlewareFunc
|
||||
ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error)
|
||||
}
|
||||
|
||||
// HandlerFromMux creates http.Handler with routing matching OpenAPI spec based on the provided mux.
|
||||
func HandlerFromMux(si ServerInterface, r *mux.Router) http.Handler {
|
||||
return HandlerWithOptions(si, GorillaServerOptions {
|
||||
BaseRouter: r,
|
||||
})
|
||||
}
|
||||
|
||||
func HandlerFromMuxWithBaseURL(si ServerInterface, r *mux.Router, baseURL string) http.Handler {
|
||||
return HandlerWithOptions(si, GorillaServerOptions {
|
||||
BaseURL: baseURL,
|
||||
BaseRouter: r,
|
||||
})
|
||||
}
|
||||
|
||||
// HandlerWithOptions creates http.Handler with additional options
|
||||
func HandlerWithOptions(si ServerInterface, options GorillaServerOptions) http.Handler {
|
||||
r := options.BaseRouter
|
||||
|
||||
if r == nil {
|
||||
r = mux.NewRouter()
|
||||
}
|
||||
if options.ErrorHandlerFunc == nil {
|
||||
options.ErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
{{if .}}wrapper := ServerInterfaceWrapper{
|
||||
Handler: si,
|
||||
HandlerMiddlewares: options.Middlewares,
|
||||
ErrorHandlerFunc: options.ErrorHandlerFunc,
|
||||
}
|
||||
{{end}}
|
||||
{{range .}}
|
||||
r.HandleFunc(options.BaseURL+"{{.Path | swaggerUriToGorillaUri }}", wrapper.{{.OperationId}}).Methods("{{.Method }}")
|
||||
{{end}}
|
||||
return r
|
||||
}
|
||||
50
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/imports.tmpl
generated
vendored
Normal file
50
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/imports.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
{{- if opts.Generate.StdHTTPServer}}//go:build go1.22
|
||||
|
||||
{{- end}}
|
||||
// Package {{.PackageName}} provides primitives to interact with the openapi HTTP API.
|
||||
//
|
||||
// Code generated by {{.ModuleName}} version {{.Version}} DO NOT EDIT.
|
||||
package {{.PackageName}}
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"gopkg.in/yaml.v2"
|
||||
"io"
|
||||
"os"
|
||||
"mime"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/oapi-codegen/runtime"
|
||||
"github.com/oapi-codegen/nullable"
|
||||
strictecho "github.com/oapi-codegen/runtime/strictmiddleware/echo"
|
||||
strictgin "github.com/oapi-codegen/runtime/strictmiddleware/gin"
|
||||
strictiris "github.com/oapi-codegen/runtime/strictmiddleware/iris"
|
||||
strictnethttp "github.com/oapi-codegen/runtime/strictmiddleware/nethttp"
|
||||
openapi_types "github.com/oapi-codegen/runtime/types"
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/kataras/iris/v12"
|
||||
"github.com/kataras/iris/v12/core/router"
|
||||
"github.com/gorilla/mux"
|
||||
{{- range .ExternalImports}}
|
||||
{{ . }}
|
||||
{{- end}}
|
||||
{{- range .AdditionalImports}}
|
||||
{{.Alias}} "{{.Package}}"
|
||||
{{- end}}
|
||||
)
|
||||
84
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/inline.tmpl
generated
vendored
Normal file
84
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/inline.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
// Base64 encoded, gzipped, json marshaled Swagger object
|
||||
var swaggerSpec = []string{
|
||||
{{range .SpecParts}}
|
||||
"{{.}}",{{end}}
|
||||
}
|
||||
|
||||
// GetSwagger returns the content of the embedded swagger specification file
|
||||
// or error if failed to decode
|
||||
func decodeSpec() ([]byte, error) {
|
||||
zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, ""))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error base64 decoding spec: %w", err)
|
||||
}
|
||||
zr, err := gzip.NewReader(bytes.NewReader(zipped))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decompressing spec: %w", err)
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
_, err = buf.ReadFrom(zr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decompressing spec: %w", err)
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
var rawSpec = decodeSpecCached()
|
||||
|
||||
// a naive cached of a decoded swagger spec
|
||||
func decodeSpecCached() func() ([]byte, error) {
|
||||
data, err := decodeSpec()
|
||||
return func() ([]byte, error) {
|
||||
return data, err
|
||||
}
|
||||
}
|
||||
|
||||
// Constructs a synthetic filesystem for resolving external references when loading openapi specifications.
|
||||
func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) {
|
||||
res := make(map[string]func() ([]byte, error))
|
||||
if len(pathToFile) > 0 {
|
||||
res[pathToFile] = rawSpec
|
||||
}
|
||||
{{ range $key, $value := .ImportMapping }}{{- if ne $value.Path "-"}}
|
||||
for rawPath, rawFunc := range {{ $value.Name }}.PathToRawSpec(path.Join(path.Dir(pathToFile), "{{ $key }}")) {
|
||||
if _, ok := res[rawPath]; ok {
|
||||
// it is not possible to compare functions in golang, so always overwrite the old value
|
||||
}
|
||||
res[rawPath] = rawFunc
|
||||
}
|
||||
{{- end }}{{- end }}
|
||||
return res
|
||||
}
|
||||
|
||||
// GetSwagger returns the Swagger specification corresponding to the generated code
|
||||
// in this file. The external references of Swagger specification are resolved.
|
||||
// The logic of resolving external references is tightly connected to "import-mapping" feature.
|
||||
// Externally referenced files must be embedded in the corresponding golang packages.
|
||||
// Urls can be supported but this task was out of the scope.
|
||||
func GetSwagger() (swagger *openapi3.T, err error) {
|
||||
resolvePath := PathToRawSpec("")
|
||||
|
||||
loader := openapi3.NewLoader()
|
||||
loader.IsExternalRefsAllowed = true
|
||||
loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) {
|
||||
pathToFile := url.String()
|
||||
pathToFile = path.Clean(pathToFile)
|
||||
getSpec, ok := resolvePath[pathToFile]
|
||||
if !ok {
|
||||
err1 := fmt.Errorf("path not found: %s", pathToFile)
|
||||
return nil, err1
|
||||
}
|
||||
return getSpec()
|
||||
}
|
||||
var specData []byte
|
||||
specData, err = rawSpec()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
swagger, err = loader.LoadFromData(specData)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
23
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/iris/iris-handler.tmpl
generated
vendored
Normal file
23
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/iris/iris-handler.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// IrisServerOption is the option for iris server
|
||||
type IrisServerOptions struct {
|
||||
BaseURL string
|
||||
Middlewares []MiddlewareFunc
|
||||
}
|
||||
|
||||
// RegisterHandlers creates http.Handler with routing matching OpenAPI spec.
|
||||
func RegisterHandlers(router *iris.Application, si ServerInterface) {
|
||||
RegisterHandlersWithOptions(router, si, IrisServerOptions{})
|
||||
}
|
||||
|
||||
|
||||
// RegisterHandlersWithOptions creates http.Handler with additional options
|
||||
func RegisterHandlersWithOptions(router *iris.Application, si ServerInterface, options IrisServerOptions) {
|
||||
{{if .}}
|
||||
wrapper := ServerInterfaceWrapper{
|
||||
Handler: si,
|
||||
}
|
||||
{{end}}
|
||||
{{range .}}router.{{.Method | lower | title}}(options.BaseURL + "{{.Path | swaggerUriToIrisUri}}", wrapper.{{.OperationId}})
|
||||
{{end}}
|
||||
router.Build()
|
||||
}
|
||||
7
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/iris/iris-interface.tmpl
generated
vendored
Normal file
7
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/iris/iris-interface.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
// ServerInterface represents all server handlers.
|
||||
type ServerInterface interface {
|
||||
{{range .}}{{.SummaryAsComment }}
|
||||
// ({{.Method}} {{.Path}})
|
||||
{{.OperationId}}(ctx iris.Context{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params {{.OperationId}}Params{{end}})
|
||||
{{end}}
|
||||
}
|
||||
161
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/iris/iris-middleware.tmpl
generated
vendored
Normal file
161
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/iris/iris-middleware.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
// ServerInterfaceWrapper converts echo contexts to parameters.
|
||||
type ServerInterfaceWrapper struct {
|
||||
Handler ServerInterface
|
||||
}
|
||||
|
||||
type MiddlewareFunc iris.Handler
|
||||
|
||||
{{range .}}{{$opid := .OperationId}}// {{$opid}} converts iris context to params.
|
||||
func (w *ServerInterfaceWrapper) {{.OperationId}} (ctx iris.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}} = ctx.URLParam("{{.ParamName}}")
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
err = json.Unmarshal([]byte(ctx.URLParam("{{.ParamName}}")), &{{$varName}})
|
||||
if err != nil {
|
||||
ctx.StatusCode(http.StatusBadRequest)
|
||||
ctx.WriteString("Error unmarshaling parameter '{{.ParamName}}' as JSON")
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindStyledParameterWithOptions("{{.Style}}", "{{.ParamName}}", ctx.Params().Get("{{.ParamName}}"), &{{$varName}}, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: {{.Explode}}, Required: {{.Required}}})
|
||||
if err != nil {
|
||||
ctx.StatusCode(http.StatusBadRequest)
|
||||
ctx.Writef("Invalid format for parameter {{.ParamName}}: %s", err)
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range .SecurityDefinitions}}
|
||||
ctx.Set({{.ProviderName | sanitizeGoIdentity | ucFirst}}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 (or (or .Required .IsPassThrough) (or .IsJson .IsStyled)) -}}
|
||||
// ------------- {{if .Required}}Required{{else}}Optional{{end}} query parameter "{{.ParamName}}" -------------
|
||||
{{ end }}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindQueryParameter("{{.Style}}", {{.Explode}}, {{.Required}}, "{{.ParamName}}", ctx.Request().URL.Query(), ¶ms.{{.GoName}})
|
||||
if err != nil {
|
||||
ctx.StatusCode(http.StatusBadRequest)
|
||||
ctx.Writef("Invalid format for parameter {{.ParamName}}: %s", err)
|
||||
return
|
||||
}
|
||||
{{else}}
|
||||
if paramValue := ctx.QueryParam("{{.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 {
|
||||
ctx.StatusCode(http.StatusBadRequest)
|
||||
ctx.WriteString("Error unmarshaling parameter '{{.ParamName}}' as JSON")
|
||||
return
|
||||
}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
}{{if .Required}} else {
|
||||
ctx.StatusCode(http.StatusBadRequest)
|
||||
ctx.WriteString("Query argument {{.ParamName}} is required, but not found")
|
||||
return
|
||||
}{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if .HeaderParams}}
|
||||
headers := ctx.Request().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 {
|
||||
ctx.StatusCode(http.StatusBadRequest)
|
||||
ctx.Writef("Expected one value for {{.ParamName}}, got %d", n)
|
||||
return
|
||||
}
|
||||
{{if .IsPassThrough}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}valueList[0]
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
err = json.Unmarshal([]byte(valueList[0]), &{{.GoName}})
|
||||
if err != nil {
|
||||
ctx.StatusCode(http.StatusBadRequest)
|
||||
ctx.WriteString("Error unmarshaling parameter '{{.ParamName}}' as JSON")
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindStyledParameterWithOptions("{{.Style}}", "{{.ParamName}}", valueList[0], &{{.GoName}}, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: {{.Explode}}, Required: {{.Required}}})
|
||||
if err != nil {
|
||||
ctx.StatusCode(http.StatusBadRequest)
|
||||
ctx.Writef("Invalid format for parameter {{.ParamName}}: %s", err)
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}{{.GoName}}
|
||||
} {{if .Required}}else {
|
||||
ctx.StatusCode(http.StatusBadRequest)
|
||||
ctx.WriteString("Header {{.ParamName}} is required, but not found")
|
||||
return
|
||||
}{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range .CookieParams}}
|
||||
if cookie, err := ctx.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 {
|
||||
ctx.StatusCode(http.StatusBadRequest)
|
||||
ctx.WriteString("Error unescaping cookie parameter '{{.ParamName}}'")
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal([]byte(decoded), &value)
|
||||
if err != nil {
|
||||
ctx.StatusCode(http.StatusBadRequest)
|
||||
ctx.WriteString("Error unmarshaling parameter '{{.ParamName}}' as JSON")
|
||||
return
|
||||
}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
var value {{.TypeDef}}
|
||||
err = runtime.BindStyledParameterWithOptions("simple", "{{.ParamName}}", cookie.Value, &value, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationCookie, Explode: {{.Explode}}, Required: {{.Required}}})
|
||||
if err != nil {
|
||||
ctx.StatusCode(http.StatusBadRequest)
|
||||
ctx.Writef("Invalid format for parameter {{.ParamName}}: %s", err)
|
||||
return
|
||||
}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
}{{if .Required}} else {
|
||||
ctx.StatusCode(http.StatusBadRequest)
|
||||
ctx.WriteString("Cookie {{.ParamName}} is required, but not found")
|
||||
return
|
||||
}{{end}}
|
||||
|
||||
{{end}}{{/* .CookieParams */}}
|
||||
|
||||
{{end}}{{/* .RequiresParamObject */}}
|
||||
// Invoke the callback with all the unmarshaled arguments
|
||||
w.Handler.{{.OperationId}}(ctx{{genParamNames .PathParams}}{{if .RequiresParamObject}}, params{{end}})
|
||||
}
|
||||
{{end}}
|
||||
6
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/param-types.tmpl
generated
vendored
Normal file
6
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/param-types.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{{range .}}{{$opid := .OperationId}}
|
||||
{{range .TypeDefinitions}}
|
||||
// {{.TypeName}} defines parameters for {{$opid}}.
|
||||
type {{.TypeName}} {{if .IsAlias}}={{end}} {{.Schema.TypeDecl}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
11
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/request-bodies.tmpl
generated
vendored
Normal file
11
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/request-bodies.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{{range .}}{{$opid := .OperationId}}
|
||||
{{range .Bodies}}
|
||||
{{if .IsSupported -}}
|
||||
{{$contentType := .ContentType -}}
|
||||
{{with .TypeDef $opid}}
|
||||
// {{.TypeName}} defines body for {{$opid}} for {{$contentType}} ContentType.
|
||||
type {{.TypeName}} {{if .IsAlias}}={{end}} {{.Schema.TypeDecl}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
55
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/stdhttp/std-http-handler.tmpl
generated
vendored
Normal file
55
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/stdhttp/std-http-handler.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
// Handler creates http.Handler with routing matching OpenAPI spec.
|
||||
func Handler(si ServerInterface) http.Handler {
|
||||
return HandlerWithOptions(si, StdHTTPServerOptions{})
|
||||
}
|
||||
|
||||
// ServeMux is an abstraction of http.ServeMux.
|
||||
type ServeMux interface {
|
||||
HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request))
|
||||
ServeHTTP(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
|
||||
type StdHTTPServerOptions struct {
|
||||
BaseURL string
|
||||
BaseRouter ServeMux
|
||||
Middlewares []MiddlewareFunc
|
||||
ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error)
|
||||
}
|
||||
|
||||
// HandlerFromMux creates http.Handler with routing matching OpenAPI spec based on the provided mux.
|
||||
func HandlerFromMux(si ServerInterface, m ServeMux) http.Handler {
|
||||
return HandlerWithOptions(si, StdHTTPServerOptions {
|
||||
BaseRouter: m,
|
||||
})
|
||||
}
|
||||
|
||||
func HandlerFromMuxWithBaseURL(si ServerInterface, m ServeMux, baseURL string) http.Handler {
|
||||
return HandlerWithOptions(si, StdHTTPServerOptions {
|
||||
BaseURL: baseURL,
|
||||
BaseRouter: m,
|
||||
})
|
||||
}
|
||||
|
||||
// HandlerWithOptions creates http.Handler with additional options
|
||||
func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.Handler {
|
||||
m := options.BaseRouter
|
||||
|
||||
if m == nil {
|
||||
m = http.NewServeMux()
|
||||
}
|
||||
if options.ErrorHandlerFunc == nil {
|
||||
options.ErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
{{if .}}
|
||||
wrapper := ServerInterfaceWrapper{
|
||||
Handler: si,
|
||||
HandlerMiddlewares: options.Middlewares,
|
||||
ErrorHandlerFunc: options.ErrorHandlerFunc,
|
||||
}
|
||||
{{end}}
|
||||
{{range .}}m.HandleFunc("{{.Method }} "+options.BaseURL+"{{.Path | swaggerUriToStdHttpUri}}", wrapper.{{.OperationId}})
|
||||
{{end}}
|
||||
return m
|
||||
}
|
||||
7
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/stdhttp/std-http-interface.tmpl
generated
vendored
Normal file
7
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/stdhttp/std-http-interface.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
// 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}}
|
||||
}
|
||||
266
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/stdhttp/std-http-middleware.tmpl
generated
vendored
Normal file
266
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/stdhttp/std-http-middleware.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
// ServerInterfaceWrapper converts contexts to parameters.
|
||||
type ServerInterfaceWrapper struct {
|
||||
Handler ServerInterface
|
||||
HandlerMiddlewares []MiddlewareFunc
|
||||
ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error)
|
||||
}
|
||||
|
||||
type MiddlewareFunc func(http.Handler) http.Handler
|
||||
|
||||
{{range .}}{{$opid := .OperationId}}
|
||||
|
||||
// {{$opid}} operation middleware
|
||||
func (siw *ServerInterfaceWrapper) {{$opid}}(w http.ResponseWriter, r *http.Request) {
|
||||
{{if or .RequiresParamObject (gt (len .PathParams) 0) }}
|
||||
var err error
|
||||
{{end}}
|
||||
|
||||
{{range .PathParams}}// ------------- Path parameter "{{.ParamName}}" -------------
|
||||
var {{$varName := .GoVariableName}}{{$varName}} {{.TypeDef}}
|
||||
|
||||
{{if .IsPassThrough}}
|
||||
{{$varName}} = r.PathValue("{{.ParamName}}")
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
err = json.Unmarshal([]byte(r.PathValue("{{.ParamName}}")), &{{$varName}})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &UnmarshalingParamError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindStyledParameterWithOptions("{{.Style}}", "{{.ParamName}}", r.PathValue("{{.ParamName}}"), &{{$varName}}, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: {{.Explode}}, Required: {{.Required}}})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{end}}
|
||||
|
||||
{{if .SecurityDefinitions -}}
|
||||
ctx := r.Context()
|
||||
{{range .SecurityDefinitions}}
|
||||
ctx = context.WithValue(ctx, {{.ProviderName | sanitizeGoIdentity | ucFirst}}Scopes, {{toStringArray .Scopes}})
|
||||
{{end}}
|
||||
r = r.WithContext(ctx)
|
||||
{{end}}
|
||||
|
||||
{{if .RequiresParamObject}}
|
||||
// Parameter object where we will unmarshal all parameters from the context
|
||||
var params {{.OperationId}}Params
|
||||
|
||||
{{range $paramIdx, $param := .QueryParams}}
|
||||
{{- if (or (or .Required .IsPassThrough) (or .IsJson .IsStyled)) -}}
|
||||
// ------------- {{if .Required}}Required{{else}}Optional{{end}} query parameter "{{.ParamName}}" -------------
|
||||
{{ end }}
|
||||
{{ if (or (or .Required .IsPassThrough) .IsJson) }}
|
||||
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 {
|
||||
siw.ErrorHandlerFunc(w, r, &UnmarshalingParamError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
}{{if .Required}} else {
|
||||
siw.ErrorHandlerFunc(w, r, &RequiredParamError{ParamName: "{{.ParamName}}"})
|
||||
return
|
||||
}{{end}}
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindQueryParameter("{{.Style}}", {{.Explode}}, {{.Required}}, "{{.ParamName}}", r.URL.Query(), ¶ms.{{.GoName}})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "{{.ParamName}}", Err: err})
|
||||
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 {
|
||||
siw.ErrorHandlerFunc(w, r, &TooManyValuesForParamError{ParamName: "{{.ParamName}}", Count: n})
|
||||
return
|
||||
}
|
||||
|
||||
{{if .IsPassThrough}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}valueList[0]
|
||||
{{end}}
|
||||
|
||||
{{if .IsJson}}
|
||||
err = json.Unmarshal([]byte(valueList[0]), &{{.GoName}})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &UnmarshalingParamError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindStyledParameterWithOptions("{{.Style}}", "{{.ParamName}}", valueList[0], &{{.GoName}}, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: {{.Explode}}, Required: {{.Required}}})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}{{.GoName}}
|
||||
|
||||
} {{if .Required}}else {
|
||||
err := fmt.Errorf("Header parameter {{.ParamName}} is required, but not found")
|
||||
siw.ErrorHandlerFunc(w, r, &RequiredHeaderError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}{{end}}
|
||||
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range .CookieParams}}
|
||||
{
|
||||
var cookie *http.Cookie
|
||||
|
||||
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 {
|
||||
err = fmt.Errorf("Error unescaping cookie parameter '{{.ParamName}}'")
|
||||
siw.ErrorHandlerFunc(w, r, &UnescapedCookieParamError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(decoded), &value)
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &UnmarshalingParamError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
|
||||
{{- if .IsStyled}}
|
||||
var value {{.TypeDef}}
|
||||
err = runtime.BindStyledParameterWithOptions("simple", "{{.ParamName}}", cookie.Value, &value, runtime.BindStyledParameterOptions{Explode: {{.Explode}}, Required: {{.Required}}})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "{{.ParamName}}", Err: err})
|
||||
return
|
||||
}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
|
||||
}
|
||||
|
||||
{{- if .Required}} else {
|
||||
siw.ErrorHandlerFunc(w, r, &RequiredParamError{ParamName: "{{.ParamName}}"})
|
||||
return
|
||||
}
|
||||
{{- end}}
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
siw.Handler.{{.OperationId}}(w, r{{genParamNames .PathParams}}{{if .RequiresParamObject}}, params{{end}})
|
||||
}))
|
||||
|
||||
{{if opts.Compatibility.ApplyChiMiddlewareFirstToLast}}
|
||||
for i := len(siw.HandlerMiddlewares) -1; i >= 0; i-- {
|
||||
handler = siw.HandlerMiddlewares[i](handler)
|
||||
}
|
||||
{{else}}
|
||||
for _, middleware := range siw.HandlerMiddlewares {
|
||||
handler = middleware(handler)
|
||||
}
|
||||
{{end}}
|
||||
|
||||
handler.ServeHTTP(w, r)
|
||||
}
|
||||
{{end}}
|
||||
|
||||
type UnescapedCookieParamError struct {
|
||||
ParamName string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *UnescapedCookieParamError) Error() string {
|
||||
return fmt.Sprintf("error unescaping cookie parameter '%s'", e.ParamName)
|
||||
}
|
||||
|
||||
func (e *UnescapedCookieParamError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
type UnmarshalingParamError struct {
|
||||
ParamName string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *UnmarshalingParamError) Error() string {
|
||||
return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error())
|
||||
}
|
||||
|
||||
func (e *UnmarshalingParamError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
type RequiredParamError struct {
|
||||
ParamName string
|
||||
}
|
||||
|
||||
func (e *RequiredParamError) Error() string {
|
||||
return fmt.Sprintf("Query argument %s is required, but not found", e.ParamName)
|
||||
}
|
||||
|
||||
type RequiredHeaderError struct {
|
||||
ParamName string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *RequiredHeaderError) Error() string {
|
||||
return fmt.Sprintf("Header parameter %s is required, but not found", e.ParamName)
|
||||
}
|
||||
|
||||
func (e *RequiredHeaderError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
type InvalidParamFormatError struct {
|
||||
ParamName string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *InvalidParamFormatError) Error() string {
|
||||
return fmt.Sprintf("Invalid format for parameter %s: %s", e.ParamName, e.Err.Error())
|
||||
}
|
||||
|
||||
func (e *InvalidParamFormatError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
type TooManyValuesForParamError struct {
|
||||
ParamName string
|
||||
Count int
|
||||
}
|
||||
|
||||
func (e *TooManyValuesForParamError) Error() string {
|
||||
return fmt.Sprintf("Expected one value for %s, got %d", e.ParamName, e.Count)
|
||||
}
|
||||
97
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/strict/strict-echo.tmpl
generated
vendored
Normal file
97
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/strict/strict-echo.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
type StrictHandlerFunc = strictecho.StrictEchoHandlerFunc
|
||||
type StrictMiddlewareFunc = strictecho.StrictEchoMiddlewareFunc
|
||||
|
||||
func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc) ServerInterface {
|
||||
return &strictHandler{ssi: ssi, middlewares: middlewares}
|
||||
}
|
||||
|
||||
type strictHandler struct {
|
||||
ssi StrictServerInterface
|
||||
middlewares []StrictMiddlewareFunc
|
||||
}
|
||||
|
||||
{{range .}}
|
||||
{{$opid := .OperationId}}
|
||||
// {{$opid}} operation middleware
|
||||
func (sh *strictHandler) {{.OperationId}}(ctx echo.Context{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params {{.OperationId}}Params{{end}}) error {
|
||||
var request {{$opid | ucFirst}}RequestObject
|
||||
|
||||
{{range .PathParams -}}
|
||||
request.{{.GoName}} = {{.GoVariableName}}
|
||||
{{end -}}
|
||||
|
||||
{{if .RequiresParamObject -}}
|
||||
request.Params = params
|
||||
{{end -}}
|
||||
|
||||
{{ if .HasMaskedRequestContentTypes -}}
|
||||
request.ContentType = ctx.Request().Header.Get("Content-Type")
|
||||
{{end -}}
|
||||
|
||||
{{$multipleBodies := gt (len .Bodies) 1 -}}
|
||||
{{range .Bodies -}}
|
||||
{{if $multipleBodies}}if strings.HasPrefix(ctx.Request().Header.Get("Content-Type"), "{{.ContentType}}") { {{end}}
|
||||
{{if .IsJSON -}}
|
||||
var body {{$opid}}{{.NameTag}}RequestBody
|
||||
if err := ctx.Bind(&body); err != nil {
|
||||
return err
|
||||
}
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body
|
||||
{{else if eq .NameTag "Formdata" -}}
|
||||
if form, err := ctx.FormParams(); err == nil {
|
||||
var body {{$opid}}{{.NameTag}}RequestBody
|
||||
if err := runtime.BindForm(&body, form, nil, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
{{else if eq .NameTag "Multipart" -}}
|
||||
{{if eq .ContentType "multipart/form-data" -}}
|
||||
if reader, err := ctx.Request().MultipartReader(); err != nil {
|
||||
return err
|
||||
} else {
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = reader
|
||||
}
|
||||
{{else -}}
|
||||
if _, params, err := mime.ParseMediaType(ctx.Request().Header.Get("Content-Type")); err != nil {
|
||||
return err
|
||||
} else if boundary := params["boundary"]; boundary == "" {
|
||||
return http.ErrMissingBoundary
|
||||
} else {
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = multipart.NewReader(ctx.Request().Body, boundary)
|
||||
}
|
||||
{{end -}}
|
||||
{{else if eq .NameTag "Text" -}}
|
||||
data, err := io.ReadAll(ctx.Request().Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
body := {{$opid}}{{.NameTag}}RequestBody(data)
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body
|
||||
{{else -}}
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = ctx.Request().Body
|
||||
{{end}}{{/* if eq .NameTag "JSON" */ -}}
|
||||
{{if $multipleBodies}}}{{end}}
|
||||
{{end}}{{/* range .Bodies */}}
|
||||
|
||||
handler := func(ctx echo.Context, request interface{}) (interface{}, error){
|
||||
return sh.ssi.{{.OperationId}}(ctx.Request().Context(), request.({{$opid | ucFirst}}RequestObject))
|
||||
}
|
||||
for _, middleware := range sh.middlewares {
|
||||
handler = middleware(handler, "{{.OperationId}}")
|
||||
}
|
||||
|
||||
response, err := handler(ctx, request)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
} else if validResponse, ok := response.({{$opid | ucFirst}}ResponseObject); ok {
|
||||
return validResponse.Visit{{$opid}}Response(ctx.Response())
|
||||
} else if response != nil {
|
||||
return fmt.Errorf("unexpected response type: %T", response)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
{{end}}
|
||||
145
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/strict/strict-fiber-interface.tmpl
generated
vendored
Normal file
145
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/strict/strict-fiber-interface.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
{{range .}}
|
||||
{{$opid := .OperationId -}}
|
||||
type {{$opid | ucFirst}}RequestObject struct {
|
||||
{{range .PathParams -}}
|
||||
{{.GoName | ucFirst}} {{.TypeDef}} {{.JsonTag}}
|
||||
{{end -}}
|
||||
{{if .RequiresParamObject -}}
|
||||
Params {{$opid}}Params
|
||||
{{end -}}
|
||||
{{if .HasMaskedRequestContentTypes -}}
|
||||
ContentType string
|
||||
{{end -}}
|
||||
{{$multipleBodies := gt (len .Bodies) 1 -}}
|
||||
{{range .Bodies -}}
|
||||
{{if $multipleBodies}}{{.NameTag}}{{end}}Body {{if eq .NameTag "Multipart"}}*multipart.Reader{{else if ne .NameTag ""}}*{{$opid}}{{.NameTag}}RequestBody{{else}}io.Reader{{end}}
|
||||
{{end -}}
|
||||
}
|
||||
|
||||
type {{$opid | ucFirst}}ResponseObject interface {
|
||||
Visit{{$opid}}Response(ctx *fiber.Ctx) error
|
||||
}
|
||||
|
||||
{{range .Responses}}
|
||||
{{$statusCode := .StatusCode -}}
|
||||
{{$hasHeaders := ne 0 (len .Headers) -}}
|
||||
{{$fixedStatusCode := .HasFixedStatusCode -}}
|
||||
{{$isRef := .IsRef -}}
|
||||
{{$isExternalRef := .IsExternalRef -}}
|
||||
{{$ref := .Ref | ucFirst -}}
|
||||
{{$headers := .Headers -}}
|
||||
|
||||
{{if (and $hasHeaders (not $isRef)) -}}
|
||||
type {{$opid}}{{$statusCode}}ResponseHeaders struct {
|
||||
{{range .Headers -}}
|
||||
{{.GoName}} {{.Schema.TypeDecl}}
|
||||
{{end -}}
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{range .Contents}}
|
||||
{{$receiverTypeName := printf "%s%s%s%s" $opid $statusCode .NameTagOrContentType "Response"}}
|
||||
{{if and $fixedStatusCode $isRef -}}
|
||||
{{ if and (not $hasHeaders) ($fixedStatusCode) (.IsSupported) (eq .NameTag "Multipart") -}}
|
||||
type {{$receiverTypeName}} {{$ref}}{{.NameTagOrContentType}}Response
|
||||
{{else if $isExternalRef -}}
|
||||
type {{$receiverTypeName}} struct { {{$ref}} }
|
||||
{{else -}}
|
||||
type {{$receiverTypeName}} struct{ {{$ref}}{{.NameTagOrContentType}}Response }
|
||||
{{end}}
|
||||
{{else if and (not $hasHeaders) ($fixedStatusCode) (.IsSupported) -}}
|
||||
type {{$receiverTypeName}} {{if eq .NameTag "Multipart"}}func(writer *multipart.Writer)error{{else if .IsSupported}}{{if and .Schema.IsRef (not .Schema.IsExternalRef)}}={{end}} {{.Schema.TypeDecl}}{{else}}io.Reader{{end}}
|
||||
{{else -}}
|
||||
type {{$receiverTypeName}} struct {
|
||||
Body {{if eq .NameTag "Multipart"}}func(writer *multipart.Writer)error{{else if .IsSupported}}{{.Schema.TypeDecl}}{{else}}io.Reader{{end}}
|
||||
{{if $hasHeaders -}}
|
||||
Headers {{if $isRef}}{{$ref}}{{else}}{{$opid}}{{$statusCode}}{{end}}ResponseHeaders
|
||||
{{end -}}
|
||||
|
||||
{{if not $fixedStatusCode -}}
|
||||
StatusCode int
|
||||
{{end -}}
|
||||
|
||||
{{if not .HasFixedContentType -}}
|
||||
ContentType string
|
||||
{{end -}}
|
||||
|
||||
{{if not .IsSupported -}}
|
||||
ContentLength int64
|
||||
{{end -}}
|
||||
}
|
||||
{{end}}
|
||||
|
||||
func (response {{$receiverTypeName}}) Visit{{$opid}}Response(ctx *fiber.Ctx) error {
|
||||
{{range $headers -}}
|
||||
ctx.Response().Header.Set("{{.Name}}", fmt.Sprint(response.Headers.{{.GoName}}))
|
||||
{{end -}}
|
||||
{{if eq .NameTag "Multipart" -}}
|
||||
writer := multipart.NewWriter(ctx.Response().BodyWriter())
|
||||
{{end -}}
|
||||
ctx.Response().Header.Set("Content-Type", {{if eq .NameTag "Multipart"}}{{if eq .ContentType "multipart/form-data"}}writer.FormDataContentType(){{else}}mime.FormatMediaType("{{.ContentType}}", map[string]string{"boundary": writer.Boundary()}){{end}}{{else if .HasFixedContentType }}"{{.ContentType}}"{{else}}response.ContentType{{end}})
|
||||
{{if not .IsSupported -}}
|
||||
if response.ContentLength != 0 {
|
||||
ctx.Response().Header.Set("Content-Length", fmt.Sprint(response.ContentLength))
|
||||
}
|
||||
{{end -}}
|
||||
ctx.Status({{if $fixedStatusCode}}{{$statusCode}}{{else}}response.StatusCode{{end}})
|
||||
{{$hasBodyVar := or ($hasHeaders) (not $fixedStatusCode) (not .IsSupported)}}
|
||||
{{if .IsJSON }}
|
||||
{{$hasUnionElements := ne 0 (len .Schema.UnionElements)}}
|
||||
return ctx.JSON(&{{if $hasBodyVar}}response.Body{{else}}response{{end}}{{if $hasUnionElements}}.union{{end}})
|
||||
{{else if eq .NameTag "Text" -}}
|
||||
_, err := ctx.WriteString(string({{if $hasBodyVar}}response.Body{{else}}response{{end}}))
|
||||
return err
|
||||
{{else if eq .NameTag "Formdata" -}}
|
||||
if form, err := runtime.MarshalForm({{if $hasBodyVar}}response.Body{{else}}response{{end}}, nil); err != nil {
|
||||
return err
|
||||
} else {
|
||||
_, err := ctx.WriteString(form.Encode())
|
||||
return err
|
||||
}
|
||||
{{else if eq .NameTag "Multipart" -}}
|
||||
defer writer.Close()
|
||||
return {{if $hasBodyVar}}response.Body{{else}}response{{end}}(writer);
|
||||
{{else -}}
|
||||
if closer, ok := response.Body.(io.ReadCloser); ok {
|
||||
defer closer.Close()
|
||||
}
|
||||
_, err := io.Copy(ctx.Response().BodyWriter(), response.Body)
|
||||
return err
|
||||
{{end}}{{/* if eq .NameTag "JSON" */ -}}
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{if eq 0 (len .Contents) -}}
|
||||
{{if and $fixedStatusCode $isRef -}}
|
||||
type {{$opid}}{{$statusCode}}Response {{if not $isExternalRef}}={{end}} {{$ref}}Response
|
||||
{{else -}}
|
||||
type {{$opid}}{{$statusCode}}Response struct {
|
||||
{{if $hasHeaders -}}
|
||||
Headers {{if $isRef}}{{$ref}}{{else}}{{$opid}}{{$statusCode}}{{end}}ResponseHeaders
|
||||
{{end}}
|
||||
{{if not $fixedStatusCode -}}
|
||||
StatusCode int
|
||||
{{end -}}
|
||||
}
|
||||
{{end -}}
|
||||
func (response {{$opid}}{{$statusCode}}Response) Visit{{$opid}}Response(ctx *fiber.Ctx) error {
|
||||
{{range $headers -}}
|
||||
ctx.Response().Header.Set("{{.Name}}", fmt.Sprint(response.Headers.{{.GoName}}))
|
||||
{{end -}}
|
||||
ctx.Status({{if $fixedStatusCode}}{{$statusCode}}{{else}}response.StatusCode{{end}})
|
||||
return nil
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
// StrictServerInterface represents all server handlers.
|
||||
type StrictServerInterface interface {
|
||||
{{range .}}{{.SummaryAsComment }}
|
||||
// ({{.Method}} {{.Path}})
|
||||
{{$opid := .OperationId -}}
|
||||
{{$opid}}(ctx context.Context, request {{$opid | ucFirst}}RequestObject) ({{$opid | ucFirst}}ResponseObject, error)
|
||||
{{end}}{{/* range . */ -}}
|
||||
}
|
||||
90
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/strict/strict-fiber.tmpl
generated
vendored
Normal file
90
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/strict/strict-fiber.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
type StrictHandlerFunc func(ctx *fiber.Ctx, args interface{}) (interface{}, error)
|
||||
|
||||
type StrictMiddlewareFunc func(f StrictHandlerFunc, operationID string) StrictHandlerFunc
|
||||
|
||||
func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc) ServerInterface {
|
||||
return &strictHandler{ssi: ssi, middlewares: middlewares}
|
||||
}
|
||||
|
||||
type strictHandler struct {
|
||||
ssi StrictServerInterface
|
||||
middlewares []StrictMiddlewareFunc
|
||||
}
|
||||
|
||||
{{range .}}
|
||||
{{$opid := .OperationId}}
|
||||
// {{$opid}} operation middleware
|
||||
func (sh *strictHandler) {{.OperationId}}(ctx *fiber.Ctx{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params {{.OperationId}}Params{{end}}) error {
|
||||
var request {{$opid | ucFirst}}RequestObject
|
||||
|
||||
{{range .PathParams -}}
|
||||
{{$varName := .GoVariableName -}}
|
||||
request.{{.GoName}} = {{.GoVariableName}}
|
||||
{{end -}}
|
||||
|
||||
{{if .RequiresParamObject -}}
|
||||
request.Params = params
|
||||
{{end -}}
|
||||
|
||||
{{ if .HasMaskedRequestContentTypes -}}
|
||||
request.ContentType = string(ctx.Request().Header.ContentType())
|
||||
{{end -}}
|
||||
|
||||
{{$multipleBodies := gt (len .Bodies) 1 -}}
|
||||
{{range .Bodies -}}
|
||||
{{if $multipleBodies}}if strings.HasPrefix(string(ctx.Request().Header.ContentType()), "{{.ContentType}}") { {{end}}
|
||||
{{if .IsJSON }}
|
||||
var body {{$opid}}{{.NameTag}}RequestBody
|
||||
if err := ctx.BodyParser(&body); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body
|
||||
{{else if eq .NameTag "Formdata" -}}
|
||||
var body {{$opid}}{{.NameTag}}RequestBody
|
||||
if err := ctx.BodyParser(&body); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body
|
||||
{{else if eq .NameTag "Multipart" -}}
|
||||
{{if eq .ContentType "multipart/form-data" -}}
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = multipart.NewReader(bytes.NewReader(ctx.Request().Body()), string(ctx.Request().Header.MultipartFormBoundary()))
|
||||
{{else -}}
|
||||
if _, params, err := mime.ParseMediaType(string(ctx.Request().Header.ContentType())); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
} else if boundary := params["boundary"]; boundary == "" {
|
||||
return fiber.NewError(fiber.StatusBadRequest, http.ErrMissingBoundary.Error())
|
||||
} else {
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = multipart.NewReader(bytes.NewReader(ctx.Request().Body()), boundary)
|
||||
}
|
||||
{{end -}}
|
||||
{{else if eq .NameTag "Text" -}}
|
||||
data := ctx.Request().Body()
|
||||
body := {{$opid}}{{.NameTag}}RequestBody(data)
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body
|
||||
{{else -}}
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = bytes.NewReader(ctx.Request().Body())
|
||||
{{end}}{{/* if eq .NameTag "JSON" */ -}}
|
||||
{{if $multipleBodies}}}{{end}}
|
||||
{{end}}{{/* range .Bodies */}}
|
||||
|
||||
handler := func(ctx *fiber.Ctx, request interface{}) (interface{}, error) {
|
||||
return sh.ssi.{{.OperationId}}(ctx.UserContext(), request.({{$opid | ucFirst}}RequestObject))
|
||||
}
|
||||
for _, middleware := range sh.middlewares {
|
||||
handler = middleware(handler, "{{.OperationId}}")
|
||||
}
|
||||
|
||||
response, err := handler(ctx, request)
|
||||
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
} else if validResponse, ok := response.({{$opid | ucFirst}}ResponseObject); ok {
|
||||
if err := validResponse.Visit{{$opid}}Response(ctx); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
} else if response != nil {
|
||||
return fmt.Errorf("unexpected response type: %T", response)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
{{end}}
|
||||
106
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/strict/strict-gin.tmpl
generated
vendored
Normal file
106
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/strict/strict-gin.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
type StrictHandlerFunc = strictgin.StrictGinHandlerFunc
|
||||
type StrictMiddlewareFunc = strictgin.StrictGinMiddlewareFunc
|
||||
|
||||
func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc) ServerInterface {
|
||||
return &strictHandler{ssi: ssi, middlewares: middlewares}
|
||||
}
|
||||
|
||||
type strictHandler struct {
|
||||
ssi StrictServerInterface
|
||||
middlewares []StrictMiddlewareFunc
|
||||
}
|
||||
|
||||
{{range .}}
|
||||
{{$opid := .OperationId}}
|
||||
// {{$opid}} operation middleware
|
||||
func (sh *strictHandler) {{.OperationId}}(ctx *gin.Context{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params {{.OperationId}}Params{{end}}) {
|
||||
var request {{$opid | ucFirst}}RequestObject
|
||||
|
||||
{{range .PathParams -}}
|
||||
request.{{.GoName}} = {{.GoVariableName}}
|
||||
{{end -}}
|
||||
|
||||
{{if .RequiresParamObject -}}
|
||||
request.Params = params
|
||||
{{end -}}
|
||||
|
||||
{{ if .HasMaskedRequestContentTypes -}}
|
||||
request.ContentType = ctx.ContentType()
|
||||
{{end -}}
|
||||
|
||||
{{$multipleBodies := gt (len .Bodies) 1 -}}
|
||||
{{range .Bodies -}}
|
||||
{{if $multipleBodies}}if strings.HasPrefix(ctx.GetHeader("Content-Type"), "{{.ContentType}}") { {{end}}
|
||||
{{if .IsJSON }}
|
||||
var body {{$opid}}{{.NameTag}}RequestBody
|
||||
if err := ctx.ShouldBindJSON(&body); err != nil {
|
||||
ctx.Status(http.StatusBadRequest)
|
||||
ctx.Error(err)
|
||||
return
|
||||
}
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body
|
||||
{{else if eq .NameTag "Formdata" -}}
|
||||
if err := ctx.Request.ParseForm(); err != nil {
|
||||
ctx.Error(err)
|
||||
return
|
||||
}
|
||||
var body {{$opid}}{{.NameTag}}RequestBody
|
||||
if err := runtime.BindForm(&body, ctx.Request.Form, nil, nil); err != nil {
|
||||
ctx.Error(err)
|
||||
return
|
||||
}
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body
|
||||
{{else if eq .NameTag "Multipart" -}}
|
||||
{{if eq .ContentType "multipart/form-data" -}}
|
||||
if reader, err := ctx.Request.MultipartReader(); err == nil {
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = reader
|
||||
} else {
|
||||
ctx.Error(err)
|
||||
return
|
||||
}
|
||||
{{else -}}
|
||||
if _, params, err := mime.ParseMediaType(ctx.Request.Header.Get("Content-Type")); err != nil {
|
||||
ctx.Error(err)
|
||||
return
|
||||
} else if boundary := params["boundary"]; boundary == "" {
|
||||
ctx.Error(http.ErrMissingBoundary)
|
||||
return
|
||||
} else {
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = multipart.NewReader(ctx.Request.Body, boundary)
|
||||
}
|
||||
{{end -}}
|
||||
{{else if eq .NameTag "Text" -}}
|
||||
data, err := io.ReadAll(ctx.Request.Body)
|
||||
if err != nil {
|
||||
ctx.Error(err)
|
||||
return
|
||||
}
|
||||
body := {{$opid}}{{.NameTag}}RequestBody(data)
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body
|
||||
{{else -}}
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = ctx.Request.Body
|
||||
{{end}}{{/* if eq .NameTag "JSON" */ -}}
|
||||
{{if $multipleBodies}}}{{end}}
|
||||
{{end}}{{/* range .Bodies */}}
|
||||
|
||||
handler := func(ctx *gin.Context, request interface{}) (interface{}, error) {
|
||||
return sh.ssi.{{.OperationId}}(ctx, request.({{$opid | ucFirst}}RequestObject))
|
||||
}
|
||||
for _, middleware := range sh.middlewares {
|
||||
handler = middleware(handler, "{{.OperationId}}")
|
||||
}
|
||||
|
||||
response, err := handler(ctx, request)
|
||||
|
||||
if err != nil {
|
||||
ctx.Error(err)
|
||||
ctx.Status(http.StatusInternalServerError)
|
||||
} else if validResponse, ok := response.({{$opid | ucFirst}}ResponseObject); ok {
|
||||
if err := validResponse.Visit{{$opid}}Response(ctx.Writer); err != nil {
|
||||
ctx.Error(err)
|
||||
}
|
||||
} else if response != nil {
|
||||
ctx.Error(fmt.Errorf("unexpected response type: %T", response))
|
||||
}
|
||||
}
|
||||
{{end}}
|
||||
121
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/strict/strict-http.tmpl
generated
vendored
Normal file
121
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/strict/strict-http.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
type StrictHandlerFunc = strictnethttp.StrictHTTPHandlerFunc
|
||||
type StrictMiddlewareFunc = strictnethttp.StrictHTTPMiddlewareFunc
|
||||
|
||||
type StrictHTTPServerOptions struct {
|
||||
RequestErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error)
|
||||
ResponseErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error)
|
||||
}
|
||||
|
||||
func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc) ServerInterface {
|
||||
return &strictHandler{ssi: ssi, middlewares: middlewares, options: StrictHTTPServerOptions {
|
||||
RequestErrorHandlerFunc: func(w http.ResponseWriter, r *http.Request, err error) {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
},
|
||||
ResponseErrorHandlerFunc: func(w http.ResponseWriter, r *http.Request, err error) {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
},
|
||||
}}
|
||||
}
|
||||
|
||||
func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface {
|
||||
return &strictHandler{ssi: ssi, middlewares: middlewares, options: options}
|
||||
}
|
||||
|
||||
type strictHandler struct {
|
||||
ssi StrictServerInterface
|
||||
middlewares []StrictMiddlewareFunc
|
||||
options StrictHTTPServerOptions
|
||||
}
|
||||
|
||||
{{range .}}
|
||||
{{$opid := .OperationId}}
|
||||
// {{$opid}} operation middleware
|
||||
func (sh *strictHandler) {{.OperationId}}(w http.ResponseWriter, r *http.Request{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params {{.OperationId}}Params{{end}}) {
|
||||
var request {{$opid | ucFirst}}RequestObject
|
||||
|
||||
{{range .PathParams -}}
|
||||
request.{{.GoName}} = {{.GoVariableName}}
|
||||
{{end -}}
|
||||
|
||||
{{if .RequiresParamObject -}}
|
||||
request.Params = params
|
||||
{{end -}}
|
||||
|
||||
{{ if .HasMaskedRequestContentTypes -}}
|
||||
request.ContentType = r.Header.Get("Content-Type")
|
||||
{{end -}}
|
||||
|
||||
{{$multipleBodies := gt (len .Bodies) 1 -}}
|
||||
{{range .Bodies -}}
|
||||
{{if $multipleBodies}}if strings.HasPrefix(r.Header.Get("Content-Type"), "{{.ContentType}}") { {{end}}
|
||||
{{if .IsJSON }}
|
||||
var body {{$opid}}{{.NameTag}}RequestBody
|
||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||
sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err))
|
||||
return
|
||||
}
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body
|
||||
{{else if eq .NameTag "Formdata" -}}
|
||||
if err := r.ParseForm(); err != nil {
|
||||
sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode formdata: %w", err))
|
||||
return
|
||||
}
|
||||
var body {{$opid}}{{.NameTag}}RequestBody
|
||||
if err := runtime.BindForm(&body, r.Form, nil, nil); err != nil {
|
||||
sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't bind formdata: %w", err))
|
||||
return
|
||||
}
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body
|
||||
{{else if eq .NameTag "Multipart" -}}
|
||||
{{if eq .ContentType "multipart/form-data" -}}
|
||||
if reader, err := r.MultipartReader(); err != nil {
|
||||
sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode multipart body: %w", err))
|
||||
return
|
||||
} else {
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = reader
|
||||
}
|
||||
{{else -}}
|
||||
if _, params, err := mime.ParseMediaType(r.Header.Get("Content-Type")); err != nil {
|
||||
sh.options.RequestErrorHandlerFunc(w, r, err)
|
||||
return
|
||||
} else if boundary := params["boundary"]; boundary == "" {
|
||||
sh.options.RequestErrorHandlerFunc(w, r, http.ErrMissingBoundary)
|
||||
return
|
||||
} else {
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = multipart.NewReader(r.Body, boundary)
|
||||
}
|
||||
{{end -}}
|
||||
{{else if eq .NameTag "Text" -}}
|
||||
data, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't read body: %w", err))
|
||||
return
|
||||
}
|
||||
body := {{$opid}}{{.NameTag}}RequestBody(data)
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body
|
||||
{{else -}}
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = r.Body
|
||||
{{end}}{{/* if eq .NameTag "JSON" */ -}}
|
||||
{{if $multipleBodies}}}{{end}}
|
||||
{{end}}{{/* range .Bodies */}}
|
||||
|
||||
handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
|
||||
return sh.ssi.{{.OperationId}}(ctx, request.({{$opid | ucFirst}}RequestObject))
|
||||
}
|
||||
for _, middleware := range sh.middlewares {
|
||||
handler = middleware(handler, "{{.OperationId}}")
|
||||
}
|
||||
|
||||
response, err := handler(r.Context(), w, r, request)
|
||||
|
||||
if err != nil {
|
||||
sh.options.ResponseErrorHandlerFunc(w, r, err)
|
||||
} else if validResponse, ok := response.({{$opid | ucFirst}}ResponseObject); ok {
|
||||
if err := validResponse.Visit{{$opid}}Response(w); err != nil {
|
||||
sh.options.ResponseErrorHandlerFunc(w, r, err)
|
||||
}
|
||||
} else if response != nil {
|
||||
sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response))
|
||||
}
|
||||
}
|
||||
{{end}}
|
||||
145
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/strict/strict-interface.tmpl
generated
vendored
Normal file
145
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/strict/strict-interface.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
{{range .}}
|
||||
{{$opid := .OperationId -}}
|
||||
type {{$opid | ucFirst}}RequestObject struct {
|
||||
{{range .PathParams -}}
|
||||
{{.GoName | ucFirst}} {{.TypeDef}} {{.JsonTag}}
|
||||
{{end -}}
|
||||
{{if .RequiresParamObject -}}
|
||||
Params {{$opid}}Params
|
||||
{{end -}}
|
||||
{{if .HasMaskedRequestContentTypes -}}
|
||||
ContentType string
|
||||
{{end -}}
|
||||
{{$multipleBodies := gt (len .Bodies) 1 -}}
|
||||
{{range .Bodies -}}
|
||||
{{if $multipleBodies}}{{.NameTag}}{{end}}Body {{if eq .NameTag "Multipart"}}*multipart.Reader{{else if ne .NameTag ""}}*{{$opid}}{{.NameTag}}RequestBody{{else}}io.Reader{{end}}
|
||||
{{end -}}
|
||||
}
|
||||
|
||||
type {{$opid | ucFirst}}ResponseObject interface {
|
||||
Visit{{$opid}}Response(w http.ResponseWriter) error
|
||||
}
|
||||
|
||||
{{range .Responses}}
|
||||
{{$statusCode := .StatusCode -}}
|
||||
{{$hasHeaders := ne 0 (len .Headers) -}}
|
||||
{{$fixedStatusCode := .HasFixedStatusCode -}}
|
||||
{{$isRef := .IsRef -}}
|
||||
{{$isExternalRef := .IsExternalRef -}}
|
||||
{{$ref := .Ref | ucFirstWithPkgName -}}
|
||||
{{$headers := .Headers -}}
|
||||
|
||||
{{if (and $hasHeaders (not $isRef)) -}}
|
||||
type {{$opid}}{{$statusCode}}ResponseHeaders struct {
|
||||
{{range .Headers -}}
|
||||
{{.GoName}} {{.Schema.TypeDecl}}
|
||||
{{end -}}
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{range .Contents}}
|
||||
{{$receiverTypeName := printf "%s%s%s%s" $opid $statusCode .NameTagOrContentType "Response"}}
|
||||
{{if and $fixedStatusCode $isRef -}}
|
||||
{{ if and (not $hasHeaders) ($fixedStatusCode) (.IsSupported) (eq .NameTag "Multipart") -}}
|
||||
type {{$receiverTypeName}} {{$ref}}{{.NameTagOrContentType}}Response
|
||||
{{else if $isExternalRef -}}
|
||||
type {{$receiverTypeName}} struct { {{$ref}} }
|
||||
{{else -}}
|
||||
type {{$receiverTypeName}} struct{ {{$ref}}{{.NameTagOrContentType}}Response }
|
||||
{{end}}
|
||||
{{else if and (not $hasHeaders) ($fixedStatusCode) (.IsSupported) -}}
|
||||
type {{$receiverTypeName}} {{if eq .NameTag "Multipart"}}func(writer *multipart.Writer)error{{else if .IsSupported}}{{if and .Schema.IsRef (not .Schema.IsExternalRef)}}={{end}} {{.Schema.TypeDecl}}{{else}}io.Reader{{end}}
|
||||
{{else -}}
|
||||
type {{$receiverTypeName}} struct {
|
||||
Body {{if eq .NameTag "Multipart"}}func(writer *multipart.Writer)error{{else if .IsSupported}}{{.Schema.TypeDecl}}{{else}}io.Reader{{end}}
|
||||
{{if $hasHeaders -}}
|
||||
Headers {{if $isRef}}{{$ref}}{{else}}{{$opid}}{{$statusCode}}{{end}}ResponseHeaders
|
||||
{{end -}}
|
||||
|
||||
{{if not $fixedStatusCode -}}
|
||||
StatusCode int
|
||||
{{end -}}
|
||||
|
||||
{{if not .HasFixedContentType -}}
|
||||
ContentType string
|
||||
{{end -}}
|
||||
|
||||
{{if not .IsSupported -}}
|
||||
ContentLength int64
|
||||
{{end -}}
|
||||
}
|
||||
{{end}}
|
||||
|
||||
func (response {{$receiverTypeName}}) Visit{{$opid}}Response(w http.ResponseWriter) error {
|
||||
{{if eq .NameTag "Multipart" -}}
|
||||
writer := multipart.NewWriter(w)
|
||||
{{end -}}
|
||||
w.Header().Set("Content-Type", {{if eq .NameTag "Multipart"}}{{if eq .ContentType "multipart/form-data"}}writer.FormDataContentType(){{else}}mime.FormatMediaType("{{.ContentType}}", map[string]string{"boundary": writer.Boundary()}){{end}}{{else if .HasFixedContentType }}"{{.ContentType}}"{{else}}response.ContentType{{end}})
|
||||
{{if not .IsSupported -}}
|
||||
if response.ContentLength != 0 {
|
||||
w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength))
|
||||
}
|
||||
{{end -}}
|
||||
{{range $headers -}}
|
||||
w.Header().Set("{{.Name}}", fmt.Sprint(response.Headers.{{.GoName}}))
|
||||
{{end -}}
|
||||
w.WriteHeader({{if $fixedStatusCode}}{{$statusCode}}{{else}}response.StatusCode{{end}})
|
||||
{{$hasBodyVar := or ($hasHeaders) (not $fixedStatusCode) (not .IsSupported)}}
|
||||
{{if .IsJSON -}}
|
||||
{{$hasUnionElements := ne 0 (len .Schema.UnionElements)}}
|
||||
return json.NewEncoder(w).Encode(response{{if $hasBodyVar}}.Body{{end}}{{if $hasUnionElements}}.union{{end}})
|
||||
{{else if eq .NameTag "Text" -}}
|
||||
_, err := w.Write([]byte({{if $hasBodyVar}}response.Body{{else}}response{{end}}))
|
||||
return err
|
||||
{{else if eq .NameTag "Formdata" -}}
|
||||
if form, err := runtime.MarshalForm({{if $hasBodyVar}}response.Body{{else}}response{{end}}, nil); err != nil {
|
||||
return err
|
||||
} else {
|
||||
_, err := w.Write([]byte(form.Encode()))
|
||||
return err
|
||||
}
|
||||
{{else if eq .NameTag "Multipart" -}}
|
||||
defer writer.Close()
|
||||
return {{if $hasBodyVar}}response.Body{{else}}response{{end}}(writer);
|
||||
{{else -}}
|
||||
if closer, ok := response.Body.(io.ReadCloser); ok {
|
||||
defer closer.Close()
|
||||
}
|
||||
_, err := io.Copy(w, response.Body)
|
||||
return err
|
||||
{{end}}{{/* if eq .NameTag "JSON" */ -}}
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{if eq 0 (len .Contents) -}}
|
||||
{{if and $fixedStatusCode $isRef -}}
|
||||
type {{$opid}}{{$statusCode}}Response {{if not $isExternalRef}}={{end}} {{$ref}}Response
|
||||
{{else -}}
|
||||
type {{$opid}}{{$statusCode}}Response struct {
|
||||
{{if $hasHeaders -}}
|
||||
Headers {{if $isRef}}{{$ref}}{{else}}{{$opid}}{{$statusCode}}{{end}}ResponseHeaders
|
||||
{{end}}
|
||||
{{if not $fixedStatusCode -}}
|
||||
StatusCode int
|
||||
{{end -}}
|
||||
}
|
||||
{{end -}}
|
||||
func (response {{$opid}}{{$statusCode}}Response) Visit{{$opid}}Response(w http.ResponseWriter) error {
|
||||
{{range $headers -}}
|
||||
w.Header().Set("{{.Name}}", fmt.Sprint(response.Headers.{{.GoName}}))
|
||||
{{end -}}
|
||||
w.WriteHeader({{if $fixedStatusCode}}{{$statusCode}}{{else}}response.StatusCode{{end}})
|
||||
return nil
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
// StrictServerInterface represents all server handlers.
|
||||
type StrictServerInterface interface {
|
||||
{{range .}}{{.SummaryAsComment }}
|
||||
// ({{.Method}} {{.Path}})
|
||||
{{$opid := .OperationId -}}
|
||||
{{$opid}}(ctx context.Context, request {{$opid | ucFirst}}RequestObject) ({{$opid | ucFirst}}ResponseObject, error)
|
||||
{{end}}{{/* range . */ -}}
|
||||
}
|
||||
147
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/strict/strict-iris-interface.tmpl
generated
vendored
Normal file
147
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/strict/strict-iris-interface.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
{{range .}}
|
||||
{{$opid := .OperationId -}}
|
||||
type {{$opid | ucFirst}}RequestObject struct {
|
||||
{{range .PathParams -}}
|
||||
{{.GoName | ucFirst}} {{.TypeDef}} {{.JsonTag}}
|
||||
{{end -}}
|
||||
{{if .RequiresParamObject -}}
|
||||
Params {{$opid}}Params
|
||||
{{end -}}
|
||||
{{if .HasMaskedRequestContentTypes -}}
|
||||
ContentType string
|
||||
{{end -}}
|
||||
{{$multipleBodies := gt (len .Bodies) 1 -}}
|
||||
{{range .Bodies -}}
|
||||
{{if $multipleBodies}}{{.NameTag}}{{end}}Body {{if eq .NameTag "Multipart"}}*multipart.Reader{{else if ne .NameTag ""}}*{{$opid}}{{.NameTag}}RequestBody{{else}}io.Reader{{end}}
|
||||
{{end -}}
|
||||
}
|
||||
|
||||
type {{$opid | ucFirst}}ResponseObject interface {
|
||||
Visit{{$opid}}Response(ctx iris.Context) error
|
||||
}
|
||||
|
||||
{{range .Responses}}
|
||||
{{$statusCode := .StatusCode -}}
|
||||
{{$hasHeaders := ne 0 (len .Headers) -}}
|
||||
{{$fixedStatusCode := .HasFixedStatusCode -}}
|
||||
{{$isRef := .IsRef -}}
|
||||
{{$isExternalRef := .IsExternalRef -}}
|
||||
{{$ref := .Ref | ucFirstWithPkgName -}}
|
||||
{{$headers := .Headers -}}
|
||||
|
||||
{{if (and $hasHeaders (not $isRef)) -}}
|
||||
type {{$opid}}{{$statusCode}}ResponseHeaders struct {
|
||||
{{range .Headers -}}
|
||||
{{.GoName}} {{.Schema.TypeDecl}}
|
||||
{{end -}}
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{range .Contents}}
|
||||
{{$receiverTypeName := printf "%s%s%s%s" $opid $statusCode .NameTagOrContentType "Response"}}
|
||||
{{if eq .NameTag "Text" -}}
|
||||
type {{$receiverTypeName}} string
|
||||
{{else if and $fixedStatusCode $isRef -}}
|
||||
{{ if and (not $hasHeaders) ($fixedStatusCode) (.IsSupported) (eq .NameTag "Multipart") -}}
|
||||
type {{$receiverTypeName}} {{$ref}}{{.NameTagOrContentType}}Response
|
||||
{{else if $isExternalRef -}}
|
||||
type {{$receiverTypeName}} struct { {{$ref}} }
|
||||
{{else -}}
|
||||
type {{$receiverTypeName}} struct{ {{$ref}}{{.NameTagOrContentType}}Response }
|
||||
{{end}}
|
||||
{{else if and (not $hasHeaders) ($fixedStatusCode) (.IsSupported) -}}
|
||||
type {{$receiverTypeName}} {{if eq .NameTag "Multipart"}}func(writer *multipart.Writer)error{{else if .IsSupported}}{{if and .Schema.IsRef (not .Schema.IsExternalRef)}}={{end}} {{.Schema.TypeDecl}}{{else}}io.Reader{{end}}
|
||||
{{else -}}
|
||||
type {{$receiverTypeName}} struct {
|
||||
Body {{if eq .NameTag "Multipart"}}func(writer *multipart.Writer)error{{else if .IsSupported}}{{.Schema.TypeDecl}}{{else}}io.Reader{{end}}
|
||||
{{if $hasHeaders -}}
|
||||
Headers {{if $isRef}}{{$ref}}{{else}}{{$opid}}{{$statusCode}}{{end}}ResponseHeaders
|
||||
{{end -}}
|
||||
|
||||
{{if not $fixedStatusCode -}}
|
||||
StatusCode int
|
||||
{{end -}}
|
||||
|
||||
{{if not .HasFixedContentType -}}
|
||||
ContentType string
|
||||
{{end -}}
|
||||
|
||||
{{if not .IsSupported -}}
|
||||
ContentLength int64
|
||||
{{end -}}
|
||||
}
|
||||
{{end}}
|
||||
|
||||
func (response {{$receiverTypeName}}) Visit{{$opid}}Response(ctx iris.Context) error {
|
||||
{{range $headers -}}
|
||||
ctx.ResponseWriter().Header().Set("{{.Name}}", fmt.Sprint(response.Headers.{{.GoName}}))
|
||||
{{end -}}
|
||||
{{if eq .NameTag "Multipart" -}}
|
||||
writer := multipart.NewWriter(ctx.ResponseWriter())
|
||||
{{end -}}
|
||||
ctx.ResponseWriter().Header().Set("Content-Type", {{if eq .NameTag "Multipart"}}{{if eq .ContentType "multipart/form-data"}}writer.FormDataContentType(){{else}}mime.FormatMediaType("{{.ContentType}}", map[string]string{"boundary": writer.Boundary()}){{end}}{{else if .HasFixedContentType }}"{{.ContentType}}"{{else}}response.ContentType{{end}})
|
||||
{{if not .IsSupported -}}
|
||||
if response.ContentLength != 0 {
|
||||
ctx.ResponseWriter().Header().Set("Content-Length", fmt.Sprint(response.ContentLength))
|
||||
}
|
||||
{{end -}}
|
||||
ctx.StatusCode({{if $fixedStatusCode}}{{$statusCode}}{{else}}response.StatusCode{{end}})
|
||||
{{$hasBodyVar := or ($hasHeaders) (not $fixedStatusCode) (not .IsSupported)}}
|
||||
{{if .IsJSON -}}
|
||||
{{$hasUnionElements := ne 0 (len .Schema.UnionElements)}}
|
||||
return ctx.JSON(&{{if $hasBodyVar}}response.Body{{else}}response{{end}}{{if $hasUnionElements}}.union{{end}})
|
||||
{{else if eq .NameTag "Text" -}}
|
||||
_, err := ctx.WriteString(string({{if $hasBodyVar}}response.Body{{else}}response{{end}}))
|
||||
return err
|
||||
{{else if eq .NameTag "Formdata" -}}
|
||||
if form, err := runtime.MarshalForm({{if $hasBodyVar}}response.Body{{else}}response{{end}}, nil); err != nil {
|
||||
return err
|
||||
} else {
|
||||
_, err := ctx.WriteString(form.Encode())
|
||||
return err
|
||||
}
|
||||
{{else if eq .NameTag "Multipart" -}}
|
||||
defer writer.Close()
|
||||
return {{if $hasBodyVar}}response.Body{{else}}response{{end}}(writer);
|
||||
{{else -}}
|
||||
if closer, ok := response.Body.(io.ReadCloser); ok {
|
||||
defer closer.Close()
|
||||
}
|
||||
_, err := io.Copy(ctx.ResponseWriter(), response.Body)
|
||||
return err
|
||||
{{end}}{{/* if eq .NameTag "JSON" */ -}}
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{if eq 0 (len .Contents) -}}
|
||||
{{if and $fixedStatusCode $isRef -}}
|
||||
type {{$opid}}{{$statusCode}}Response {{if not $isExternalRef}}={{end}} {{$ref}}Response
|
||||
{{else -}}
|
||||
type {{$opid}}{{$statusCode}}Response struct {
|
||||
{{if $hasHeaders -}}
|
||||
Headers {{if $isRef}}{{$ref}}{{else}}{{$opid}}{{$statusCode}}{{end}}ResponseHeaders
|
||||
{{end}}
|
||||
{{if not $fixedStatusCode -}}
|
||||
StatusCode int
|
||||
{{end -}}
|
||||
}
|
||||
{{end -}}
|
||||
func (response {{$opid}}{{$statusCode}}Response) Visit{{$opid}}Response(ctx iris.Context) error {
|
||||
{{range $headers -}}
|
||||
ctx.Response().Header.Set("{{.Name}}", fmt.Sprint(response.Headers.{{.GoName}}))
|
||||
{{end -}}
|
||||
ctx.StatusCode({{if $fixedStatusCode}}{{$statusCode}}{{else}}response.StatusCode{{end}})
|
||||
return nil
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
// StrictServerInterface represents all server handlers.
|
||||
type StrictServerInterface interface {
|
||||
{{range .}}{{.SummaryAsComment }}
|
||||
// ({{.Method}} {{.Path}})
|
||||
{{$opid := .OperationId -}}
|
||||
{{$opid}}(ctx context.Context, request {{$opid | ucFirst}}RequestObject) ({{$opid | ucFirst}}ResponseObject, error)
|
||||
{{end}}{{/* range . */ -}}
|
||||
}
|
||||
107
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/strict/strict-iris.tmpl
generated
vendored
Normal file
107
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/strict/strict-iris.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
type StrictHandlerFunc = strictiris.StrictIrisHandlerFunc
|
||||
type StrictMiddlewareFunc = strictiris.StrictIrisMiddlewareFunc
|
||||
|
||||
func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc) ServerInterface {
|
||||
return &strictHandler{ssi: ssi, middlewares: middlewares}
|
||||
}
|
||||
|
||||
type strictHandler struct {
|
||||
ssi StrictServerInterface
|
||||
middlewares []StrictMiddlewareFunc
|
||||
}
|
||||
|
||||
{{range .}}
|
||||
{{$opid := .OperationId}}
|
||||
// {{$opid}} operation middleware
|
||||
func (sh *strictHandler) {{.OperationId}}(ctx iris.Context{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params {{.OperationId}}Params{{end}}) {
|
||||
var request {{$opid | ucFirst}}RequestObject
|
||||
|
||||
{{range .PathParams -}}
|
||||
request.{{.GoName}} = {{.GoVariableName}}
|
||||
{{end -}}
|
||||
|
||||
{{if .RequiresParamObject -}}
|
||||
request.Params = params
|
||||
{{end -}}
|
||||
|
||||
{{ if .HasMaskedRequestContentTypes -}}
|
||||
request.ContentType = ctx.GetContentTypeRequested()
|
||||
{{end -}}
|
||||
|
||||
{{$multipleBodies := gt (len .Bodies) 1 -}}
|
||||
{{range .Bodies -}}
|
||||
{{if $multipleBodies}}if strings.HasPrefix(ctx.GetHeader("Content-Type"), "{{.ContentType}}") { {{end}}
|
||||
{{if .IsJSON }}
|
||||
var body {{$opid}}{{.NameTag}}RequestBody
|
||||
if err := ctx.ReadJSON(&body); err != nil {
|
||||
ctx.StopWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body
|
||||
{{else if eq .NameTag "Formdata" -}}
|
||||
if err := ctx.Request().ParseForm(); err != nil {
|
||||
ctx.StopWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
var body {{$opid}}{{.NameTag}}RequestBody
|
||||
if err := runtime.BindForm(&body, ctx.Request().Form, nil, nil); err != nil {
|
||||
ctx.StopWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body
|
||||
{{else if eq .NameTag "Multipart" -}}
|
||||
{{if eq .ContentType "multipart/form-data" -}}
|
||||
if reader, err := ctx.Request().MultipartReader(); err == nil {
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = reader
|
||||
} else {
|
||||
ctx.StopWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
{{else -}}
|
||||
if _, params, err := mime.ParseMediaType(ctx.Request().Header.Get("Content-Type")); err != nil {
|
||||
ctx.StopWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
} else if boundary := params["boundary"]; boundary == "" {
|
||||
ctx.StopWithError(http.StatusBadRequest, http.ErrMissingBoundary)
|
||||
return
|
||||
} else {
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = multipart.NewReader(ctx.Request().Body, boundary)
|
||||
}
|
||||
{{end -}}
|
||||
{{else if eq .NameTag "Text" -}}
|
||||
data, err := io.ReadAll(ctx.Request().Body)
|
||||
if err != nil {
|
||||
ctx.StopWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
body := {{$opid}}{{.NameTag}}RequestBody(data)
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body
|
||||
{{else -}}
|
||||
request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = ctx.Request().Body
|
||||
{{end}}{{/* if eq .NameTag "JSON" */ -}}
|
||||
{{if $multipleBodies}}}{{end}}
|
||||
{{end}}{{/* range .Bodies */}}
|
||||
|
||||
handler := func(ctx iris.Context, request interface{}) (interface{}, error) {
|
||||
return sh.ssi.{{.OperationId}}(ctx, request.({{$opid | ucFirst}}RequestObject))
|
||||
}
|
||||
for _, middleware := range sh.middlewares {
|
||||
handler = middleware(handler, "{{.OperationId}}")
|
||||
}
|
||||
|
||||
response, err := handler(ctx, request)
|
||||
|
||||
if err != nil {
|
||||
ctx.StopWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
} else if validResponse, ok := response.({{$opid | ucFirst}}ResponseObject); ok {
|
||||
if err := validResponse.Visit{{$opid}}Response(ctx); err != nil {
|
||||
ctx.StopWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
} else if response != nil {
|
||||
ctx.Writef("Unexpected response type: %T", response)
|
||||
return
|
||||
}
|
||||
}
|
||||
{{end}}
|
||||
41
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/strict/strict-responses.tmpl
generated
vendored
Normal file
41
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/strict/strict-responses.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
{{range . -}}
|
||||
{{$hasHeaders := ne 0 (len .Headers) -}}
|
||||
{{$name := .GoName | ucFirst -}}
|
||||
{{if $hasHeaders -}}
|
||||
type {{$name}}ResponseHeaders struct {
|
||||
{{range .Headers -}}
|
||||
{{.GoName}} {{.Schema.TypeDecl}}
|
||||
{{end -}}
|
||||
}
|
||||
{{end -}}
|
||||
|
||||
{{range .Contents -}}
|
||||
{{if and (not $hasHeaders) (.IsSupported) -}}
|
||||
type {{$name}}{{.NameTagOrContentType}}Response {{if eq .NameTag "Multipart"}}func(writer *multipart.Writer)error{{else if .IsSupported}}{{if .Schema.IsRef}}={{end}} {{.Schema.TypeDecl}}{{else}}io.Reader{{end}}
|
||||
{{else -}}
|
||||
type {{$name}}{{.NameTagOrContentType}}Response struct {
|
||||
Body {{if eq .NameTag "Multipart"}}func(writer *multipart.Writer)error{{else if .IsSupported}}{{.Schema.TypeDecl}}{{else}}io.Reader{{end}}
|
||||
|
||||
{{if $hasHeaders -}}
|
||||
Headers {{$name}}ResponseHeaders
|
||||
{{end -}}
|
||||
|
||||
{{if not .HasFixedContentType -}}
|
||||
ContentType string
|
||||
{{end -}}
|
||||
|
||||
{{if not .IsSupported -}}
|
||||
ContentLength int64
|
||||
{{end -}}
|
||||
}
|
||||
{{end -}}
|
||||
{{end -}}
|
||||
|
||||
{{if eq 0 (len .Contents) -}}
|
||||
type {{$name}}Response struct {
|
||||
{{if $hasHeaders -}}
|
||||
Headers {{$name}}ResponseHeaders
|
||||
{{end}}
|
||||
}
|
||||
{{end}}
|
||||
{{end -}}
|
||||
4
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/typedef.tmpl
generated
vendored
Normal file
4
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/typedef.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{{range .Types}}
|
||||
{{ if .Schema.Description }}{{ toGoComment .Schema.Description .TypeName }}{{ else }}// {{.TypeName}} defines model for {{.JsonName}}.{{ end }}
|
||||
type {{.TypeName}} {{if .IsAlias }}={{end}} {{.Schema.TypeDecl}}
|
||||
{{end}}
|
||||
72
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/union-and-additional-properties.tmpl
generated
vendored
Normal file
72
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/union-and-additional-properties.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
{{range .Types}}
|
||||
|
||||
{{$addType := .Schema.AdditionalPropertiesType.TypeDecl}}
|
||||
{{$typeName := .TypeName -}}
|
||||
{{$discriminator := .Schema.Discriminator}}
|
||||
{{$properties := .Schema.Properties -}}
|
||||
|
||||
// Override default JSON handling for {{.TypeName}} to handle AdditionalProperties and union
|
||||
func (a *{{.TypeName}}) UnmarshalJSON(b []byte) error {
|
||||
err := a.union.UnmarshalJSON(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
object := make(map[string]json.RawMessage)
|
||||
err = json.Unmarshal(b, &object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
{{range .Schema.Properties}}
|
||||
if raw, found := object["{{.JsonFieldName}}"]; found {
|
||||
err = json.Unmarshal(raw, &a.{{.GoFieldName}})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading '{{.JsonFieldName}}': %w", err)
|
||||
}
|
||||
delete(object, "{{.JsonFieldName}}")
|
||||
}
|
||||
{{end}}
|
||||
if len(object) != 0 {
|
||||
a.AdditionalProperties = make(map[string]{{$addType}})
|
||||
for fieldName, fieldBuf := range object {
|
||||
var fieldVal {{$addType}}
|
||||
err := json.Unmarshal(fieldBuf, &fieldVal)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error unmarshaling field %s: %w", fieldName, err)
|
||||
}
|
||||
a.AdditionalProperties[fieldName] = fieldVal
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Override default JSON handling for {{.TypeName}} to handle AdditionalProperties and union
|
||||
func (a {{.TypeName}}) MarshalJSON() ([]byte, error) {
|
||||
var err error
|
||||
b, err := a.union.MarshalJSON()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
object := make(map[string]json.RawMessage)
|
||||
if a.union != nil {
|
||||
err = json.Unmarshal(b, &object)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
{{range .Schema.Properties}}
|
||||
{{if not .Required}}if a.{{.GoFieldName}} != nil { {{end}}
|
||||
object["{{.JsonFieldName}}"], err = json.Marshal(a.{{.GoFieldName}})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error marshaling '{{.JsonFieldName}}': %w", err)
|
||||
}
|
||||
{{if not .Required}} }{{end}}
|
||||
{{end}}
|
||||
for fieldName, field := range a.AdditionalProperties {
|
||||
object[fieldName], err = json.Marshal(field)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error marshaling '%s': %w", fieldName, err)
|
||||
}
|
||||
}
|
||||
return json.Marshal(object)
|
||||
}
|
||||
{{end}}
|
||||
140
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/union.tmpl
generated
vendored
Normal file
140
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/templates/union.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
{{range .Types}}
|
||||
{{$typeName := .TypeName -}}
|
||||
{{$discriminator := .Schema.Discriminator}}
|
||||
{{$properties := .Schema.Properties -}}
|
||||
{{range .Schema.UnionElements}}
|
||||
{{$element := . -}}
|
||||
// As{{ .Method }} returns the union data inside the {{$typeName}} as a {{.}}
|
||||
func (t {{$typeName}}) As{{ .Method }}() ({{.}}, error) {
|
||||
var body {{.}}
|
||||
err := json.Unmarshal(t.union, &body)
|
||||
return body, err
|
||||
}
|
||||
|
||||
// From{{ .Method }} overwrites any union data inside the {{$typeName}} as the provided {{.}}
|
||||
func (t *{{$typeName}}) From{{ .Method }} (v {{.}}) error {
|
||||
{{if $discriminator -}}
|
||||
{{range $value, $type := $discriminator.Mapping -}}
|
||||
{{if eq $type $element -}}
|
||||
{{$hasProperty := false -}}
|
||||
{{range $properties -}}
|
||||
{{if eq .GoFieldName $discriminator.PropertyName -}}
|
||||
t.{{$discriminator.PropertyName}} = "{{$value}}"
|
||||
{{$hasProperty = true -}}
|
||||
{{end -}}
|
||||
{{end -}}
|
||||
{{if not $hasProperty}}v.{{$discriminator.PropertyName}} = "{{$value}}"{{end}}
|
||||
{{end -}}
|
||||
{{end -}}
|
||||
{{end -}}
|
||||
b, err := json.Marshal(v)
|
||||
t.union = b
|
||||
return err
|
||||
}
|
||||
|
||||
// Merge{{ .Method }} performs a merge with any union data inside the {{$typeName}}, using the provided {{.}}
|
||||
func (t *{{$typeName}}) Merge{{ .Method }} (v {{.}}) error {
|
||||
{{if $discriminator -}}
|
||||
{{range $value, $type := $discriminator.Mapping -}}
|
||||
{{if eq $type $element -}}
|
||||
{{$hasProperty := false -}}
|
||||
{{range $properties -}}
|
||||
{{if eq .GoFieldName $discriminator.PropertyName -}}
|
||||
t.{{$discriminator.PropertyName}} = "{{$value}}"
|
||||
{{$hasProperty = true -}}
|
||||
{{end -}}
|
||||
{{end -}}
|
||||
{{if not $hasProperty}}v.{{$discriminator.PropertyName}} = "{{$value}}"{{end}}
|
||||
{{end -}}
|
||||
{{end -}}
|
||||
{{end -}}
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
merged, err := runtime.JSONMerge(t.union, b)
|
||||
t.union = merged
|
||||
return err
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{if $discriminator}}
|
||||
func (t {{.TypeName}}) Discriminator() (string, error) {
|
||||
var discriminator struct {
|
||||
Discriminator string {{$discriminator.JSONTag}}
|
||||
}
|
||||
err := json.Unmarshal(t.union, &discriminator)
|
||||
return discriminator.Discriminator, err
|
||||
}
|
||||
|
||||
{{if ne 0 (len $discriminator.Mapping)}}
|
||||
func (t {{.TypeName}}) ValueByDiscriminator() (interface{}, error) {
|
||||
discriminator, err := t.Discriminator()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch discriminator{
|
||||
{{range $value, $type := $discriminator.Mapping -}}
|
||||
case "{{$value}}":
|
||||
return t.As{{$type}}()
|
||||
{{end -}}
|
||||
default:
|
||||
return nil, errors.New("unknown discriminator value: "+discriminator)
|
||||
}
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if not .Schema.HasAdditionalProperties}}
|
||||
|
||||
func (t {{.TypeName}}) MarshalJSON() ([]byte, error) {
|
||||
b, err := t.union.MarshalJSON()
|
||||
{{if ne 0 (len .Schema.Properties) -}}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
object := make(map[string]json.RawMessage)
|
||||
if t.union != nil {
|
||||
err = json.Unmarshal(b, &object)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
{{range .Schema.Properties}}
|
||||
{{if not .Required}}if t.{{.GoFieldName}} != nil { {{end}}
|
||||
object["{{.JsonFieldName}}"], err = json.Marshal(t.{{.GoFieldName}})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error marshaling '{{.JsonFieldName}}': %w", err)
|
||||
}
|
||||
{{if not .Required}} }{{end}}
|
||||
{{end -}}
|
||||
b, err = json.Marshal(object)
|
||||
{{end -}}
|
||||
return b, err
|
||||
}
|
||||
|
||||
func (t *{{.TypeName}}) UnmarshalJSON(b []byte) error {
|
||||
err := t.union.UnmarshalJSON(b)
|
||||
{{if ne 0 (len .Schema.Properties) -}}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
object := make(map[string]json.RawMessage)
|
||||
err = json.Unmarshal(b, &object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
{{range .Schema.Properties}}
|
||||
if raw, found := object["{{.JsonFieldName}}"]; found {
|
||||
err = json.Unmarshal(raw, &t.{{.GoFieldName}})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading '{{.JsonFieldName}}': %w", err)
|
||||
}
|
||||
}
|
||||
{{end}}
|
||||
{{end -}}
|
||||
return err
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
15
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/test_schema.json
generated
vendored
Normal file
15
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/test_schema.json
generated
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"title": "node",
|
||||
"type": "object",
|
||||
"description": "Represents a node",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"format": "uri-reference"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"pattern": "^[A-Z][a-zA-Z0-9]*$"
|
||||
}
|
||||
}
|
||||
}
|
||||
207
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/test_spec.yaml
generated
vendored
Normal file
207
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/test_spec.yaml
generated
vendored
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
openapi: 3.0.1
|
||||
|
||||
info:
|
||||
title: OpenAPI-CodeGen Test
|
||||
description: 'This is a test OpenAPI Spec'
|
||||
version: 1.0.0
|
||||
|
||||
servers:
|
||||
- url: https://test.oapi-codegen.com/v2
|
||||
- url: http://test.oapi-codegen.com/v2
|
||||
|
||||
paths:
|
||||
/test/{name}:
|
||||
get:
|
||||
tags:
|
||||
- test
|
||||
summary: Get test
|
||||
operationId: getTestByName
|
||||
parameters:
|
||||
- name: name
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- name: $top
|
||||
in: query
|
||||
required: false
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
200:
|
||||
description: Success
|
||||
content:
|
||||
application/xml:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Test'
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Test'
|
||||
422:
|
||||
description: InvalidArray
|
||||
content:
|
||||
application/xml:
|
||||
schema:
|
||||
type: array
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
default:
|
||||
description: Error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
/cat:
|
||||
get:
|
||||
tags:
|
||||
- cat
|
||||
summary: Get cat status
|
||||
operationId: getCatStatus
|
||||
responses:
|
||||
200:
|
||||
description: Success
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/CatAlive'
|
||||
- $ref: '#/components/schemas/CatDead'
|
||||
application/xml:
|
||||
schema:
|
||||
anyOf:
|
||||
- $ref: '#/components/schemas/CatAlive'
|
||||
- $ref: '#/components/schemas/CatDead'
|
||||
application/yaml:
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/CatAlive'
|
||||
- $ref: '#/components/schemas/CatDead'
|
||||
default:
|
||||
description: Error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
/enum:
|
||||
get:
|
||||
tags:
|
||||
- enum
|
||||
summary: References enum
|
||||
operationId: getEnum
|
||||
responses:
|
||||
200:
|
||||
description: Success
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/EnumTest'
|
||||
default:
|
||||
description: Error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
/user:
|
||||
get:
|
||||
tags:
|
||||
- mergeAllOf
|
||||
summary: Merges allOf ref-ing a JSON schema
|
||||
operationId: getUser
|
||||
responses:
|
||||
200:
|
||||
description: Success
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/User'
|
||||
default:
|
||||
description: Error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
|
||||
components:
|
||||
schemas:
|
||||
|
||||
Test:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
cases:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/TestCase'
|
||||
|
||||
TestCase:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
command:
|
||||
type: string
|
||||
|
||||
Error:
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
format: int32
|
||||
message:
|
||||
type: string
|
||||
|
||||
CatAlive:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
alive_since:
|
||||
type: string
|
||||
format: date-time
|
||||
|
||||
CatDead:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
dead_since:
|
||||
type: string
|
||||
format: date-time
|
||||
x-oapi-codegen-extra-tags:
|
||||
tag1: value1
|
||||
tag2: value2
|
||||
cause:
|
||||
type: string
|
||||
enum: [ car, dog, oldage ]
|
||||
|
||||
EnumTest:
|
||||
properties:
|
||||
numerics:
|
||||
type: integer
|
||||
enum: [0, 1, 2]
|
||||
enumNames:
|
||||
type: integer
|
||||
enum: [0, 1, 2]
|
||||
x-enumNames:
|
||||
- zero
|
||||
- one
|
||||
- two
|
||||
enumVarnames:
|
||||
type: integer
|
||||
enum: [0, 1, 2]
|
||||
x-enum-varnames:
|
||||
- na
|
||||
- single
|
||||
- double
|
||||
User:
|
||||
allOf:
|
||||
- $ref: ./test_schema.json
|
||||
- type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: User name
|
||||
1099
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/utils.go
generated
vendored
Normal file
1099
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen/utils.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
79
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/util/inputmapping.go
generated
vendored
Normal file
79
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/util/inputmapping.go
generated
vendored
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// The input mapping is expressed on the command line as `key1:value1,key2:value2,...`
|
||||
// We parse it here, but need to keep in mind that keys or values may contain
|
||||
// commas and colons. We will allow escaping those using double quotes, so
|
||||
// when passing in "key1":"value1", we will not look inside the quoted sections.
|
||||
func ParseCommandlineMap(src string) (map[string]string, error) {
|
||||
result := make(map[string]string)
|
||||
tuples := splitString(src, ',')
|
||||
for _, t := range tuples {
|
||||
kv := splitString(t, ':')
|
||||
if len(kv) != 2 {
|
||||
return nil, fmt.Errorf("expected key:value, got :%s", t)
|
||||
}
|
||||
key := strings.TrimLeft(kv[0], `"`)
|
||||
key = strings.TrimRight(key, `"`)
|
||||
|
||||
value := strings.TrimLeft(kv[1], `"`)
|
||||
value = strings.TrimRight(value, `"`)
|
||||
|
||||
result[key] = value
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
// splitString splits a string along the specified 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 {
|
||||
const escapeChar rune = '"'
|
||||
|
||||
var parts []string
|
||||
var part string
|
||||
inQuotes := false
|
||||
|
||||
for _, c := range s {
|
||||
if c == escapeChar {
|
||||
if inQuotes {
|
||||
inQuotes = false
|
||||
} else {
|
||||
inQuotes = true
|
||||
}
|
||||
}
|
||||
|
||||
// If we've gotten the separator rune, consider the previous part
|
||||
// complete, but only if we're outside of quoted sections
|
||||
if c == sep && !inQuotes {
|
||||
parts = append(parts, part)
|
||||
part = ""
|
||||
continue
|
||||
}
|
||||
part += string(c)
|
||||
}
|
||||
return append(parts, part)
|
||||
}
|
||||
14
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/util/isjson.go
generated
vendored
Normal file
14
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/util/isjson.go
generated
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"mime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func IsMediaTypeJson(mediaType string) bool {
|
||||
parsed, _, err := mime.ParseMediaType(mediaType)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return parsed == "application/json" || strings.HasSuffix(parsed, "+json")
|
||||
}
|
||||
94
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/util/loader.go
generated
vendored
Normal file
94
vendor/github.com/oapi-codegen/oapi-codegen/v2/pkg/util/loader.go
generated
vendored
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
"github.com/speakeasy-api/openapi-overlay/pkg/loader"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func LoadSwagger(filePath string) (swagger *openapi3.T, err error) {
|
||||
|
||||
loader := openapi3.NewLoader()
|
||||
loader.IsExternalRefsAllowed = true
|
||||
|
||||
u, err := url.Parse(filePath)
|
||||
if err == nil && u.Scheme != "" && u.Host != "" {
|
||||
return loader.LoadFromURI(u)
|
||||
} else {
|
||||
return loader.LoadFromFile(filePath)
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated: In kin-openapi v0.126.0 (https://github.com/getkin/kin-openapi/tree/v0.126.0?tab=readme-ov-file#v01260) the Circular Reference Counter functionality was removed, instead resolving all references with backtracking, to avoid needing to provide a limit to reference counts.
|
||||
//
|
||||
// This is now identital in method as `LoadSwagger`.
|
||||
func LoadSwaggerWithCircularReferenceCount(filePath string, _ int) (swagger *openapi3.T, err error) {
|
||||
return LoadSwagger(filePath)
|
||||
}
|
||||
|
||||
type LoadSwaggerWithOverlayOpts struct {
|
||||
Path string
|
||||
Strict bool
|
||||
}
|
||||
|
||||
func LoadSwaggerWithOverlay(filePath string, opts LoadSwaggerWithOverlayOpts) (swagger *openapi3.T, err error) {
|
||||
spec, err := LoadSwagger(filePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load OpenAPI specification: %w", err)
|
||||
}
|
||||
|
||||
if opts.Path == "" {
|
||||
return spec, nil
|
||||
}
|
||||
|
||||
// parse out the yaml.Node, which is required by the overlay library
|
||||
data, err := yaml.Marshal(spec)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal spec from %#v as YAML: %w", filePath, err)
|
||||
}
|
||||
|
||||
var node yaml.Node
|
||||
err = yaml.NewDecoder(bytes.NewReader(data)).Decode(&node)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse spec from %#v: %w", filePath, err)
|
||||
}
|
||||
|
||||
overlay, err := loader.LoadOverlay(opts.Path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load Overlay from %#v: %v", opts.Path, err)
|
||||
}
|
||||
|
||||
err = overlay.Validate()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("The Overlay in %#v was not valid: %v", opts.Path, err)
|
||||
}
|
||||
|
||||
if opts.Strict {
|
||||
err, vs := overlay.ApplyToStrict(&node)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to apply Overlay %#v to specification %#v: %v\nAdditionally, the following validation errors were found:\n- %s", opts.Path, filePath, err, strings.Join(vs, "\n- "))
|
||||
}
|
||||
} else {
|
||||
err = overlay.ApplyTo(&node)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to apply Overlay %#v to specification %#v: %v", opts.Path, filePath, err)
|
||||
}
|
||||
}
|
||||
|
||||
b, err := yaml.Marshal(&node)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to serialize Overlay'd specification %#v: %v", opts.Path, err)
|
||||
}
|
||||
|
||||
swagger, err = openapi3.NewLoader().LoadFromData(b)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to serialize Overlay'd specification %#v: %v", opts.Path, err)
|
||||
}
|
||||
|
||||
return swagger, nil
|
||||
}
|
||||
1
vendor/github.com/oapi-codegen/runtime/.gitignore
generated
vendored
Normal file
1
vendor/github.com/oapi-codegen/runtime/.gitignore
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
bin/
|
||||
201
vendor/github.com/oapi-codegen/runtime/LICENSE
generated
vendored
Normal file
201
vendor/github.com/oapi-codegen/runtime/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
32
vendor/github.com/oapi-codegen/runtime/Makefile
generated
vendored
Normal file
32
vendor/github.com/oapi-codegen/runtime/Makefile
generated
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
GOBASE=$(shell pwd)
|
||||
GOBIN=$(GOBASE)/bin
|
||||
|
||||
help:
|
||||
@echo "This is a helper makefile for oapi-codegen"
|
||||
@echo "Targets:"
|
||||
@echo " generate: regenerate all generated files"
|
||||
@echo " test: run all tests"
|
||||
@echo " gin_example generate gin example server code"
|
||||
@echo " tidy tidy go mod"
|
||||
|
||||
$(GOBIN)/golangci-lint:
|
||||
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOBIN) v1.55.2
|
||||
|
||||
.PHONY: tools
|
||||
tools: $(GOBIN)/golangci-lint
|
||||
|
||||
lint: tools
|
||||
$(GOBIN)/golangci-lint run ./...
|
||||
|
||||
lint-ci: tools
|
||||
$(GOBIN)/golangci-lint run ./... --out-format=github-actions --timeout=5m
|
||||
|
||||
generate:
|
||||
go generate ./...
|
||||
|
||||
test:
|
||||
go test -cover ./...
|
||||
|
||||
tidy:
|
||||
@echo "tidy..."
|
||||
go mod tidy
|
||||
6
vendor/github.com/oapi-codegen/runtime/README.md
generated
vendored
Normal file
6
vendor/github.com/oapi-codegen/runtime/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# oapi-codegen/runtime
|
||||
|
||||
⚠️ This README may be for the latest development version, which may
|
||||
contain unreleased changes. Please ensure you're looking at the README for the latest release version.
|
||||
|
||||
This provides any runtime-specific code that the generated code that oapi-codegen generates may need, and therefore is expected to be used with [deepmap/oapi-codegen](https://github.com/deepmap/oapi-codegen).
|
||||
24
vendor/github.com/oapi-codegen/runtime/bind.go
generated
vendored
Normal file
24
vendor/github.com/oapi-codegen/runtime/bind.go
generated
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2021 DeepMap, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package runtime
|
||||
|
||||
// Binder is the interface implemented by types that can be bound to a query string or a parameter string
|
||||
// The input can be assumed to be a valid string. If you define a Bind method you are responsible for all
|
||||
// data being completely bound to the type.
|
||||
//
|
||||
// By convention, to approximate the behavior of Bind functions themselves,
|
||||
// Binder implements Bind("") as a no-op.
|
||||
type Binder interface {
|
||||
Bind(src string) error
|
||||
}
|
||||
318
vendor/github.com/oapi-codegen/runtime/bindform.go
generated
vendored
Normal file
318
vendor/github.com/oapi-codegen/runtime/bindform.go
generated
vendored
Normal file
|
|
@ -0,0 +1,318 @@
|
|||
package runtime
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"mime/multipart"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/oapi-codegen/runtime/types"
|
||||
)
|
||||
|
||||
const tagName = "json"
|
||||
const jsonContentType = "application/json"
|
||||
|
||||
type RequestBodyEncoding struct {
|
||||
ContentType string
|
||||
Style string
|
||||
Explode *bool
|
||||
Required *bool
|
||||
}
|
||||
|
||||
func BindMultipart(ptr interface{}, reader multipart.Reader) error {
|
||||
const defaultMemory = 32 << 20
|
||||
form, err := reader.ReadForm(defaultMemory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return BindForm(ptr, form.Value, form.File, nil)
|
||||
}
|
||||
|
||||
func BindForm(ptr interface{}, form map[string][]string, files map[string][]*multipart.FileHeader, encodings map[string]RequestBodyEncoding) error {
|
||||
ptrVal := reflect.Indirect(reflect.ValueOf(ptr))
|
||||
if ptrVal.Kind() != reflect.Struct {
|
||||
return errors.New("form data body should be a struct")
|
||||
}
|
||||
tValue := ptrVal.Type()
|
||||
|
||||
for i := 0; i < tValue.NumField(); i++ {
|
||||
field := ptrVal.Field(i)
|
||||
tag := tValue.Field(i).Tag.Get(tagName)
|
||||
if !field.CanInterface() || tag == "-" {
|
||||
continue
|
||||
}
|
||||
tag = strings.Split(tag, ",")[0] // extract the name of the tag
|
||||
if encoding, ok := encodings[tag]; ok {
|
||||
// custom encoding
|
||||
values := form[tag]
|
||||
if len(values) == 0 {
|
||||
continue
|
||||
}
|
||||
value := values[0]
|
||||
if encoding.ContentType != "" {
|
||||
if strings.HasPrefix(encoding.ContentType, jsonContentType) {
|
||||
if err := json.Unmarshal([]byte(value), ptr); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return errors.New("unsupported encoding, only application/json is supported")
|
||||
} else {
|
||||
var explode bool
|
||||
if encoding.Explode != nil {
|
||||
explode = *encoding.Explode
|
||||
}
|
||||
var required bool
|
||||
if encoding.Required != nil {
|
||||
required = *encoding.Required
|
||||
}
|
||||
if err := BindStyledParameterWithOptions(encoding.Style, tag, value, field.Addr().Interface(), BindStyledParameterOptions{
|
||||
ParamLocation: ParamLocationUndefined,
|
||||
Explode: explode,
|
||||
Required: required,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// regular form data
|
||||
if _, err := bindFormImpl(field, form, files, tag); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func MarshalForm(ptr interface{}, encodings map[string]RequestBodyEncoding) (url.Values, error) {
|
||||
ptrVal := reflect.Indirect(reflect.ValueOf(ptr))
|
||||
if ptrVal.Kind() != reflect.Struct {
|
||||
return nil, errors.New("form data body should be a struct")
|
||||
}
|
||||
tValue := ptrVal.Type()
|
||||
result := make(url.Values)
|
||||
for i := 0; i < tValue.NumField(); i++ {
|
||||
field := ptrVal.Field(i)
|
||||
tag := tValue.Field(i).Tag.Get(tagName)
|
||||
if !field.CanInterface() || tag == "-" {
|
||||
continue
|
||||
}
|
||||
omitEmpty := strings.HasSuffix(tag, ",omitempty")
|
||||
if omitEmpty && field.IsZero() {
|
||||
continue
|
||||
}
|
||||
tag = strings.Split(tag, ",")[0] // extract the name of the tag
|
||||
if encoding, ok := encodings[tag]; ok && encoding.ContentType != "" {
|
||||
if strings.HasPrefix(encoding.ContentType, jsonContentType) {
|
||||
if data, err := json.Marshal(field); err != nil { //nolint:staticcheck
|
||||
return nil, err
|
||||
} else {
|
||||
result[tag] = append(result[tag], string(data))
|
||||
}
|
||||
}
|
||||
return nil, errors.New("unsupported encoding, only application/json is supported")
|
||||
} else {
|
||||
marshalFormImpl(field, result, tag)
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func bindFormImpl(v reflect.Value, form map[string][]string, files map[string][]*multipart.FileHeader, name string) (bool, error) {
|
||||
var hasData bool
|
||||
switch v.Kind() {
|
||||
case reflect.Interface:
|
||||
return bindFormImpl(v.Elem(), form, files, name)
|
||||
case reflect.Ptr:
|
||||
ptrData := v.Elem()
|
||||
if !ptrData.IsValid() {
|
||||
ptrData = reflect.New(v.Type().Elem())
|
||||
}
|
||||
ptrHasData, err := bindFormImpl(ptrData, form, files, name)
|
||||
if err == nil && ptrHasData && !v.Elem().IsValid() {
|
||||
v.Set(ptrData)
|
||||
}
|
||||
return ptrHasData, err
|
||||
case reflect.Slice:
|
||||
if files := append(files[name], files[name+"[]"]...); len(files) != 0 {
|
||||
if _, ok := v.Interface().([]types.File); ok {
|
||||
result := make([]types.File, len(files))
|
||||
for i, file := range files {
|
||||
result[i].InitFromMultipart(file)
|
||||
}
|
||||
v.Set(reflect.ValueOf(result))
|
||||
hasData = true
|
||||
}
|
||||
}
|
||||
indexedElementsCount := indexedElementsCount(form, files, name)
|
||||
items := append(form[name], form[name+"[]"]...)
|
||||
if indexedElementsCount+len(items) != 0 {
|
||||
result := reflect.MakeSlice(v.Type(), indexedElementsCount+len(items), indexedElementsCount+len(items))
|
||||
for i := 0; i < indexedElementsCount; i++ {
|
||||
if _, err := bindFormImpl(result.Index(i), form, files, fmt.Sprintf("%s[%v]", name, i)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
for i, item := range items {
|
||||
if err := BindStringToObject(item, result.Index(indexedElementsCount+i).Addr().Interface()); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
v.Set(result)
|
||||
hasData = true
|
||||
}
|
||||
case reflect.Struct:
|
||||
if files := files[name]; len(files) != 0 {
|
||||
if file, ok := v.Interface().(types.File); ok {
|
||||
file.InitFromMultipart(files[0])
|
||||
v.Set(reflect.ValueOf(file))
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
field := v.Type().Field(i)
|
||||
tag := field.Tag.Get(tagName)
|
||||
if field.Name == "AdditionalProperties" && field.Type.Kind() == reflect.Map && tag == "-" {
|
||||
additionalPropertiesHasData, err := bindAdditionalProperties(v.Field(i), v, form, files, name)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
hasData = hasData || additionalPropertiesHasData
|
||||
}
|
||||
if !v.Field(i).CanInterface() || tag == "-" {
|
||||
continue
|
||||
}
|
||||
tag = strings.Split(tag, ",")[0] // extract the name of the tag
|
||||
fieldHasData, err := bindFormImpl(v.Field(i), form, files, fmt.Sprintf("%s[%s]", name, tag))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
hasData = hasData || fieldHasData
|
||||
}
|
||||
return hasData, nil
|
||||
default:
|
||||
value := form[name]
|
||||
if len(value) != 0 {
|
||||
return true, BindStringToObject(value[0], v.Addr().Interface())
|
||||
}
|
||||
}
|
||||
return hasData, nil
|
||||
}
|
||||
|
||||
func indexedElementsCount(form map[string][]string, files map[string][]*multipart.FileHeader, name string) int {
|
||||
name += "["
|
||||
maxIndex := -1
|
||||
for k := range form {
|
||||
if strings.HasPrefix(k, name) {
|
||||
str := strings.TrimPrefix(k, name)
|
||||
str = str[:strings.Index(str, "]")]
|
||||
if idx, err := strconv.Atoi(str); err == nil {
|
||||
if idx > maxIndex {
|
||||
maxIndex = idx
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for k := range files {
|
||||
if strings.HasPrefix(k, name) {
|
||||
str := strings.TrimPrefix(k, name)
|
||||
str = str[:strings.Index(str, "]")]
|
||||
if idx, err := strconv.Atoi(str); err == nil {
|
||||
if idx > maxIndex {
|
||||
maxIndex = idx
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return maxIndex + 1
|
||||
}
|
||||
|
||||
func bindAdditionalProperties(additionalProperties reflect.Value, parentStruct reflect.Value, form map[string][]string, files map[string][]*multipart.FileHeader, name string) (bool, error) {
|
||||
hasData := false
|
||||
valueType := additionalProperties.Type().Elem()
|
||||
|
||||
// store all fixed properties in a set
|
||||
fieldsSet := make(map[string]struct{})
|
||||
for i := 0; i < parentStruct.NumField(); i++ {
|
||||
tag := parentStruct.Type().Field(i).Tag.Get(tagName)
|
||||
if !parentStruct.Field(i).CanInterface() || tag == "-" {
|
||||
continue
|
||||
}
|
||||
tag = strings.Split(tag, ",")[0]
|
||||
fieldsSet[tag] = struct{}{}
|
||||
}
|
||||
|
||||
result := reflect.MakeMap(additionalProperties.Type())
|
||||
for k := range form {
|
||||
if strings.HasPrefix(k, name+"[") {
|
||||
key := strings.TrimPrefix(k, name+"[")
|
||||
key = key[:strings.Index(key, "]")]
|
||||
if _, ok := fieldsSet[key]; ok {
|
||||
continue
|
||||
}
|
||||
value := reflect.New(valueType)
|
||||
ptrHasData, err := bindFormImpl(value, form, files, fmt.Sprintf("%s[%s]", name, key))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
result.SetMapIndex(reflect.ValueOf(key), value.Elem())
|
||||
hasData = hasData || ptrHasData
|
||||
}
|
||||
}
|
||||
for k := range files {
|
||||
if strings.HasPrefix(k, name+"[") {
|
||||
key := strings.TrimPrefix(k, name+"[")
|
||||
key = key[:strings.Index(key, "]")]
|
||||
if _, ok := fieldsSet[key]; ok {
|
||||
continue
|
||||
}
|
||||
value := reflect.New(valueType)
|
||||
result.SetMapIndex(reflect.ValueOf(key), value)
|
||||
ptrHasData, err := bindFormImpl(value, form, files, fmt.Sprintf("%s[%s]", name, key))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
result.SetMapIndex(reflect.ValueOf(key), value.Elem())
|
||||
hasData = hasData || ptrHasData
|
||||
}
|
||||
}
|
||||
if hasData {
|
||||
additionalProperties.Set(result)
|
||||
}
|
||||
return hasData, nil
|
||||
}
|
||||
|
||||
func marshalFormImpl(v reflect.Value, result url.Values, name string) {
|
||||
switch v.Kind() {
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
marshalFormImpl(v.Elem(), result, name)
|
||||
case reflect.Slice:
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
elem := v.Index(i)
|
||||
marshalFormImpl(elem, result, fmt.Sprintf("%s[%v]", name, i))
|
||||
}
|
||||
case reflect.Struct:
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
field := v.Type().Field(i)
|
||||
tag := field.Tag.Get(tagName)
|
||||
if field.Name == "AdditionalProperties" && tag == "-" {
|
||||
iter := v.MapRange()
|
||||
for iter.Next() {
|
||||
marshalFormImpl(iter.Value(), result, fmt.Sprintf("%s[%s]", name, iter.Key().String()))
|
||||
}
|
||||
continue
|
||||
}
|
||||
if !v.Field(i).CanInterface() || tag == "-" {
|
||||
continue
|
||||
}
|
||||
tag = strings.Split(tag, ",")[0] // extract the name of the tag
|
||||
marshalFormImpl(v.Field(i), result, fmt.Sprintf("%s[%s]", name, tag))
|
||||
}
|
||||
default:
|
||||
result[name] = append(result[name], fmt.Sprint(v.Interface()))
|
||||
}
|
||||
}
|
||||
555
vendor/github.com/oapi-codegen/runtime/bindparam.go
generated
vendored
Normal file
555
vendor/github.com/oapi-codegen/runtime/bindparam.go
generated
vendored
Normal file
|
|
@ -0,0 +1,555 @@
|
|||
// Copyright 2019 DeepMap, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/oapi-codegen/runtime/types"
|
||||
)
|
||||
|
||||
// BindStyledParameter binds a parameter as described in the Path Parameters
|
||||
// section here to a Go object:
|
||||
// https://swagger.io/docs/specification/serialization/
|
||||
// It is a backward compatible function to clients generated with codegen
|
||||
// up to version v1.5.5. v1.5.6+ calls the function below.
|
||||
// Deprecated: BindStyledParameter is deprecated.
|
||||
func BindStyledParameter(style string, explode bool, paramName string,
|
||||
value string, dest interface{}) error {
|
||||
return BindStyledParameterWithOptions(style, paramName, value, dest, BindStyledParameterOptions{
|
||||
ParamLocation: ParamLocationUndefined,
|
||||
Explode: explode,
|
||||
Required: true,
|
||||
})
|
||||
}
|
||||
|
||||
// BindStyledParameterWithLocation binds a parameter as described in the Path Parameters
|
||||
// section here to a Go object:
|
||||
// https://swagger.io/docs/specification/serialization/
|
||||
// This is a compatibility function which is used by oapi-codegen v2.0.0 and earlier.
|
||||
// Deprecated: BindStyledParameterWithLocation is deprecated.
|
||||
func BindStyledParameterWithLocation(style string, explode bool, paramName string,
|
||||
paramLocation ParamLocation, value string, dest interface{}) error {
|
||||
return BindStyledParameterWithOptions(style, paramName, value, dest, BindStyledParameterOptions{
|
||||
ParamLocation: paramLocation,
|
||||
Explode: explode,
|
||||
Required: true, // This emulates behavior before the required parameter was optional.
|
||||
})
|
||||
}
|
||||
|
||||
// BindStyledParameterOptions defines optional arguments for BindStyledParameterWithOptions
|
||||
type BindStyledParameterOptions struct {
|
||||
// ParamLocation tells us where the parameter is located in the request.
|
||||
ParamLocation ParamLocation
|
||||
// Whether the parameter should use exploded structure
|
||||
Explode bool
|
||||
// Whether the parameter is required in the query
|
||||
Required bool
|
||||
}
|
||||
|
||||
// BindStyledParameterWithOptions binds a parameter as described in the Path Parameters
|
||||
// section here to a Go object:
|
||||
// https://swagger.io/docs/specification/serialization/
|
||||
func BindStyledParameterWithOptions(style string, paramName string, value string, dest any, opts BindStyledParameterOptions) error {
|
||||
if opts.Required {
|
||||
if value == "" {
|
||||
return fmt.Errorf("parameter '%s' is empty, can't bind its value", paramName)
|
||||
}
|
||||
}
|
||||
|
||||
// Based on the location of the parameter, we need to unescape it properly.
|
||||
var err error
|
||||
switch opts.ParamLocation {
|
||||
case ParamLocationQuery, ParamLocationUndefined:
|
||||
// We unescape undefined parameter locations here for older generated code,
|
||||
// since prior to this refactoring, they always query unescaped.
|
||||
value, err = url.QueryUnescape(value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error unescaping query parameter '%s': %v", paramName, err)
|
||||
}
|
||||
case ParamLocationPath:
|
||||
value, err = url.PathUnescape(value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error unescaping path parameter '%s': %v", paramName, err)
|
||||
}
|
||||
default:
|
||||
// Headers and cookies aren't escaped.
|
||||
}
|
||||
|
||||
// If the destination implements encoding.TextUnmarshaler we use it for binding
|
||||
if tu, ok := dest.(encoding.TextUnmarshaler); ok {
|
||||
if err := tu.UnmarshalText([]byte(value)); err != nil {
|
||||
return fmt.Errorf("error unmarshaling '%s' text as %T: %s", value, dest, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Everything comes in by pointer, dereference it
|
||||
v := reflect.Indirect(reflect.ValueOf(dest))
|
||||
|
||||
// This is the basic type of the destination object.
|
||||
t := v.Type()
|
||||
|
||||
if t.Kind() == reflect.Struct {
|
||||
// We've got a destination object, we'll create a JSON representation
|
||||
// of the input value, and let the json library deal with the unmarshaling
|
||||
parts, err := splitStyledParameter(style, opts.Explode, true, paramName, value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return bindSplitPartsToDestinationStruct(paramName, parts, opts.Explode, dest)
|
||||
}
|
||||
|
||||
if t.Kind() == reflect.Slice {
|
||||
// Chop up the parameter into parts based on its style
|
||||
parts, err := splitStyledParameter(style, opts.Explode, false, paramName, value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error splitting input '%s' into parts: %s", value, err)
|
||||
}
|
||||
|
||||
return bindSplitPartsToDestinationArray(parts, dest)
|
||||
}
|
||||
|
||||
// Try to bind the remaining types as a base type.
|
||||
return BindStringToObject(value, dest)
|
||||
}
|
||||
|
||||
// This is a complex set of operations, but each given parameter style can be
|
||||
// packed together in multiple ways, using different styles of separators, and
|
||||
// different packing strategies based on the explode flag. This function takes
|
||||
// as input any parameter format, and unpacks it to a simple list of strings
|
||||
// or key-values which we can then treat generically.
|
||||
// Why, oh why, great Swagger gods, did you have to make this so complicated?
|
||||
func splitStyledParameter(style string, explode bool, object bool, paramName string, value string) ([]string, error) {
|
||||
switch style {
|
||||
case "simple":
|
||||
// In the simple case, we always split on comma
|
||||
parts := strings.Split(value, ",")
|
||||
return parts, nil
|
||||
case "label":
|
||||
// In the label case, it's more tricky. In the no explode case, we have
|
||||
// /users/.3,4,5 for arrays
|
||||
// /users/.role,admin,firstName,Alex for objects
|
||||
// in the explode case, we have:
|
||||
// /users/.3.4.5
|
||||
// /users/.role=admin.firstName=Alex
|
||||
if explode {
|
||||
// In the exploded case, split everything on periods.
|
||||
parts := strings.Split(value, ".")
|
||||
// The first part should be an empty string because we have a
|
||||
// leading period.
|
||||
if parts[0] != "" {
|
||||
return nil, fmt.Errorf("invalid format for label parameter '%s', should start with '.'", paramName)
|
||||
}
|
||||
return parts[1:], nil
|
||||
|
||||
} else {
|
||||
// In the unexploded case, we strip off the leading period.
|
||||
if value[0] != '.' {
|
||||
return nil, fmt.Errorf("invalid format for label parameter '%s', should start with '.'", paramName)
|
||||
}
|
||||
// The rest is comma separated.
|
||||
return strings.Split(value[1:], ","), nil
|
||||
}
|
||||
|
||||
case "matrix":
|
||||
if explode {
|
||||
// In the exploded case, we break everything up on semicolon
|
||||
parts := strings.Split(value, ";")
|
||||
// The first part should always be empty string, since we started
|
||||
// with ;something
|
||||
if parts[0] != "" {
|
||||
return nil, fmt.Errorf("invalid format for matrix parameter '%s', should start with ';'", paramName)
|
||||
}
|
||||
parts = parts[1:]
|
||||
// Now, if we have an object, we just have a list of x=y statements.
|
||||
// for a non-object, like an array, we have id=x, id=y. id=z, etc,
|
||||
// so we need to strip the prefix from each of them.
|
||||
if !object {
|
||||
prefix := paramName + "="
|
||||
for i := range parts {
|
||||
parts[i] = strings.TrimPrefix(parts[i], prefix)
|
||||
}
|
||||
}
|
||||
return parts, nil
|
||||
} else {
|
||||
// In the unexploded case, parameters will start with ;paramName=
|
||||
prefix := ";" + paramName + "="
|
||||
if !strings.HasPrefix(value, prefix) {
|
||||
return nil, fmt.Errorf("expected parameter '%s' to start with %s", paramName, prefix)
|
||||
}
|
||||
str := strings.TrimPrefix(value, prefix)
|
||||
return strings.Split(str, ","), nil
|
||||
}
|
||||
case "form":
|
||||
var parts []string
|
||||
if explode {
|
||||
parts = strings.Split(value, "&")
|
||||
if !object {
|
||||
prefix := paramName + "="
|
||||
for i := range parts {
|
||||
parts[i] = strings.TrimPrefix(parts[i], prefix)
|
||||
}
|
||||
}
|
||||
return parts, nil
|
||||
} else {
|
||||
parts = strings.Split(value, ",")
|
||||
prefix := paramName + "="
|
||||
for i := range parts {
|
||||
parts[i] = strings.TrimPrefix(parts[i], prefix)
|
||||
}
|
||||
}
|
||||
return parts, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("unhandled parameter style: %s", style)
|
||||
}
|
||||
|
||||
// Given a set of values as a slice, create a slice to hold them all, and
|
||||
// assign to each one by one.
|
||||
func bindSplitPartsToDestinationArray(parts []string, dest interface{}) error {
|
||||
// Everything comes in by pointer, dereference it
|
||||
v := reflect.Indirect(reflect.ValueOf(dest))
|
||||
|
||||
// This is the basic type of the destination object.
|
||||
t := v.Type()
|
||||
|
||||
// We've got a destination array, bind each object one by one.
|
||||
// This generates a slice of the correct element type and length to
|
||||
// hold all the parts.
|
||||
newArray := reflect.MakeSlice(t, len(parts), len(parts))
|
||||
for i, p := range parts {
|
||||
err := BindStringToObject(p, newArray.Index(i).Addr().Interface())
|
||||
if err != nil {
|
||||
return fmt.Errorf("error setting array element: %w", err)
|
||||
}
|
||||
}
|
||||
v.Set(newArray)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Given a set of chopped up parameter parts, bind them to a destination
|
||||
// struct. The exploded parameter controls whether we send key value pairs
|
||||
// in the exploded case, or a sequence of values which are interpreted as
|
||||
// tuples.
|
||||
// Given the struct Id { firstName string, role string }, as in the canonical
|
||||
// swagger examples, in the exploded case, we would pass
|
||||
// ["firstName=Alex", "role=admin"], where in the non-exploded case, we would
|
||||
// pass "firstName", "Alex", "role", "admin"]
|
||||
//
|
||||
// We punt the hard work of binding these values to the object to the json
|
||||
// library. We'll turn those arrays into JSON strings, and unmarshal
|
||||
// into the struct.
|
||||
func bindSplitPartsToDestinationStruct(paramName string, parts []string, explode bool, dest interface{}) error {
|
||||
// We've got a destination object, we'll create a JSON representation
|
||||
// of the input value, and let the json library deal with the unmarshaling
|
||||
var fields []string
|
||||
if explode {
|
||||
fields = make([]string, len(parts))
|
||||
for i, property := range parts {
|
||||
propertyParts := strings.Split(property, "=")
|
||||
if len(propertyParts) != 2 {
|
||||
return fmt.Errorf("parameter '%s' has invalid exploded format", paramName)
|
||||
}
|
||||
fields[i] = "\"" + propertyParts[0] + "\":\"" + propertyParts[1] + "\""
|
||||
}
|
||||
} else {
|
||||
if len(parts)%2 != 0 {
|
||||
return fmt.Errorf("parameter '%s' has invalid format, property/values need to be pairs", paramName)
|
||||
}
|
||||
fields = make([]string, len(parts)/2)
|
||||
for i := 0; i < len(parts); i += 2 {
|
||||
key := parts[i]
|
||||
value := parts[i+1]
|
||||
fields[i/2] = "\"" + key + "\":\"" + value + "\""
|
||||
}
|
||||
}
|
||||
jsonParam := "{" + strings.Join(fields, ",") + "}"
|
||||
err := json.Unmarshal([]byte(jsonParam), dest)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error binding parameter %s fields: %s", paramName, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// BindQueryParameter works much like BindStyledParameter, however it takes a query argument
|
||||
// input array from the url package, since query arguments come through a
|
||||
// different path than the styled arguments. They're also exceptionally fussy.
|
||||
// For example, consider the exploded and unexploded form parameter examples:
|
||||
// (exploded) /users?role=admin&firstName=Alex
|
||||
// (unexploded) /users?id=role,admin,firstName,Alex
|
||||
//
|
||||
// In the first case, we can pull the "id" parameter off the context,
|
||||
// and unmarshal via json as an intermediate. Easy. In the second case, we
|
||||
// don't have the id QueryParam present, but must find "role", and "firstName".
|
||||
// what if there is another parameter similar to "ID" named "role"? We can't
|
||||
// tell them apart. This code tries to fail, but the moral of the story is that
|
||||
// you shouldn't pass objects via form styled query arguments, just use
|
||||
// the Content parameter form.
|
||||
func BindQueryParameter(style string, explode bool, required bool, paramName string,
|
||||
queryParams url.Values, dest interface{}) error {
|
||||
|
||||
// dv = destination value.
|
||||
dv := reflect.Indirect(reflect.ValueOf(dest))
|
||||
|
||||
// intermediate value form which is either dv or dv dereferenced.
|
||||
v := dv
|
||||
|
||||
// inner code will bind the string's value to this interface.
|
||||
var output interface{}
|
||||
|
||||
if required {
|
||||
// If the parameter is required, then the generated code will pass us
|
||||
// a pointer to it: &int, &object, and so forth. We can directly set
|
||||
// them.
|
||||
output = dest
|
||||
} else {
|
||||
// For optional parameters, we have an extra indirect. An optional
|
||||
// parameter of type "int" will be *int on the struct. We pass that
|
||||
// in by pointer, and have **int.
|
||||
|
||||
// If the destination, is a nil pointer, we need to allocate it.
|
||||
if v.IsNil() {
|
||||
t := v.Type()
|
||||
newValue := reflect.New(t.Elem())
|
||||
// for now, hang onto the output buffer separately from destination,
|
||||
// as we don't want to write anything to destination until we can
|
||||
// unmarshal successfully, and check whether a field is required.
|
||||
output = newValue.Interface()
|
||||
} else {
|
||||
// If the destination isn't nil, just use that.
|
||||
output = v.Interface()
|
||||
}
|
||||
|
||||
// Get rid of that extra indirect as compared to the required case,
|
||||
// so the code below doesn't have to care.
|
||||
v = reflect.Indirect(reflect.ValueOf(output))
|
||||
}
|
||||
|
||||
// This is the basic type of the destination object.
|
||||
t := v.Type()
|
||||
k := t.Kind()
|
||||
|
||||
switch style {
|
||||
case "form":
|
||||
var parts []string
|
||||
if explode {
|
||||
// ok, the explode case in query arguments is very, very annoying,
|
||||
// because an exploded object, such as /users?role=admin&firstName=Alex
|
||||
// isn't actually present in the parameter array. We have to do
|
||||
// different things based on destination type.
|
||||
values, found := queryParams[paramName]
|
||||
var err error
|
||||
|
||||
switch k {
|
||||
case reflect.Slice:
|
||||
// In the slice case, we simply use the arguments provided by
|
||||
// http library.
|
||||
|
||||
if !found {
|
||||
if required {
|
||||
return fmt.Errorf("query parameter '%s' is required", paramName)
|
||||
} else {
|
||||
// If an optional parameter is not found, we do nothing,
|
||||
return nil
|
||||
}
|
||||
}
|
||||
err = bindSplitPartsToDestinationArray(values, output)
|
||||
case reflect.Struct:
|
||||
// This case is really annoying, and error prone, but the
|
||||
// form style object binding doesn't tell us which arguments
|
||||
// in the query string correspond to the object's fields. We'll
|
||||
// try to bind field by field.
|
||||
var fieldsPresent bool
|
||||
fieldsPresent, err = bindParamsToExplodedObject(paramName, queryParams, output)
|
||||
// If no fields were set, and there is no error, we will not fall
|
||||
// through to assign the destination.
|
||||
if !fieldsPresent {
|
||||
return nil
|
||||
}
|
||||
default:
|
||||
// Primitive object case. We expect to have 1 value to
|
||||
// unmarshal.
|
||||
if len(values) == 0 {
|
||||
if required {
|
||||
return fmt.Errorf("query parameter '%s' is required", paramName)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if len(values) != 1 {
|
||||
return fmt.Errorf("multiple values for single value parameter '%s'", paramName)
|
||||
}
|
||||
|
||||
if !found {
|
||||
if required {
|
||||
return fmt.Errorf("query parameter '%s' is required", paramName)
|
||||
} else {
|
||||
// If an optional parameter is not found, we do nothing,
|
||||
return nil
|
||||
}
|
||||
}
|
||||
err = BindStringToObject(values[0], output)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// If the parameter is required, and we've successfully unmarshaled
|
||||
// it, this assigns the new object to the pointer pointer.
|
||||
if !required {
|
||||
dv.Set(reflect.ValueOf(output))
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
values, found := queryParams[paramName]
|
||||
if !found {
|
||||
if required {
|
||||
return fmt.Errorf("query parameter '%s' is required", paramName)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if len(values) != 1 {
|
||||
return fmt.Errorf("parameter '%s' is not exploded, but is specified multiple times", paramName)
|
||||
}
|
||||
parts = strings.Split(values[0], ",")
|
||||
}
|
||||
var err error
|
||||
switch k {
|
||||
case reflect.Slice:
|
||||
err = bindSplitPartsToDestinationArray(parts, output)
|
||||
case reflect.Struct:
|
||||
err = bindSplitPartsToDestinationStruct(paramName, parts, explode, output)
|
||||
default:
|
||||
if len(parts) == 0 {
|
||||
if required {
|
||||
return fmt.Errorf("query parameter '%s' is required", paramName)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if len(parts) != 1 {
|
||||
return fmt.Errorf("multiple values for single value parameter '%s'", paramName)
|
||||
}
|
||||
err = BindStringToObject(parts[0], output)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !required {
|
||||
dv.Set(reflect.ValueOf(output))
|
||||
}
|
||||
return nil
|
||||
case "deepObject":
|
||||
if !explode {
|
||||
return errors.New("deepObjects must be exploded")
|
||||
}
|
||||
return UnmarshalDeepObject(dest, paramName, queryParams)
|
||||
case "spaceDelimited", "pipeDelimited":
|
||||
return fmt.Errorf("query arguments of style '%s' aren't yet supported", style)
|
||||
default:
|
||||
return fmt.Errorf("style '%s' on parameter '%s' is invalid", style, paramName)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// bindParamsToExplodedObject reflects the destination structure, and pulls the value for
|
||||
// each settable field from the given parameters map. This is to deal with the
|
||||
// exploded form styled object which may occupy any number of parameter names.
|
||||
// We don't try to be smart here, if the field exists as a query argument,
|
||||
// set its value. This function returns a boolean, telling us whether there was
|
||||
// anything to bind. There will be nothing to bind if a parameter isn't found by name,
|
||||
// or none of an exploded object's fields are present.
|
||||
func bindParamsToExplodedObject(paramName string, values url.Values, dest interface{}) (bool, error) {
|
||||
// Dereference pointers to their destination values
|
||||
binder, v, t := indirect(dest)
|
||||
if binder != nil {
|
||||
_, found := values[paramName]
|
||||
if !found {
|
||||
return false, nil
|
||||
}
|
||||
return true, BindStringToObject(values.Get(paramName), dest)
|
||||
}
|
||||
if t.Kind() != reflect.Struct {
|
||||
return false, fmt.Errorf("unmarshaling query arg '%s' into wrong type", paramName)
|
||||
}
|
||||
|
||||
fieldsPresent := false
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
fieldT := t.Field(i)
|
||||
|
||||
// Skip unsettable fields, such as internal ones.
|
||||
if !v.Field(i).CanSet() {
|
||||
continue
|
||||
}
|
||||
|
||||
// Find the json annotation on the field, and use the json specified
|
||||
// name if available, otherwise, just the field name.
|
||||
tag := fieldT.Tag.Get("json")
|
||||
fieldName := fieldT.Name
|
||||
if tag != "" {
|
||||
tagParts := strings.Split(tag, ",")
|
||||
name := tagParts[0]
|
||||
if name != "" {
|
||||
fieldName = name
|
||||
}
|
||||
}
|
||||
|
||||
// At this point, we look up field name in the parameter list.
|
||||
fieldVal, found := values[fieldName]
|
||||
if found {
|
||||
if len(fieldVal) != 1 {
|
||||
return false, fmt.Errorf("field '%s' specified multiple times for param '%s'", fieldName, paramName)
|
||||
}
|
||||
err := BindStringToObject(fieldVal[0], v.Field(i).Addr().Interface())
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("could not bind query arg '%s' to request object: %s'", paramName, err)
|
||||
}
|
||||
fieldsPresent = true
|
||||
}
|
||||
}
|
||||
return fieldsPresent, nil
|
||||
}
|
||||
|
||||
// indirect
|
||||
func indirect(dest interface{}) (interface{}, reflect.Value, reflect.Type) {
|
||||
v := reflect.ValueOf(dest)
|
||||
if v.Type().NumMethod() > 0 && v.CanInterface() {
|
||||
if u, ok := v.Interface().(Binder); ok {
|
||||
return u, reflect.Value{}, nil
|
||||
}
|
||||
}
|
||||
v = reflect.Indirect(v)
|
||||
t := v.Type()
|
||||
// special handling for custom types which might look like an object. We
|
||||
// don't want to use object binding on them, but rather treat them as
|
||||
// primitive types. time.Time{} is a unique case since we can't add a Binder
|
||||
// to it without changing the underlying generated code.
|
||||
if t.ConvertibleTo(reflect.TypeOf(time.Time{})) {
|
||||
return dest, reflect.Value{}, nil
|
||||
}
|
||||
if t.ConvertibleTo(reflect.TypeOf(types.Date{})) {
|
||||
return dest, reflect.Value{}, nil
|
||||
}
|
||||
return nil, v, t
|
||||
}
|
||||
174
vendor/github.com/oapi-codegen/runtime/bindstring.go
generated
vendored
Normal file
174
vendor/github.com/oapi-codegen/runtime/bindstring.go
generated
vendored
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
// Copyright 2019 DeepMap, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/oapi-codegen/runtime/types"
|
||||
)
|
||||
|
||||
// BindStringToObject takes a string, and attempts to assign it to the destination
|
||||
// interface via whatever type conversion is necessary. We have to do this
|
||||
// via reflection instead of a much simpler type switch so that we can handle
|
||||
// type aliases. This function was the easy way out, the better way, since we
|
||||
// know the destination type each place that we use this, is to generate code
|
||||
// to read each specific type.
|
||||
func BindStringToObject(src string, dst interface{}) error {
|
||||
var err error
|
||||
|
||||
v := reflect.ValueOf(dst)
|
||||
t := reflect.TypeOf(dst)
|
||||
|
||||
// We need to dereference pointers
|
||||
if t.Kind() == reflect.Ptr {
|
||||
v = reflect.Indirect(v)
|
||||
t = v.Type()
|
||||
}
|
||||
|
||||
// For some optional args
|
||||
if t.Kind() == reflect.Ptr {
|
||||
if v.IsNil() {
|
||||
v.Set(reflect.New(t.Elem()))
|
||||
}
|
||||
|
||||
v = reflect.Indirect(v)
|
||||
t = v.Type()
|
||||
}
|
||||
|
||||
// The resulting type must be settable. reflect will catch issues like
|
||||
// passing the destination by value.
|
||||
if !v.CanSet() {
|
||||
return errors.New("destination is not settable")
|
||||
}
|
||||
|
||||
switch t.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
var val int64
|
||||
val, err = strconv.ParseInt(src, 10, 64)
|
||||
if err == nil {
|
||||
if v.OverflowInt(val) {
|
||||
err = fmt.Errorf("value '%s' overflows destination of type: %s", src, t.Kind())
|
||||
}
|
||||
if err == nil {
|
||||
v.SetInt(val)
|
||||
}
|
||||
}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
var val uint64
|
||||
val, err = strconv.ParseUint(src, 10, 64)
|
||||
if err == nil {
|
||||
if v.OverflowUint(val) {
|
||||
err = fmt.Errorf("value '%s' overflows destination of type: %s", src, t.Kind())
|
||||
}
|
||||
v.SetUint(val)
|
||||
}
|
||||
case reflect.String:
|
||||
v.SetString(src)
|
||||
err = nil
|
||||
case reflect.Float64, reflect.Float32:
|
||||
var val float64
|
||||
val, err = strconv.ParseFloat(src, 64)
|
||||
if err == nil {
|
||||
if v.OverflowFloat(val) {
|
||||
err = fmt.Errorf("value '%s' overflows destination of type: %s", src, t.Kind())
|
||||
}
|
||||
v.SetFloat(val)
|
||||
}
|
||||
case reflect.Bool:
|
||||
var val bool
|
||||
val, err = strconv.ParseBool(src)
|
||||
if err == nil {
|
||||
v.SetBool(val)
|
||||
}
|
||||
case reflect.Array:
|
||||
if tu, ok := dst.(encoding.TextUnmarshaler); ok {
|
||||
if err := tu.UnmarshalText([]byte(src)); err != nil {
|
||||
return fmt.Errorf("error unmarshaling '%s' text as %T: %s", src, dst, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
fallthrough
|
||||
case reflect.Struct:
|
||||
// if this is not of type Time or of type Date look to see if this is of type Binder.
|
||||
if dstType, ok := dst.(Binder); ok {
|
||||
return dstType.Bind(src)
|
||||
}
|
||||
|
||||
if t.ConvertibleTo(reflect.TypeOf(time.Time{})) {
|
||||
// Don't fail on empty string.
|
||||
if src == "" {
|
||||
return nil
|
||||
}
|
||||
// Time is a special case of a struct that we handle
|
||||
parsedTime, err := time.Parse(time.RFC3339Nano, src)
|
||||
if err != nil {
|
||||
parsedTime, err = time.Parse(types.DateFormat, src)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing '%s' as RFC3339 or 2006-01-02 time: %s", src, err)
|
||||
}
|
||||
}
|
||||
// So, assigning this gets a little fun. We have a value to the
|
||||
// dereference destination. We can't do a conversion to
|
||||
// time.Time because the result isn't assignable, so we need to
|
||||
// convert pointers.
|
||||
if t != reflect.TypeOf(time.Time{}) {
|
||||
vPtr := v.Addr()
|
||||
vtPtr := vPtr.Convert(reflect.TypeOf(&time.Time{}))
|
||||
v = reflect.Indirect(vtPtr)
|
||||
}
|
||||
v.Set(reflect.ValueOf(parsedTime))
|
||||
return nil
|
||||
}
|
||||
|
||||
if t.ConvertibleTo(reflect.TypeOf(types.Date{})) {
|
||||
// Don't fail on empty string.
|
||||
if src == "" {
|
||||
return nil
|
||||
}
|
||||
parsedTime, err := time.Parse(types.DateFormat, src)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing '%s' as date: %s", src, err)
|
||||
}
|
||||
parsedDate := types.Date{Time: parsedTime}
|
||||
|
||||
// We have to do the same dance here to assign, just like with times
|
||||
// above.
|
||||
if t != reflect.TypeOf(types.Date{}) {
|
||||
vPtr := v.Addr()
|
||||
vtPtr := vPtr.Convert(reflect.TypeOf(&types.Date{}))
|
||||
v = reflect.Indirect(vtPtr)
|
||||
}
|
||||
v.Set(reflect.ValueOf(parsedDate))
|
||||
return nil
|
||||
}
|
||||
|
||||
// We fall through to the error case below if we haven't handled the
|
||||
// destination type above.
|
||||
fallthrough
|
||||
default:
|
||||
// We've got a bunch of types unimplemented, don't fail silently.
|
||||
err = fmt.Errorf("can not bind to destination of type: %s", t.Kind())
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("error binding string parameter: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
371
vendor/github.com/oapi-codegen/runtime/deepobject.go
generated
vendored
Normal file
371
vendor/github.com/oapi-codegen/runtime/deepobject.go
generated
vendored
Normal file
|
|
@ -0,0 +1,371 @@
|
|||
package runtime
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/oapi-codegen/runtime/types"
|
||||
)
|
||||
|
||||
func marshalDeepObject(in interface{}, path []string) ([]string, error) {
|
||||
var result []string
|
||||
|
||||
switch t := in.(type) {
|
||||
case []interface{}:
|
||||
// For the array, we will use numerical subscripts of the form [x],
|
||||
// in the same order as the array.
|
||||
for i, iface := range t {
|
||||
newPath := append(path, strconv.Itoa(i))
|
||||
fields, err := marshalDeepObject(iface, newPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error traversing array: %w", err)
|
||||
}
|
||||
result = append(result, fields...)
|
||||
}
|
||||
case map[string]interface{}:
|
||||
// For a map, each key (field name) becomes a member of the path, and
|
||||
// we recurse. First, sort the keys.
|
||||
keys := make([]string, len(t))
|
||||
i := 0
|
||||
for k := range t {
|
||||
keys[i] = k
|
||||
i++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
// Now, for each key, we recursively marshal it.
|
||||
for _, k := range keys {
|
||||
newPath := append(path, k)
|
||||
fields, err := marshalDeepObject(t[k], newPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error traversing map: %w", err)
|
||||
}
|
||||
result = append(result, fields...)
|
||||
}
|
||||
default:
|
||||
// Now, for a concrete value, we will turn the path elements
|
||||
// into a deepObject style set of subscripts. [a, b, c] turns into
|
||||
// [a][b][c]
|
||||
prefix := "[" + strings.Join(path, "][") + "]"
|
||||
result = []string{
|
||||
prefix + fmt.Sprintf("=%v", t),
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func MarshalDeepObject(i interface{}, paramName string) (string, error) {
|
||||
// We're going to marshal to JSON and unmarshal into an interface{},
|
||||
// which will use the json pkg to deal with all the field annotations. We
|
||||
// can then walk the generic object structure to produce a deepObject. This
|
||||
// isn't efficient and it would be more efficient to reflect on our own,
|
||||
// but it's complicated, error-prone code.
|
||||
buf, err := json.Marshal(i)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to marshal input to JSON: %w", err)
|
||||
}
|
||||
var i2 interface{}
|
||||
err = json.Unmarshal(buf, &i2)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to unmarshal JSON: %w", err)
|
||||
}
|
||||
fields, err := marshalDeepObject(i2, nil)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error traversing JSON structure: %w", err)
|
||||
}
|
||||
|
||||
// Prefix the param name to each subscripted field.
|
||||
for i := range fields {
|
||||
fields[i] = paramName + fields[i]
|
||||
}
|
||||
return strings.Join(fields, "&"), nil
|
||||
}
|
||||
|
||||
type fieldOrValue struct {
|
||||
fields map[string]fieldOrValue
|
||||
value string
|
||||
}
|
||||
|
||||
func (f *fieldOrValue) appendPathValue(path []string, value string) {
|
||||
fieldName := path[0]
|
||||
if len(path) == 1 {
|
||||
f.fields[fieldName] = fieldOrValue{value: value}
|
||||
return
|
||||
}
|
||||
|
||||
pv, found := f.fields[fieldName]
|
||||
if !found {
|
||||
pv = fieldOrValue{
|
||||
fields: make(map[string]fieldOrValue),
|
||||
}
|
||||
f.fields[fieldName] = pv
|
||||
}
|
||||
pv.appendPathValue(path[1:], value)
|
||||
}
|
||||
|
||||
func makeFieldOrValue(paths [][]string, values []string) fieldOrValue {
|
||||
|
||||
f := fieldOrValue{
|
||||
fields: make(map[string]fieldOrValue),
|
||||
}
|
||||
for i := range paths {
|
||||
path := paths[i]
|
||||
value := values[i]
|
||||
f.appendPathValue(path, value)
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func UnmarshalDeepObject(dst interface{}, paramName string, params url.Values) error {
|
||||
// Params are all the query args, so we need those that look like
|
||||
// "paramName["...
|
||||
var fieldNames []string
|
||||
var fieldValues []string
|
||||
searchStr := paramName + "["
|
||||
for pName, pValues := range params {
|
||||
if strings.HasPrefix(pName, searchStr) {
|
||||
// trim the parameter name from the full name.
|
||||
pName = pName[len(paramName):]
|
||||
fieldNames = append(fieldNames, pName)
|
||||
if len(pValues) != 1 {
|
||||
return fmt.Errorf("%s has multiple values", pName)
|
||||
}
|
||||
fieldValues = append(fieldValues, pValues[0])
|
||||
}
|
||||
}
|
||||
|
||||
// Now, for each field, reconstruct its subscript path and value
|
||||
paths := make([][]string, len(fieldNames))
|
||||
for i, path := range fieldNames {
|
||||
path = strings.TrimLeft(path, "[")
|
||||
path = strings.TrimRight(path, "]")
|
||||
paths[i] = strings.Split(path, "][")
|
||||
}
|
||||
|
||||
fieldPaths := makeFieldOrValue(paths, fieldValues)
|
||||
err := assignPathValues(dst, fieldPaths)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error assigning value to destination: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// This returns a field name, either using the variable name, or the json
|
||||
// annotation if that exists.
|
||||
func getFieldName(f reflect.StructField) string {
|
||||
n := f.Name
|
||||
tag, found := f.Tag.Lookup("json")
|
||||
if found {
|
||||
// If we have a json field, and the first part of it before the
|
||||
// first comma is non-empty, that's our field name.
|
||||
parts := strings.Split(tag, ",")
|
||||
if parts[0] != "" {
|
||||
n = parts[0]
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// Create a map of field names that we'll see in the deepObject to reflect
|
||||
// field indices on the given type.
|
||||
func fieldIndicesByJSONTag(i interface{}) (map[string]int, error) {
|
||||
t := reflect.TypeOf(i)
|
||||
if t.Kind() != reflect.Struct {
|
||||
return nil, errors.New("expected a struct as input")
|
||||
}
|
||||
|
||||
n := t.NumField()
|
||||
fieldMap := make(map[string]int)
|
||||
for i := 0; i < n; i++ {
|
||||
field := t.Field(i)
|
||||
fieldName := getFieldName(field)
|
||||
fieldMap[fieldName] = i
|
||||
}
|
||||
return fieldMap, nil
|
||||
}
|
||||
|
||||
func assignPathValues(dst interface{}, pathValues fieldOrValue) error {
|
||||
//t := reflect.TypeOf(dst)
|
||||
v := reflect.ValueOf(dst)
|
||||
|
||||
iv := reflect.Indirect(v)
|
||||
it := iv.Type()
|
||||
|
||||
switch it.Kind() {
|
||||
case reflect.Map:
|
||||
dstMap := reflect.MakeMap(iv.Type())
|
||||
for key, value := range pathValues.fields {
|
||||
dstKey := reflect.ValueOf(key)
|
||||
dstVal := reflect.New(iv.Type().Elem())
|
||||
err := assignPathValues(dstVal.Interface(), value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error binding map: %w", err)
|
||||
}
|
||||
dstMap.SetMapIndex(dstKey, dstVal.Elem())
|
||||
}
|
||||
iv.Set(dstMap)
|
||||
return nil
|
||||
case reflect.Slice:
|
||||
sliceLength := len(pathValues.fields)
|
||||
dstSlice := reflect.MakeSlice(it, sliceLength, sliceLength)
|
||||
err := assignSlice(dstSlice, pathValues)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error assigning slice: %w", err)
|
||||
}
|
||||
iv.Set(dstSlice)
|
||||
return nil
|
||||
case reflect.Struct:
|
||||
// Some special types we care about are structs. Handle them
|
||||
// here. They may be redefined, so we need to do some hoop
|
||||
// jumping. If the types are aliased, we need to type convert
|
||||
// the pointer, then set the value of the dereference pointer.
|
||||
|
||||
// We check to see if the object implements the Binder interface first.
|
||||
if dst, isBinder := v.Interface().(Binder); isBinder {
|
||||
return dst.Bind(pathValues.value)
|
||||
}
|
||||
// Then check the legacy types
|
||||
if it.ConvertibleTo(reflect.TypeOf(types.Date{})) {
|
||||
var date types.Date
|
||||
var err error
|
||||
date.Time, err = time.Parse(types.DateFormat, pathValues.value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid date format: %w", err)
|
||||
}
|
||||
dst := iv
|
||||
if it != reflect.TypeOf(types.Date{}) {
|
||||
// Types are aliased, convert the pointers.
|
||||
ivPtr := iv.Addr()
|
||||
aPtr := ivPtr.Convert(reflect.TypeOf(&types.Date{}))
|
||||
dst = reflect.Indirect(aPtr)
|
||||
}
|
||||
dst.Set(reflect.ValueOf(date))
|
||||
}
|
||||
if it.ConvertibleTo(reflect.TypeOf(time.Time{})) {
|
||||
var tm time.Time
|
||||
var err error
|
||||
tm, err = time.Parse(time.RFC3339Nano, pathValues.value)
|
||||
if err != nil {
|
||||
// Fall back to parsing it as a date.
|
||||
// TODO: why is this marked as an ineffassign?
|
||||
tm, err = time.Parse(types.DateFormat, pathValues.value) //nolint:ineffassign,staticcheck
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing '%s' as RFC3339 or 2006-01-02 time: %s", pathValues.value, err)
|
||||
}
|
||||
return fmt.Errorf("invalid date format: %w", err)
|
||||
}
|
||||
dst := iv
|
||||
if it != reflect.TypeOf(time.Time{}) {
|
||||
// Types are aliased, convert the pointers.
|
||||
ivPtr := iv.Addr()
|
||||
aPtr := ivPtr.Convert(reflect.TypeOf(&time.Time{}))
|
||||
dst = reflect.Indirect(aPtr)
|
||||
}
|
||||
dst.Set(reflect.ValueOf(tm))
|
||||
}
|
||||
fieldMap, err := fieldIndicesByJSONTag(iv.Interface())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed enumerating fields: %w", err)
|
||||
}
|
||||
for _, fieldName := range sortedFieldOrValueKeys(pathValues.fields) {
|
||||
fieldValue := pathValues.fields[fieldName]
|
||||
fieldIndex, found := fieldMap[fieldName]
|
||||
if !found {
|
||||
return fmt.Errorf("field [%s] is not present in destination object", fieldName)
|
||||
}
|
||||
field := iv.Field(fieldIndex)
|
||||
err = assignPathValues(field.Addr().Interface(), fieldValue)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error assigning field [%s]: %w", fieldName, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
case reflect.Ptr:
|
||||
// If we have a pointer after redirecting, it means we're dealing with
|
||||
// an optional field, such as *string, which was passed in as &foo. We
|
||||
// will allocate it if necessary, and call ourselves with a different
|
||||
// interface.
|
||||
dstVal := reflect.New(it.Elem())
|
||||
dstPtr := dstVal.Interface()
|
||||
err := assignPathValues(dstPtr, pathValues)
|
||||
iv.Set(dstVal)
|
||||
return err
|
||||
case reflect.Bool:
|
||||
val, err := strconv.ParseBool(pathValues.value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("expected a valid bool, got %s", pathValues.value)
|
||||
}
|
||||
iv.SetBool(val)
|
||||
return nil
|
||||
case reflect.Float32:
|
||||
val, err := strconv.ParseFloat(pathValues.value, 32)
|
||||
if err != nil {
|
||||
return fmt.Errorf("expected a valid float, got %s", pathValues.value)
|
||||
}
|
||||
iv.SetFloat(val)
|
||||
return nil
|
||||
case reflect.Float64:
|
||||
val, err := strconv.ParseFloat(pathValues.value, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("expected a valid float, got %s", pathValues.value)
|
||||
}
|
||||
iv.SetFloat(val)
|
||||
return nil
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
val, err := strconv.ParseInt(pathValues.value, 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("expected a valid int, got %s", pathValues.value)
|
||||
}
|
||||
iv.SetInt(val)
|
||||
return nil
|
||||
case reflect.String:
|
||||
iv.SetString(pathValues.value)
|
||||
return nil
|
||||
default:
|
||||
return errors.New("unhandled type: " + it.String())
|
||||
}
|
||||
}
|
||||
|
||||
func assignSlice(dst reflect.Value, pathValues fieldOrValue) error {
|
||||
// Gather up the values
|
||||
nValues := len(pathValues.fields)
|
||||
values := make([]string, nValues)
|
||||
// We expect to have consecutive array indices in the map
|
||||
for i := 0; i < nValues; i++ {
|
||||
indexStr := strconv.Itoa(i)
|
||||
fv, found := pathValues.fields[indexStr]
|
||||
if !found {
|
||||
return errors.New("array deepObjects must have consecutive indices")
|
||||
}
|
||||
values[i] = fv.value
|
||||
}
|
||||
|
||||
// This could be cleaner, but we can call into assignPathValues to
|
||||
// avoid recreating this logic.
|
||||
for i := 0; i < nValues; i++ {
|
||||
dstElem := dst.Index(i).Addr()
|
||||
err := assignPathValues(dstElem.Interface(), fieldOrValue{value: values[i]})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error binding array: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func sortedFieldOrValueKeys(m map[string]fieldOrValue) []string {
|
||||
keys := make([]string, 0, len(m))
|
||||
for k := range m {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
34
vendor/github.com/oapi-codegen/runtime/jsonmerge.go
generated
vendored
Normal file
34
vendor/github.com/oapi-codegen/runtime/jsonmerge.go
generated
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
package runtime
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/apapsch/go-jsonmerge/v2"
|
||||
)
|
||||
|
||||
// JsonMerge merges two JSON representation into a single object. `data` is the
|
||||
// existing representation and `patch` is the new data to be merged in
|
||||
//
|
||||
// Deprecated: Use JSONMerge instead.
|
||||
func JsonMerge(data, patch json.RawMessage) (json.RawMessage, error) {
|
||||
return JSONMerge(data, patch)
|
||||
}
|
||||
|
||||
// JSONMerge merges two JSON representation into a single object. `data` is the
|
||||
// existing representation and `patch` is the new data to be merged in
|
||||
func JSONMerge(data, patch json.RawMessage) (json.RawMessage, error) {
|
||||
merger := jsonmerge.Merger{
|
||||
CopyNonexistent: true,
|
||||
}
|
||||
if data == nil {
|
||||
data = []byte(`{}`)
|
||||
}
|
||||
if patch == nil {
|
||||
patch = []byte(`{}`)
|
||||
}
|
||||
merged, err := merger.MergeBytes(data, patch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return merged, nil
|
||||
}
|
||||
6
vendor/github.com/oapi-codegen/runtime/renovate.json
generated
vendored
Normal file
6
vendor/github.com/oapi-codegen/runtime/renovate.json
generated
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"local>oapi-codegen/renovate-config"
|
||||
]
|
||||
}
|
||||
478
vendor/github.com/oapi-codegen/runtime/styleparam.go
generated
vendored
Normal file
478
vendor/github.com/oapi-codegen/runtime/styleparam.go
generated
vendored
Normal file
|
|
@ -0,0 +1,478 @@
|
|||
// Copyright 2019 DeepMap, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/oapi-codegen/runtime/types"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// Parameter escaping works differently based on where a header is found
|
||||
|
||||
type ParamLocation int
|
||||
|
||||
const (
|
||||
ParamLocationUndefined ParamLocation = iota
|
||||
ParamLocationQuery
|
||||
ParamLocationPath
|
||||
ParamLocationHeader
|
||||
ParamLocationCookie
|
||||
)
|
||||
|
||||
// StyleParam is used by older generated code, and must remain compatible
|
||||
// with that code. It is not to be used in new templates. Please see the
|
||||
// function below, which can specialize its output based on the location of
|
||||
// the parameter.
|
||||
func StyleParam(style string, explode bool, paramName string, value interface{}) (string, error) {
|
||||
return StyleParamWithLocation(style, explode, paramName, ParamLocationUndefined, value)
|
||||
}
|
||||
|
||||
// Given an input value, such as a primitive type, array or object, turn it
|
||||
// into a parameter based on style/explode definition, performing whatever
|
||||
// escaping is necessary based on parameter location
|
||||
func StyleParamWithLocation(style string, explode bool, paramName string, paramLocation ParamLocation, value interface{}) (string, error) {
|
||||
t := reflect.TypeOf(value)
|
||||
v := reflect.ValueOf(value)
|
||||
|
||||
// Things may be passed in by pointer, we need to dereference, so return
|
||||
// error on nil.
|
||||
if t.Kind() == reflect.Ptr {
|
||||
if v.IsNil() {
|
||||
return "", fmt.Errorf("value is a nil pointer")
|
||||
}
|
||||
v = reflect.Indirect(v)
|
||||
t = v.Type()
|
||||
}
|
||||
|
||||
// If the value implements encoding.TextMarshaler we use it for marshaling
|
||||
// https://github.com/deepmap/oapi-codegen/issues/504
|
||||
if tu, ok := value.(encoding.TextMarshaler); ok {
|
||||
t := reflect.Indirect(reflect.ValueOf(value)).Type()
|
||||
convertableToTime := t.ConvertibleTo(reflect.TypeOf(time.Time{}))
|
||||
convertableToDate := t.ConvertibleTo(reflect.TypeOf(types.Date{}))
|
||||
|
||||
// Since both time.Time and types.Date implement encoding.TextMarshaler
|
||||
// we should avoid calling theirs MarshalText()
|
||||
if !convertableToTime && !convertableToDate {
|
||||
b, err := tu.MarshalText()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error marshaling '%s' as text: %s", value, err)
|
||||
}
|
||||
|
||||
return stylePrimitive(style, explode, paramName, paramLocation, string(b))
|
||||
}
|
||||
}
|
||||
|
||||
switch t.Kind() {
|
||||
case reflect.Slice:
|
||||
n := v.Len()
|
||||
sliceVal := make([]interface{}, n)
|
||||
for i := 0; i < n; i++ {
|
||||
sliceVal[i] = v.Index(i).Interface()
|
||||
}
|
||||
return styleSlice(style, explode, paramName, paramLocation, sliceVal)
|
||||
case reflect.Struct:
|
||||
return styleStruct(style, explode, paramName, paramLocation, value)
|
||||
case reflect.Map:
|
||||
return styleMap(style, explode, paramName, paramLocation, value)
|
||||
default:
|
||||
return stylePrimitive(style, explode, paramName, paramLocation, value)
|
||||
}
|
||||
}
|
||||
|
||||
func styleSlice(style string, explode bool, paramName string, paramLocation ParamLocation, values []interface{}) (string, error) {
|
||||
if style == "deepObject" {
|
||||
if !explode {
|
||||
return "", errors.New("deepObjects must be exploded")
|
||||
}
|
||||
return MarshalDeepObject(values, paramName)
|
||||
}
|
||||
|
||||
var prefix string
|
||||
var separator string
|
||||
|
||||
switch style {
|
||||
case "simple":
|
||||
separator = ","
|
||||
case "label":
|
||||
prefix = "."
|
||||
if explode {
|
||||
separator = "."
|
||||
} else {
|
||||
separator = ","
|
||||
}
|
||||
case "matrix":
|
||||
prefix = fmt.Sprintf(";%s=", paramName)
|
||||
if explode {
|
||||
separator = prefix
|
||||
} else {
|
||||
separator = ","
|
||||
}
|
||||
case "form":
|
||||
prefix = fmt.Sprintf("%s=", paramName)
|
||||
if explode {
|
||||
separator = "&" + prefix
|
||||
} else {
|
||||
separator = ","
|
||||
}
|
||||
case "spaceDelimited":
|
||||
prefix = fmt.Sprintf("%s=", paramName)
|
||||
if explode {
|
||||
separator = "&" + prefix
|
||||
} else {
|
||||
separator = " "
|
||||
}
|
||||
case "pipeDelimited":
|
||||
prefix = fmt.Sprintf("%s=", paramName)
|
||||
if explode {
|
||||
separator = "&" + prefix
|
||||
} else {
|
||||
separator = "|"
|
||||
}
|
||||
default:
|
||||
return "", fmt.Errorf("unsupported style '%s'", style)
|
||||
}
|
||||
|
||||
// We're going to assume here that the array is one of simple types.
|
||||
var err error
|
||||
var part string
|
||||
parts := make([]string, len(values))
|
||||
for i, v := range values {
|
||||
part, err = primitiveToString(v)
|
||||
part = escapeParameterString(part, paramLocation)
|
||||
parts[i] = part
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error formatting '%s': %s", paramName, err)
|
||||
}
|
||||
}
|
||||
return prefix + strings.Join(parts, separator), nil
|
||||
}
|
||||
|
||||
func sortedKeys(strMap map[string]string) []string {
|
||||
keys := make([]string, len(strMap))
|
||||
i := 0
|
||||
for k := range strMap {
|
||||
keys[i] = k
|
||||
i++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
// These are special cases. The value may be a date, time, or uuid,
|
||||
// in which case, marshal it into the correct format.
|
||||
func marshalKnownTypes(value interface{}) (string, bool) {
|
||||
v := reflect.Indirect(reflect.ValueOf(value))
|
||||
t := v.Type()
|
||||
|
||||
if t.ConvertibleTo(reflect.TypeOf(time.Time{})) {
|
||||
tt := v.Convert(reflect.TypeOf(time.Time{}))
|
||||
timeVal := tt.Interface().(time.Time)
|
||||
return timeVal.Format(time.RFC3339Nano), true
|
||||
}
|
||||
|
||||
if t.ConvertibleTo(reflect.TypeOf(types.Date{})) {
|
||||
d := v.Convert(reflect.TypeOf(types.Date{}))
|
||||
dateVal := d.Interface().(types.Date)
|
||||
return dateVal.Format(types.DateFormat), true
|
||||
}
|
||||
|
||||
if t.ConvertibleTo(reflect.TypeOf(types.UUID{})) {
|
||||
u := v.Convert(reflect.TypeOf(types.UUID{}))
|
||||
uuidVal := u.Interface().(types.UUID)
|
||||
return uuidVal.String(), true
|
||||
}
|
||||
|
||||
return "", false
|
||||
}
|
||||
|
||||
func styleStruct(style string, explode bool, paramName string, paramLocation ParamLocation, value interface{}) (string, error) {
|
||||
if timeVal, ok := marshalKnownTypes(value); ok {
|
||||
styledVal, err := stylePrimitive(style, explode, paramName, paramLocation, timeVal)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to style time: %w", err)
|
||||
}
|
||||
return styledVal, nil
|
||||
}
|
||||
|
||||
if style == "deepObject" {
|
||||
if !explode {
|
||||
return "", errors.New("deepObjects must be exploded")
|
||||
}
|
||||
return MarshalDeepObject(value, paramName)
|
||||
}
|
||||
|
||||
// If input has Marshaler, such as object has Additional Property or AnyOf,
|
||||
// We use this Marshaler and convert into interface{} before styling.
|
||||
if m, ok := value.(json.Marshaler); ok {
|
||||
buf, err := m.MarshalJSON()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to marshal input to JSON: %w", err)
|
||||
}
|
||||
e := json.NewDecoder(bytes.NewReader(buf))
|
||||
e.UseNumber()
|
||||
var i2 interface{}
|
||||
err = e.Decode(&i2)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to unmarshal JSON: %w", err)
|
||||
}
|
||||
s, err := StyleParamWithLocation(style, explode, paramName, paramLocation, i2)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error style JSON structure: %w", err)
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Otherwise, we need to build a dictionary of the struct's fields. Each
|
||||
// field may only be a primitive value.
|
||||
v := reflect.ValueOf(value)
|
||||
t := reflect.TypeOf(value)
|
||||
fieldDict := make(map[string]string)
|
||||
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
fieldT := t.Field(i)
|
||||
// Find the json annotation on the field, and use the json specified
|
||||
// name if available, otherwise, just the field name.
|
||||
tag := fieldT.Tag.Get("json")
|
||||
fieldName := fieldT.Name
|
||||
if tag != "" {
|
||||
tagParts := strings.Split(tag, ",")
|
||||
name := tagParts[0]
|
||||
if name != "" {
|
||||
fieldName = name
|
||||
}
|
||||
}
|
||||
f := v.Field(i)
|
||||
|
||||
// Unset optional fields will be nil pointers, skip over those.
|
||||
if f.Type().Kind() == reflect.Ptr && f.IsNil() {
|
||||
continue
|
||||
}
|
||||
str, err := primitiveToString(f.Interface())
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error formatting '%s': %s", paramName, err)
|
||||
}
|
||||
fieldDict[fieldName] = str
|
||||
}
|
||||
|
||||
return processFieldDict(style, explode, paramName, paramLocation, fieldDict)
|
||||
}
|
||||
|
||||
func styleMap(style string, explode bool, paramName string, paramLocation ParamLocation, value interface{}) (string, error) {
|
||||
if style == "deepObject" {
|
||||
if !explode {
|
||||
return "", errors.New("deepObjects must be exploded")
|
||||
}
|
||||
return MarshalDeepObject(value, paramName)
|
||||
}
|
||||
|
||||
dict, ok := value.(map[string]interface{})
|
||||
if !ok {
|
||||
return "", errors.New("map not of type map[string]interface{}")
|
||||
}
|
||||
|
||||
fieldDict := make(map[string]string)
|
||||
for fieldName, value := range dict {
|
||||
str, err := primitiveToString(value)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error formatting '%s': %s", paramName, err)
|
||||
}
|
||||
fieldDict[fieldName] = str
|
||||
}
|
||||
return processFieldDict(style, explode, paramName, paramLocation, fieldDict)
|
||||
}
|
||||
|
||||
func processFieldDict(style string, explode bool, paramName string, paramLocation ParamLocation, fieldDict map[string]string) (string, error) {
|
||||
var parts []string
|
||||
|
||||
// This works for everything except deepObject. We'll handle that one
|
||||
// separately.
|
||||
if style != "deepObject" {
|
||||
if explode {
|
||||
for _, k := range sortedKeys(fieldDict) {
|
||||
v := escapeParameterString(fieldDict[k], paramLocation)
|
||||
parts = append(parts, k+"="+v)
|
||||
}
|
||||
} else {
|
||||
for _, k := range sortedKeys(fieldDict) {
|
||||
v := escapeParameterString(fieldDict[k], paramLocation)
|
||||
parts = append(parts, k)
|
||||
parts = append(parts, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var prefix string
|
||||
var separator string
|
||||
|
||||
switch style {
|
||||
case "simple":
|
||||
separator = ","
|
||||
case "label":
|
||||
prefix = "."
|
||||
if explode {
|
||||
separator = prefix
|
||||
} else {
|
||||
separator = ","
|
||||
}
|
||||
case "matrix":
|
||||
if explode {
|
||||
separator = ";"
|
||||
prefix = ";"
|
||||
} else {
|
||||
separator = ","
|
||||
prefix = fmt.Sprintf(";%s=", paramName)
|
||||
}
|
||||
case "form":
|
||||
if explode {
|
||||
separator = "&"
|
||||
} else {
|
||||
prefix = fmt.Sprintf("%s=", paramName)
|
||||
separator = ","
|
||||
}
|
||||
case "deepObject":
|
||||
{
|
||||
if !explode {
|
||||
return "", fmt.Errorf("deepObject parameters must be exploded")
|
||||
}
|
||||
for _, k := range sortedKeys(fieldDict) {
|
||||
v := fieldDict[k]
|
||||
part := fmt.Sprintf("%s[%s]=%s", paramName, k, v)
|
||||
parts = append(parts, part)
|
||||
}
|
||||
separator = "&"
|
||||
}
|
||||
default:
|
||||
return "", fmt.Errorf("unsupported style '%s'", style)
|
||||
}
|
||||
|
||||
return prefix + strings.Join(parts, separator), nil
|
||||
}
|
||||
|
||||
func stylePrimitive(style string, explode bool, paramName string, paramLocation ParamLocation, value interface{}) (string, error) {
|
||||
strVal, err := primitiveToString(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var prefix string
|
||||
switch style {
|
||||
case "simple":
|
||||
case "label":
|
||||
prefix = "."
|
||||
case "matrix":
|
||||
prefix = fmt.Sprintf(";%s=", paramName)
|
||||
case "form":
|
||||
prefix = fmt.Sprintf("%s=", paramName)
|
||||
default:
|
||||
return "", fmt.Errorf("unsupported style '%s'", style)
|
||||
}
|
||||
return prefix + escapeParameterString(strVal, paramLocation), nil
|
||||
}
|
||||
|
||||
// Converts a primitive value to a string. We need to do this based on the
|
||||
// Kind of an interface, not the Type to work with aliased types.
|
||||
func primitiveToString(value interface{}) (string, error) {
|
||||
var output string
|
||||
|
||||
// sometimes time and date used like primitive types
|
||||
// it can happen if paramether is object and has time or date as field
|
||||
if res, ok := marshalKnownTypes(value); ok {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Values may come in by pointer for optionals, so make sure to dereferene.
|
||||
v := reflect.Indirect(reflect.ValueOf(value))
|
||||
t := v.Type()
|
||||
kind := t.Kind()
|
||||
|
||||
switch kind {
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
||||
output = strconv.FormatInt(v.Int(), 10)
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||
output = strconv.FormatUint(v.Uint(), 10)
|
||||
case reflect.Float64:
|
||||
output = strconv.FormatFloat(v.Float(), 'f', -1, 64)
|
||||
case reflect.Float32:
|
||||
output = strconv.FormatFloat(v.Float(), 'f', -1, 32)
|
||||
case reflect.Bool:
|
||||
if v.Bool() {
|
||||
output = "true"
|
||||
} else {
|
||||
output = "false"
|
||||
}
|
||||
case reflect.String:
|
||||
output = v.String()
|
||||
case reflect.Struct:
|
||||
// If input has Marshaler, such as object has Additional Property or AnyOf,
|
||||
// We use this Marshaler and convert into interface{} before styling.
|
||||
if v, ok := value.(uuid.UUID); ok {
|
||||
output = v.String()
|
||||
break
|
||||
}
|
||||
if m, ok := value.(json.Marshaler); ok {
|
||||
buf, err := m.MarshalJSON()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to marshal input to JSON: %w", err)
|
||||
}
|
||||
e := json.NewDecoder(bytes.NewReader(buf))
|
||||
e.UseNumber()
|
||||
var i2 interface{}
|
||||
err = e.Decode(&i2)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to unmarshal JSON: %w", err)
|
||||
}
|
||||
output, err = primitiveToString(i2)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error convert JSON structure: %w", err)
|
||||
}
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
default:
|
||||
v, ok := value.(fmt.Stringer)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("unsupported type %s", reflect.TypeOf(value).String())
|
||||
}
|
||||
|
||||
output = v.String()
|
||||
}
|
||||
return output, nil
|
||||
}
|
||||
|
||||
// escapeParameterString escapes a parameter value bas on the location of that parameter.
|
||||
// Query params and path params need different kinds of escaping, while header
|
||||
// and cookie params seem not to need escaping.
|
||||
func escapeParameterString(value string, paramLocation ParamLocation) string {
|
||||
switch paramLocation {
|
||||
case ParamLocationQuery:
|
||||
return url.QueryEscape(value)
|
||||
case ParamLocationPath:
|
||||
return url.PathEscape(value)
|
||||
default:
|
||||
return value
|
||||
}
|
||||
}
|
||||
43
vendor/github.com/oapi-codegen/runtime/types/date.go
generated
vendored
Normal file
43
vendor/github.com/oapi-codegen/runtime/types/date.go
generated
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
const DateFormat = "2006-01-02"
|
||||
|
||||
type Date struct {
|
||||
time.Time
|
||||
}
|
||||
|
||||
func (d Date) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(d.Time.Format(DateFormat))
|
||||
}
|
||||
|
||||
func (d *Date) UnmarshalJSON(data []byte) error {
|
||||
var dateStr string
|
||||
err := json.Unmarshal(data, &dateStr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
parsed, err := time.Parse(DateFormat, dateStr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.Time = parsed
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d Date) String() string {
|
||||
return d.Time.Format(DateFormat)
|
||||
}
|
||||
|
||||
func (d *Date) UnmarshalText(data []byte) error {
|
||||
parsed, err := time.Parse(DateFormat, string(data))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.Time = parsed
|
||||
return nil
|
||||
}
|
||||
40
vendor/github.com/oapi-codegen/runtime/types/email.go
generated
vendored
Normal file
40
vendor/github.com/oapi-codegen/runtime/types/email.go
generated
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// ErrValidationEmail is the sentinel error returned when an email fails validation
|
||||
var ErrValidationEmail = errors.New("email: failed to pass regex validation")
|
||||
|
||||
// Email represents an email address.
|
||||
// It is a string type that must pass regex validation before being marshalled
|
||||
// to JSON or unmarshalled from JSON.
|
||||
type Email string
|
||||
|
||||
func (e Email) MarshalJSON() ([]byte, error) {
|
||||
if !emailRegex.MatchString(string(e)) {
|
||||
return nil, ErrValidationEmail
|
||||
}
|
||||
|
||||
return json.Marshal(string(e))
|
||||
}
|
||||
|
||||
func (e *Email) UnmarshalJSON(data []byte) error {
|
||||
if e == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var s string
|
||||
if err := json.Unmarshal(data, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*e = Email(s)
|
||||
if !emailRegex.MatchString(s) {
|
||||
return ErrValidationEmail
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
71
vendor/github.com/oapi-codegen/runtime/types/file.go
generated
vendored
Normal file
71
vendor/github.com/oapi-codegen/runtime/types/file.go
generated
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
)
|
||||
|
||||
type File struct {
|
||||
multipart *multipart.FileHeader
|
||||
data []byte
|
||||
filename string
|
||||
}
|
||||
|
||||
func (file *File) InitFromMultipart(header *multipart.FileHeader) {
|
||||
file.multipart = header
|
||||
file.data = nil
|
||||
file.filename = ""
|
||||
}
|
||||
|
||||
func (file *File) InitFromBytes(data []byte, filename string) {
|
||||
file.data = data
|
||||
file.filename = filename
|
||||
file.multipart = nil
|
||||
}
|
||||
|
||||
func (file File) MarshalJSON() ([]byte, error) {
|
||||
b, err := file.Bytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(b)
|
||||
}
|
||||
|
||||
func (file *File) UnmarshalJSON(data []byte) error {
|
||||
return json.Unmarshal(data, &file.data)
|
||||
}
|
||||
|
||||
func (file File) Bytes() ([]byte, error) {
|
||||
if file.multipart != nil {
|
||||
f, err := file.multipart.Open()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() { _ = f.Close() }()
|
||||
return io.ReadAll(f)
|
||||
}
|
||||
return file.data, nil
|
||||
}
|
||||
|
||||
func (file File) Reader() (io.ReadCloser, error) {
|
||||
if file.multipart != nil {
|
||||
return file.multipart.Open()
|
||||
}
|
||||
return io.NopCloser(bytes.NewReader(file.data)), nil
|
||||
}
|
||||
|
||||
func (file File) Filename() string {
|
||||
if file.multipart != nil {
|
||||
return file.multipart.Filename
|
||||
}
|
||||
return file.filename
|
||||
}
|
||||
|
||||
func (file File) FileSize() int64 {
|
||||
if file.multipart != nil {
|
||||
return file.multipart.Size
|
||||
}
|
||||
return int64(len(file.data))
|
||||
}
|
||||
11
vendor/github.com/oapi-codegen/runtime/types/regexes.go
generated
vendored
Normal file
11
vendor/github.com/oapi-codegen/runtime/types/regexes.go
generated
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
package types
|
||||
|
||||
import "regexp"
|
||||
|
||||
const (
|
||||
emailRegexString = "^(?:(?:(?:(?:[a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(?:\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|(?:(?:\\x22)(?:(?:(?:(?:\\x20|\\x09)*(?:\\x0d\\x0a))?(?:\\x20|\\x09)+)?(?:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(?:(?:[\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(?:(?:(?:\\x20|\\x09)*(?:\\x0d\\x0a))?(\\x20|\\x09)+)?(?:\\x22))))@(?:(?:(?:[a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(?:(?:[a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])(?:[a-zA-Z]|\\d|-|\\.|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*(?:[a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(?:(?:[a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(?:(?:[a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])(?:[a-zA-Z]|\\d|-|\\.|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*(?:[a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$"
|
||||
)
|
||||
|
||||
var (
|
||||
emailRegex = regexp.MustCompile(emailRegexString)
|
||||
)
|
||||
7
vendor/github.com/oapi-codegen/runtime/types/uuid.go
generated
vendored
Normal file
7
vendor/github.com/oapi-codegen/runtime/types/uuid.go
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type UUID = uuid.UUID
|
||||
Loading…
Add table
Add a link
Reference in a new issue