Documentation
¶
Overview ¶
Package loads provides document loading methods for swagger (OAI v2) API specifications.
It is used by other go-openapi packages to load and run analysis on local or remote spec documents.
Loaders support JSON and YAML documents.
Security ¶
This package does not enforce a security policy of its own: like the underlying github.com/go-openapi/swag/loading utilities, it reads whatever the configured loader is allowed to read.
When a spec — its path or its contents — may derive from untrusted input, the caller must confine loading explicitly.
This is a deliberate design choice. Both this package and the github.com/go-openapi/swag/loading utilities are base building blocks: deciding which sources are legitimate, and containing access to them, requires application context that a general-purpose loader does not have.
Just as sanitizing a file name before handing it to os.ReadFile is the caller's responsibility and not that function's, sanitizing and containing the path and references resolved here is the responsibility of the code that may feed them untrusted input.
There are two distinct attack surfaces:
The path passed to Spec, JSONSpec, or Embedded. By default a local path is read with no confinement, so a caller-controlled path (including an absolute path or a "file:///etc/passwd" URI) may read any file the process can access. A remote path is fetched with net/http.DefaultClient, which follows redirects and performs no destination filtering, so a caller-controlled URL may reach internal services or cloud metadata endpoints (server-side request forgery).
The contents of the spec, when references are resolved. Document.Expanded follows the "$ref" pointers found inside the document by calling the same loader recursively. A spec obtained even from a trusted path can therefore drive arbitrary local reads ("$ref": "file:///etc/passwd") or SSRF ("$ref": "http://169.254.169.254/...") through its own contents. This amplification is specific to reference resolution and does not exist in the raw loading utilities.
Mitigation. Pass github.com/go-openapi/swag/loading options through WithLoadingOptions; they are attached to the document's loader and so apply both to the initial load and to every "$ref" resolved during expansion:
github.com/go-openapi/swag/loading.WithRoot confines local reads to a trusted directory, rejecting absolute paths, ".." traversal, and symlinks that escape it. Prefer it over a github.com/go-openapi/swag/loading.WithFS built from os.DirFS, which does not block symlink escapes.
github.com/go-openapi/swag/loading.WithHTTPClient allows to supply a restricted HTTP client. Enforce the network policy at dial time (a net.Dialer Control hook), so it also covers redirects and DNS rebinding, which a URL-string allowlist cannot. See the example on Spec.
Pre-baked loaders. When the opinionated defaults fit, SpecRestricted, JSONSpecRestricted and JSONDocRestricted bundle a trusted root with a network-restricted client (RestrictedHTTPClient), and apply the confinement to "$ref" resolution as well — so the common case needs no manual wiring. To harden the global default in one call (so even callers that rely on the package-level loader are confined), use SetRestrictedLoaders. Reach for the options above when you need a custom policy; IsForbiddenAddress exposes the default network policy so you can reuse it as the base of your own HTTP client.
Caveats:
The package-level default loader (also installed as github.com/go-openapi/spec.PathLoader) carries no loading options and is therefore unconfined. It is used as a fallback when expansion runs without a document loader, and by other go-openapi packages that resolve references on their own. AddLoader does not fix this — it only prepends, leaving the unconfined fallback reachable. Either build a confined loader per call, or replace the global default outright with SetLoaders / SetRestrictedLoaders.
A custom loader installed via WithDocLoader or AddLoader only honors these protections if its loading function actually applies the github.com/go-openapi/swag/loading options it is given.
Index ¶
- Constants
- func AddLoader(predicate DocMatcher, load DocLoader)
- func IsForbiddenAddress(addr netip.Addr) bool
- func JSONDoc(path string, opts ...loading.Option) (json.RawMessage, error)
- func RestrictedHTTPClient() *http.Client
- func SetLoaders(ldrs ...DocLoaderWithMatch)
- func SetRestrictedLoaders(root string, opts ...loading.Option)
- type DocLoader
- type DocLoaderWithMatch
- type DocMatcher
- type Document
- func Analyzed(data json.RawMessage, version string, options ...LoaderOption) (*Document, error)
- func Embedded(orig, flat json.RawMessage, opts ...LoaderOption) (*Document, error)
- func JSONSpec(path string, opts ...LoaderOption) (*Document, error)
- func JSONSpecRestricted(path, root string, opts ...loading.Option) (*Document, error)
- func Spec(path string, opts ...LoaderOption) (*Document, error)
- func SpecRestricted(path, root string, opts ...loading.Option) (*Document, error)
- func (d *Document) BasePath() string
- func (d *Document) Expanded(options ...*spec.ExpandOptions) (*Document, error)
- func (d *Document) Host() string
- func (d *Document) OrigSpec() *spec.Swagger
- func (d *Document) Pristine() *Document
- func (d *Document) Raw() json.RawMessage
- func (d *Document) ResetDefinitions() *Document
- func (d *Document) Schema() *spec.Schema
- func (d *Document) Spec() *spec.Swagger
- func (d *Document) SpecFilePath() string
- func (d *Document) Version() string
- type LoaderOption
Examples ¶
Constants ¶
const ( // ErrLoads is an error returned by the loads package. ErrLoads loaderError = "loaderrs error" // ErrNoLoader indicates that no configured loader matched the input. ErrNoLoader loaderError = "no loader matched" // ErrForbiddenAddress is returned by [RestrictedHTTPClient] when a connection is attempted // to a non-public address (loopback, private, link-local, or unspecified). ErrForbiddenAddress loaderError = "blocked dial to a non-public address" )
Variables ¶
This section is empty.
Functions ¶
func AddLoader ¶
func AddLoader(predicate DocMatcher, load DocLoader)
AddLoader for a document, executed before other previously set loaders.
This sets the configuration at the package level.
Concurrency ¶
This function updates the default loader used by github.com/go-openapi/spec. Since this sets package level globals, you shouldn't call this concurrently.
Security ¶
AddLoader only *prepends* to the default chain: the previous loaders — including the unconfined JSON fallback — remain reachable, both here and via cross-package "$ref" resolution. It is therefore the wrong tool for hardening the global default. To replace the chain entirely (leaving no unconfined fallback) use SetLoaders, or SetRestrictedLoaders for a one-call confined setup. For a single load, prefer a confined per-call loader via WithLoadingOptions or WithDocLoaderMatches. A custom loader registered here only honors the protections if its loading function applies the github.com/go-openapi/swag/loading options it is given. See the package documentation on Security.
func IsForbiddenAddress ¶ added in v0.24.0
IsForbiddenAddress reports whether addr is one that RestrictedHTTPClient refuses to dial: a loopback, private, link-local (including cloud-metadata endpoints such as 169.254.169.254), or unspecified address. IPv4-mapped IPv6 addresses are unmapped before the check.
It is exported so callers can reuse or extend the default policy when building their own dialer Control hook, for example to also reject a CGNAT range or to carve out a single trusted internal host:
control := func(_, address string, _ syscall.RawConn) error {
host, _, err := net.SplitHostPort(address)
if err != nil {
return err
}
addr, err := netip.ParseAddr(host)
if err != nil {
return err
}
if loads.IsForbiddenAddress(addr) && host != allowedInternalHost {
return loads.ErrForbiddenAddress
}
return nil
}
func JSONDoc ¶
JSONDoc loads a json document from either a file or a remote URL.
See loading.Option for available options (e.g. configuring authentication, headers or using embedded file system resources).
func RestrictedHTTPClient ¶ added in v0.24.0
RestrictedHTTPClient returns an http.Client that refuses, at dial time, to connect to loopback, private, link-local (including cloud-metadata endpoints such as 169.254.169.254), or unspecified addresses. A blocked connection fails with an error wrapping ErrForbiddenAddress.
The check runs in the dialer Control hook, after DNS resolution and before connect, so it also covers HTTP redirects and DNS rebinding — which a URL-string allowlist cannot. The client does not honor proxy environment variables, so the guard always inspects the real destination rather than a proxy address.
This is the network half of the restricted loaders (JSONDocRestricted, JSONSpecRestricted, SpecRestricted). It may also be used directly with github.com/go-openapi/swag/loading.WithHTTPClient.
The policy is opinionated and deliberately simple. For a different one (a custom allow/deny list, an explicit proxy, mutual TLS, ...), build your own client and pass it with github.com/go-openapi/swag/loading.WithHTTPClient. To keep the default address policy as a base, reuse IsForbiddenAddress in your own dialer Control hook — see the package examples for the pattern.
func SetLoaders ¶ added in v0.24.0
func SetLoaders(ldrs ...DocLoaderWithMatch)
SetLoaders replaces the package-level default loader chain with the given loaders, tried in order, and re-points github.com/go-openapi/spec.PathLoader at it.
Unlike AddLoader, nothing of the previous default survives — so when the replacement is confined, no unconfined fallback remains for any caller relying on the global default (including cross-package "$ref" resolution). An entry with a nil Match is a catch-all; you are responsible for providing a suitable fallback. Calling SetLoaders with no usable loader restores the built-in default (a YAML matcher with a JSON fallback).
Concurrency ¶
This sets package-level globals and the github.com/go-openapi/spec global loader. It is not safe to call concurrently with other loads or with AddLoader; configure it once at startup, before serving.
Security ¶
This is the way to harden the global default in one place. For a ready-made confined setup, see SetRestrictedLoaders. As with AddLoader, a custom loader only honors the protections if its loading function applies the github.com/go-openapi/swag/loading options it is given. See the package documentation on Security.
func SetRestrictedLoaders ¶ added in v0.24.0
SetRestrictedLoaders hardens the package-level default in a single call: it installs a confined JSON/YAML loader chain — local reads rooted at root, remote fetches through RestrictedHTTPClient — as the global default and as github.com/go-openapi/spec.PathLoader.
After this call, every load that relies on the package default (Spec, JSONSpec, and any cross-package "$ref" resolution) is confined, with no unconfined fallback left behind. It is the global counterpart of SpecRestricted; a single restricted client is shared across the chain. Extra github.com/go-openapi/swag/loading options may be supplied; the confinement always wins over them.
Concurrency ¶
Like SetLoaders, this mutates package-level and github.com/go-openapi/spec globals and is not safe to call concurrently. Configure it once at startup, before serving. To revert, call SetLoaders with no arguments.
Example ¶
ExampleSetRestrictedLoaders shows how to harden the package-level default in a single call, so every subsequent load — and every cross-package "$ref" resolution through spec.PathLoader — is confined, with no unconfined fallback left behind. Prefer this to AddLoader, which only prepends and leaves the unconfined default reachable.
package main
import (
"fmt"
"github.com/go-openapi/loads"
)
func main() {
loads.SetRestrictedLoaders("fixtures/yaml")
defer loads.SetLoaders() // restore the built-in default
doc, err := loads.Spec("swagger/spec.yml")
if err != nil {
panic(err)
}
fmt.Println(doc.Host())
_, err = loads.Spec("../../../../etc/passwd")
fmt.Println("escape blocked:", err != nil)
}
Output: api.example.com escape blocked: true
Types ¶
type DocLoader ¶
DocLoader represents a doc loader type.
func JSONDocRestricted ¶ added in v0.24.0
JSONDocRestricted returns a JSON DocLoader that confines local reads to root (via github.com/go-openapi/swag/loading.WithRoot) and restricts remote fetches with RestrictedHTTPClient.
The returned loader may be registered with WithDocLoader or AddLoader. The confinement always takes precedence over any option passed here or at call time, so a caller cannot loosen it through WithLoadingOptions.
Like JSONDoc, it loads JSON only: it does not convert YAML. For specs whose references may point at YAML documents, prefer SpecRestricted, which keeps the default JSON/YAML chain.
type DocLoaderWithMatch ¶ added in v0.20.0
type DocLoaderWithMatch struct {
Fn DocLoader
Match DocMatcher
}
DocLoaderWithMatch describes a loading function for a given extension match.
func NewDocLoaderWithMatch ¶ added in v0.20.0
func NewDocLoaderWithMatch(fn DocLoader, matcher DocMatcher) DocLoaderWithMatch
NewDocLoaderWithMatch builds a DocLoaderWithMatch to be used in load options.
type DocMatcher ¶
DocMatcher represents a predicate to check if a loader matches.
type Document ¶
type Document struct {
// specAnalyzer
Analyzer *analysis.Spec
// contains filtered or unexported fields
}
Document represents a swagger spec document.
func Analyzed ¶
func Analyzed(data json.RawMessage, version string, options ...LoaderOption) (*Document, error)
Analyzed creates a new analyzed spec document for a root json.RawMessage.
func Embedded ¶
func Embedded(orig, flat json.RawMessage, opts ...LoaderOption) (*Document, error)
Embedded returns a Document based on embedded specs (i.e. as a json.RawMessage). No analysis is required.
func JSONSpec ¶
func JSONSpec(path string, opts ...LoaderOption) (*Document, error)
JSONSpec loads a spec from a JSON document, using the JSONDoc loader.
A set of loading.Option may be passed to this loader using WithLoadingOptions.
Example (Http_custom_header) ¶
Loads a JSON document from http, with a custom header.
package main
import (
"fmt"
"io"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"github.com/go-openapi/loads"
"github.com/go-openapi/swag/loading"
)
func main() {
ts := serveSomeJSONDocument()
defer ts.Close()
doc, err := loads.JSONSpec(ts.URL,
loads.WithLoadingOptions(loading.WithCustomHeaders(map[string]string{
"X-API-key": "my-api-key",
})))
if err != nil {
panic(err)
}
fmt.Println(doc.Host())
fmt.Println(doc.Version())
}
func serveSomeJSONDocument() *httptest.Server {
source, err := os.Open(filepath.Join("fixtures", "json", "resources", "pathLoaderIssue.json"))
if err != nil {
panic(err)
}
return httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {
rw.WriteHeader(http.StatusOK)
_, _ = io.Copy(rw, source)
}))
}
Output: api.example.com 2.0
func JSONSpecRestricted ¶ added in v0.24.0
JSONSpecRestricted loads a JSON spec like JSONSpec, but confines local reads to root and restricts remote fetches with RestrictedHTTPClient.
The confinement is attached to the document's loader, so it also applies to every "$ref" resolved by Document.Expanded. Extra github.com/go-openapi/swag/loading options (custom headers, basic auth, timeout, ...) may be supplied; the confinement always wins over them.
func Spec ¶
func Spec(path string, opts ...LoaderOption) (*Document, error)
Spec loads a new spec document from a local or remote path.
By default it uses a JSON or YAML loader, with auto-detection based on the resource extension.
Security: by default the path is read with no confinement (local) and fetched with net/http.DefaultClient (remote), and any "$ref" later resolved by Document.Expanded is loaded the same way. When the path or the spec contents may derive from untrusted input, confine loading with WithLoadingOptions (for example github.com/go-openapi/swag/loading.WithRoot and github.com/go-openapi/swag/loading.WithHTTPClient). See the package documentation on Security.
Example (Embedded_yaml) ¶
Loads a JSON document from the embedded file system and get the deserialized spec.Swagger specification.
package main
import (
"embed"
"fmt"
"path"
"github.com/go-openapi/loads"
"github.com/go-openapi/swag/loading"
)
//go:embed fixtures
var embeddedFixtures embed.FS
func main() {
// loads a YAML spec from a file on an embedded file system
doc, err := loads.Spec(
path.Join("fixtures", "yaml", "swagger", "spec.yml"), // [embed.FS] sep is "/" even on windows
loads.WithLoadingOptions(
loading.WithFS(embeddedFixtures),
))
if err != nil {
panic(err)
}
fmt.Println(doc.Host())
fmt.Println(doc.Version())
spec := doc.Spec()
if spec == nil {
panic("spec should not be nil")
}
}
Output: api.example.com 2.0
Example (File) ¶
Example with default loaders defined at the package level.
package main
import (
"fmt"
"github.com/go-openapi/loads"
)
func main() {
path := "fixtures/yaml/swagger/spec.yml"
doc, err := loads.Spec(path)
if err != nil {
fmt.Println("Could not load this spec")
return
}
fmt.Printf("Spec loaded: %q\n", doc.Host())
}
Output: Spec loaded: "api.example.com"
Example (Http_json) ¶
Loads a JSON document and get the deserialized spec.Swagger specification.
package main
import (
"fmt"
"io"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"github.com/go-openapi/loads"
)
func main() {
ts := serveSomeJSONDocument()
defer ts.Close()
// loads a YAML spec from a http URL
doc, err := loads.Spec(ts.URL)
if err != nil {
panic(err)
}
fmt.Println(doc.Host())
fmt.Println(doc.Version())
spec := doc.Spec()
if spec == nil {
panic("spec should not be nil")
}
}
func serveSomeJSONDocument() *httptest.Server {
source, err := os.Open(filepath.Join("fixtures", "json", "resources", "pathLoaderIssue.json"))
if err != nil {
panic(err)
}
return httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {
rw.WriteHeader(http.StatusOK)
_, _ = io.Copy(rw, source)
}))
}
Output: api.example.com 2.0
Example (Http_yaml) ¶
Loads a YAML document and get the deserialized spec.Swagger specification.
package main
import (
"fmt"
"io"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"github.com/go-openapi/loads"
)
func main() {
ts := serveSomeYAMLDocument()
defer ts.Close()
// loads a YAML spec from a http URL
doc, err := loads.Spec(ts.URL)
if err != nil {
panic(err)
}
fmt.Println(doc.Host())
fmt.Println(doc.Version())
spec := doc.Spec()
if spec == nil {
panic("spec should not be nil")
}
}
func serveSomeYAMLDocument() *httptest.Server {
source, err := os.Open(filepath.Join("fixtures", "yaml", "swagger", "spec.yml"))
if err != nil {
panic(err)
}
return httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {
rw.WriteHeader(http.StatusOK)
_, _ = io.Copy(rw, source)
}))
}
Output: api.example.com 2.0
Example (RestrictFilesystem) ¶
ExampleSpec_restrictFilesystem shows how to confine local spec loading — and any "file://" reference the spec resolves — to a trusted directory.
loading.WithRoot is built on os.Root: it resolves every requested path relative to the chosen directory and rejects anything that escapes it, whether through an absolute path, ".." traversal, or a symlink pointing outside. Passing it through loads.WithLoadingOptions makes the confinement apply to reference resolution as well.
package main
import (
"fmt"
"github.com/go-openapi/loads"
"github.com/go-openapi/swag/loading"
)
func main() {
const root = "fixtures/yaml"
// A document inside the trusted root loads normally.
doc, err := loads.Spec("swagger/spec.yml", loads.WithLoadingOptions(loading.WithRoot(root)))
if err != nil {
panic(err)
}
fmt.Println(doc.Host())
// An attempt to escape the root is rejected.
_, err = loads.Spec("../../../../etc/passwd", loads.WithLoadingOptions(loading.WithRoot(root)))
fmt.Println("escape blocked:", err != nil)
}
Output: api.example.com escape blocked: true
Example (RestrictNetwork) ¶
ExampleSpec_restrictNetwork shows how to confine remote spec loading so that a caller-controlled URL — or a "$ref" inside the spec — cannot reach loopback, private, or link-local (cloud metadata) addresses.
The net.Dialer Control hook runs after DNS resolution and before connect, on every connection, so the check also covers HTTP redirects and DNS rebinding — neither of which a URL-string allowlist can defend against. Because the client is passed through loads.WithLoadingOptions, the same guard applies to every reference resolved during loads.Document.Expanded. Here a loopback test server stands in for an internal endpoint that the guard must refuse to reach.
package main
import (
"errors"
"fmt"
"net"
"net/http"
"net/http/httptest"
"net/netip"
"syscall"
"github.com/go-openapi/loads"
"github.com/go-openapi/swag/loading"
)
// errForbiddenAddr is returned by the dial guard when a destination is not allowed.
var errForbiddenAddr = errors.New("blocked dial to a forbidden address")
func main() {
control := func(_, address string, _ syscall.RawConn) error {
host, _, err := net.SplitHostPort(address)
if err != nil {
return err
}
addr, err := netip.ParseAddr(host)
if err != nil {
return err
}
if a := addr.Unmap(); a.IsLoopback() || a.IsPrivate() || a.IsLinkLocalUnicast() || a.IsUnspecified() {
return errForbiddenAddr
}
return nil
}
client := &http.Client{
Transport: &http.Transport{
DialContext: (&net.Dialer{Control: control}).DialContext,
},
}
// An internal service the application must not let untrusted input reach.
internal := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
_, _ = w.Write([]byte(`{"swagger":"2.0"}`))
}))
defer internal.Close()
// internal.URL is a loopback address (the untrusted URL in a real attack).
_, err := loads.Spec(internal.URL, loads.WithLoadingOptions(loading.WithHTTPClient(client)))
fmt.Println("blocked:", errors.Is(err, errForbiddenAddr))
}
Output: blocked: true
func SpecRestricted ¶ added in v0.24.0
SpecRestricted loads a spec like Spec — with JSON/YAML auto-detection — but confines local reads to root and restricts remote fetches with RestrictedHTTPClient.
The confinement is attached to the document's loader, so it also applies to every "$ref" resolved by Document.Expanded. Extra github.com/go-openapi/swag/loading options (custom headers, basic auth, timeout, ...) may be supplied; the confinement always wins over them.
Example ¶
ExampleSpecRestricted shows the pre-baked restricted loader, which bundles local confinement and a network-restricted HTTP client. The same confinement applies to every "$ref" the spec resolves during expansion.
Use this when the convenient, opinionated defaults fit; reach for the manual options shown in the other examples when you need a custom policy.
package main
import (
"errors"
"fmt"
"net/http"
"net/http/httptest"
"github.com/go-openapi/loads"
)
func main() {
const root = "fixtures/yaml"
// A document inside the trusted root loads normally.
doc, err := loads.SpecRestricted("swagger/spec.yml", root)
if err != nil {
panic(err)
}
fmt.Println(doc.Host())
// A path escaping the root is rejected.
_, err = loads.SpecRestricted("../../../../etc/passwd", root)
fmt.Println("escape blocked:", err != nil)
// A remote URL pointing at an internal (loopback) address is rejected at dial time.
internal := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
_, _ = w.Write([]byte(`{"swagger":"2.0"}`))
}))
defer internal.Close()
_, err = loads.SpecRestricted(internal.URL, root)
fmt.Println("network blocked:", errors.Is(err, loads.ErrForbiddenAddress))
}
Output: api.example.com escape blocked: true network blocked: true
func (*Document) Expanded ¶
func (d *Document) Expanded(options ...*spec.ExpandOptions) (*Document, error)
Expanded expands the $ref fields in the spec Document and returns a new expanded Document.
Security: expansion resolves every "$ref" by calling the document's loader recursively, so the spec contents drive further loads. A spec from an untrusted source can thus trigger arbitrary local reads or SSRF through its references. The loader carries the github.com/go-openapi/swag/loading options supplied via WithLoadingOptions at load time; configure confinement there so it applies to expansion as well. When no document loader is set, expansion falls back to the unconfined package-level loader. See the package documentation on Security.
func (*Document) Pristine ¶
Pristine creates a new pristine document instance based on the input data.
func (*Document) Raw ¶
func (d *Document) Raw() json.RawMessage
Raw returns the raw swagger spec as json bytes.
func (*Document) ResetDefinitions ¶
ResetDefinitions yields a shallow copy with the models reset to the original spec.
func (*Document) SpecFilePath ¶
SpecFilePath returns the file path of the spec if one is defined.
type LoaderOption ¶ added in v0.20.0
type LoaderOption func(*options)
LoaderOption allows to fine-tune the spec loader behavior.
Example ¶
Example with custom loaders passed as options.
package main
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"github.com/go-openapi/loads"
"github.com/go-openapi/swag/loading"
)
func main() {
path := "fixtures/yaml/swagger/spec.yml"
// a simpler version of loads.JSONDoc
jsonLoader := loads.NewDocLoaderWithMatch(
func(pth string, _ ...loading.Option) (json.RawMessage, error) {
buf, err := os.ReadFile(pth)
return json.RawMessage(buf), err
},
func(pth string) bool {
return filepath.Ext(pth) == ".json"
},
)
// equivalent to the default loader at the package level, which does:
//
// loads.AddLoader(loading.YAMLMatcher, loading.YAMLDoc)
yamlLoader := loads.NewDocLoaderWithMatch(
loading.YAMLDoc,
func(pth string) bool {
return filepath.Ext(pth) == ".yml"
},
)
doc, err := loads.Spec(path, loads.WithDocLoaderMatches(jsonLoader, yamlLoader))
if err != nil {
fmt.Println("Could not load this spec")
return
}
fmt.Printf("Spec loaded: %q\n", doc.Host())
}
Output: Spec loaded: "api.example.com"
func WithDocLoader ¶ added in v0.20.0
func WithDocLoader(l DocLoader) LoaderOption
WithDocLoader sets a custom loader for loading specs.
func WithDocLoaderMatches ¶ added in v0.20.0
func WithDocLoaderMatches(l ...DocLoaderWithMatch) LoaderOption
WithDocLoaderMatches sets a chain of custom loaders for loading specs for different extension matches.
Loaders are executed in the order of provided DocLoaderWithMatch 'es.
func WithLoadingOptions ¶ added in v0.23.0
func WithLoadingOptions(loadingOptions ...loading.Option) LoaderOption
WithLoadingOptions adds some loading.Option to be added when calling a registered loader.
The options are attached to the document's loader, so they apply both to the initial load and to every "$ref" resolved during Document.Expanded. This is the recommended place to confine loading of untrusted input, for example with loading.WithRoot (local) and loading.WithHTTPClient (remote). See the package documentation on Security.