This commit is contained in:
parent
99a03bac5d
commit
b20b1719bd
@ -40,7 +40,7 @@ ovhck=
|
|||||||
## License
|
## License
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Copyright (c) 2020, 2021 PaulBSD
|
Copyright (c) 2020, 2021, 2022 PaulBSD
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
49
go.mod
49
go.mod
@ -1,41 +1,42 @@
|
|||||||
module git.paulbsd.com/paulbsd/pki
|
module git.paulbsd.com/paulbsd/pki
|
||||||
|
|
||||||
go 1.17
|
go 1.19
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/go-acme/lego/v4 v4.4.0
|
github.com/go-acme/lego/v4 v4.9.0
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/google/go-cmp v0.5.5 // indirect
|
github.com/google/go-cmp v0.5.5 // indirect
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20210406100015-1e088ea4ee04 // indirect
|
github.com/labstack/echo/v4 v4.9.1
|
||||||
github.com/labstack/echo/v4 v4.5.0
|
github.com/lib/pq v1.10.7
|
||||||
github.com/lib/pq v1.10.3
|
github.com/miekg/dns v1.1.50 // indirect
|
||||||
github.com/miekg/dns v1.1.43 // indirect
|
|
||||||
github.com/onsi/ginkgo v1.16.0 // indirect
|
github.com/onsi/ginkgo v1.16.0 // indirect
|
||||||
github.com/onsi/gomega v1.11.0 // indirect
|
github.com/onsi/gomega v1.11.0 // indirect
|
||||||
github.com/smartystreets/assertions v1.2.0 // indirect
|
golang.org/x/crypto v0.1.0 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
|
golang.org/x/net v0.1.0 // indirect
|
||||||
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f // indirect
|
golang.org/x/sys v0.1.0 // indirect
|
||||||
golang.org/x/sys v0.0.0-20210903071746-97244b99971b // indirect
|
golang.org/x/text v0.4.0 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/time v0.1.0 // indirect
|
||||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
gopkg.in/ini.v1 v1.67.0
|
||||||
gopkg.in/ini.v1 v1.62.1
|
xorm.io/builder v0.3.12 // indirect
|
||||||
xorm.io/builder v0.3.9 // indirect
|
xorm.io/xorm v1.3.2
|
||||||
xorm.io/xorm v1.2.3
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/cenkalti/backoff/v4 v4.1.1 // indirect
|
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
|
||||||
github.com/goccy/go-json v0.7.8 // indirect
|
github.com/goccy/go-json v0.9.11 // indirect
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||||
github.com/json-iterator/go v1.1.11 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/labstack/gommon v0.3.0 // indirect
|
github.com/labstack/gommon v0.4.0 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.8 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.13 // indirect
|
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/ovh/go-ovh v1.1.0 // indirect
|
github.com/ovh/go-ovh v1.3.0 // indirect
|
||||||
github.com/syndtr/goleveldb v1.0.0 // indirect
|
github.com/syndtr/goleveldb v1.0.0 // indirect
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/valyala/fasttemplate v1.2.1 // indirect
|
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||||
|
golang.org/x/mod v0.6.0 // indirect
|
||||||
|
golang.org/x/tools v0.2.0 // indirect
|
||||||
|
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||||
)
|
)
|
||||||
|
3
vendor/github.com/cenkalti/backoff/v4/exponential.go
generated
vendored
3
vendor/github.com/cenkalti/backoff/v4/exponential.go
generated
vendored
@ -147,6 +147,9 @@ func (b *ExponentialBackOff) incrementCurrentInterval() {
|
|||||||
// Returns a random value from the following interval:
|
// Returns a random value from the following interval:
|
||||||
// [currentInterval - randomizationFactor * currentInterval, currentInterval + randomizationFactor * currentInterval].
|
// [currentInterval - randomizationFactor * currentInterval, currentInterval + randomizationFactor * currentInterval].
|
||||||
func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration {
|
func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration {
|
||||||
|
if randomizationFactor == 0 {
|
||||||
|
return currentInterval // make sure no randomness is used when randomizationFactor is 0.
|
||||||
|
}
|
||||||
var delta = randomizationFactor * float64(currentInterval)
|
var delta = randomizationFactor * float64(currentInterval)
|
||||||
var minInterval = float64(currentInterval) - delta
|
var minInterval = float64(currentInterval) - delta
|
||||||
var maxInterval = float64(currentInterval) + delta
|
var maxInterval = float64(currentInterval) + delta
|
||||||
|
10
vendor/github.com/go-acme/lego/v4/acme/api/api.go
generated
vendored
10
vendor/github.com/go-acme/lego/v4/acme/api/api.go
generated
vendored
@ -2,7 +2,6 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
|
||||||
"crypto"
|
"crypto"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
@ -71,7 +70,7 @@ func (a *Core) post(uri string, reqBody, response interface{}) (*http.Response,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// postAsGet performs an HTTP POST ("POST-as-GET") request.
|
// postAsGet performs an HTTP POST ("POST-as-GET") request.
|
||||||
// https://tools.ietf.org/html/rfc8555#section-6.3
|
// https://www.rfc-editor.org/rfc/rfc8555.html#section-6.3
|
||||||
func (a *Core) postAsGet(uri string, response interface{}) (*http.Response, error) {
|
func (a *Core) postAsGet(uri string, response interface{}) (*http.Response, error) {
|
||||||
return a.retrievablePost(uri, []byte{}, response)
|
return a.retrievablePost(uri, []byte{}, response)
|
||||||
}
|
}
|
||||||
@ -83,8 +82,6 @@ func (a *Core) retrievablePost(uri string, content []byte, response interface{})
|
|||||||
bo.MaxInterval = 5 * time.Second
|
bo.MaxInterval = 5 * time.Second
|
||||||
bo.MaxElapsedTime = 20 * time.Second
|
bo.MaxElapsedTime = 20 * time.Second
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
|
|
||||||
var resp *http.Response
|
var resp *http.Response
|
||||||
operation := func() error {
|
operation := func() error {
|
||||||
var err error
|
var err error
|
||||||
@ -96,8 +93,7 @@ func (a *Core) retrievablePost(uri string, content []byte, response interface{})
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cancel()
|
return backoff.Permanent(err)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -107,7 +103,7 @@ func (a *Core) retrievablePost(uri string, content []byte, response interface{})
|
|||||||
log.Infof("retry due to: %v", err)
|
log.Infof("retry due to: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := backoff.RetryNotify(operation, backoff.WithContext(bo, ctx), notify)
|
err := backoff.RetryNotify(operation, bo, notify)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
14
vendor/github.com/go-acme/lego/v4/acme/api/certificate.go
generated
vendored
14
vendor/github.com/go-acme/lego/v4/acme/api/certificate.go
generated
vendored
@ -1,10 +1,11 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/go-acme/lego/v4/acme"
|
"github.com/go-acme/lego/v4/acme"
|
||||||
@ -39,7 +40,7 @@ func (c *CertificateService) GetAll(certURL string, bundle bool) (map[string]*ac
|
|||||||
certs := map[string]*acme.RawCertificate{certURL: cert}
|
certs := map[string]*acme.RawCertificate{certURL: cert}
|
||||||
|
|
||||||
// URLs of "alternate" link relation
|
// URLs of "alternate" link relation
|
||||||
// - https://tools.ietf.org/html/rfc8555#section-7.4.2
|
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.4.2
|
||||||
alts := getLinks(headers, "alternate")
|
alts := getLinks(headers, "alternate")
|
||||||
|
|
||||||
for _, alt := range alts {
|
for _, alt := range alts {
|
||||||
@ -71,7 +72,7 @@ func (c *CertificateService) get(certURL string, bundle bool) (*acme.RawCertific
|
|||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(http.MaxBytesReader(nil, resp.Body, maxBodySize))
|
data, err := io.ReadAll(http.MaxBytesReader(nil, resp.Body, maxBodySize))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, resp.Header, err
|
return nil, resp.Header, err
|
||||||
}
|
}
|
||||||
@ -87,12 +88,17 @@ func (c *CertificateService) getCertificateChain(cert []byte, headers http.Heade
|
|||||||
// See https://community.letsencrypt.org/t/acme-v2-no-up-link-in-response/64962
|
// See https://community.letsencrypt.org/t/acme-v2-no-up-link-in-response/64962
|
||||||
_, issuer := pem.Decode(cert)
|
_, issuer := pem.Decode(cert)
|
||||||
if issuer != nil {
|
if issuer != nil {
|
||||||
|
// If bundle is false, we want to return a single certificate.
|
||||||
|
// To do this, we remove the issuer cert(s) from the issued cert.
|
||||||
|
if !bundle {
|
||||||
|
cert = bytes.TrimSuffix(cert, issuer)
|
||||||
|
}
|
||||||
return &acme.RawCertificate{Cert: cert, Issuer: issuer}
|
return &acme.RawCertificate{Cert: cert, Issuer: issuer}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The issuer certificate link may be supplied via an "up" link
|
// The issuer certificate link may be supplied via an "up" link
|
||||||
// in the response headers of a new certificate.
|
// in the response headers of a new certificate.
|
||||||
// See https://tools.ietf.org/html/rfc8555#section-7.4.2
|
// See https://www.rfc-editor.org/rfc/rfc8555.html#section-7.4.2
|
||||||
up := getLink(headers, "up")
|
up := getLink(headers, "up")
|
||||||
|
|
||||||
issuer, err := c.getIssuerFromLink(up)
|
issuer, err := c.getIssuerFromLink(up)
|
||||||
|
5
vendor/github.com/go-acme/lego/v4/acme/api/internal/sender/sender.go
generated
vendored
5
vendor/github.com/go-acme/lego/v4/acme/api/internal/sender/sender.go
generated
vendored
@ -4,7 +4,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
@ -96,7 +95,7 @@ func (d *Doer) do(req *http.Request, response interface{}) (*http.Response, erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
if response != nil {
|
if response != nil {
|
||||||
raw, err := ioutil.ReadAll(resp.Body)
|
raw, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
@ -120,7 +119,7 @@ func (d *Doer) formatUserAgent() string {
|
|||||||
|
|
||||||
func checkError(req *http.Request, resp *http.Response) error {
|
func checkError(req *http.Request, resp *http.Response) error {
|
||||||
if resp.StatusCode >= http.StatusBadRequest {
|
if resp.StatusCode >= http.StatusBadRequest {
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%d :: %s :: %s :: %w", resp.StatusCode, req.Method, req.URL, err)
|
return fmt.Errorf("%d :: %s :: %s :: %w", resp.StatusCode, req.Method, req.URL, err)
|
||||||
}
|
}
|
||||||
|
2
vendor/github.com/go-acme/lego/v4/acme/api/internal/sender/useragent.go
generated
vendored
2
vendor/github.com/go-acme/lego/v4/acme/api/internal/sender/useragent.go
generated
vendored
@ -5,7 +5,7 @@ package sender
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// ourUserAgent is the User-Agent of this underlying library package.
|
// ourUserAgent is the User-Agent of this underlying library package.
|
||||||
ourUserAgent = "xenolf-acme/4.4.0"
|
ourUserAgent = "xenolf-acme/4.9.0"
|
||||||
|
|
||||||
// ourUserAgentComment is part of the UA comment linked to the version status of this underlying library package.
|
// ourUserAgentComment is part of the UA comment linked to the version status of this underlying library package.
|
||||||
// values: detach|release
|
// values: detach|release
|
||||||
|
61
vendor/github.com/go-acme/lego/v4/acme/commons.go
generated
vendored
61
vendor/github.com/go-acme/lego/v4/acme/commons.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
// Package acme contains all objects related the ACME endpoints.
|
// Package acme contains all objects related the ACME endpoints.
|
||||||
// https://tools.ietf.org/html/rfc8555
|
// https://www.rfc-editor.org/rfc/rfc8555.html
|
||||||
package acme
|
package acme
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -7,20 +7,37 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Challenge statuses.
|
// ACME status values of Account, Order, Authorization and Challenge objects.
|
||||||
// https://tools.ietf.org/html/rfc8555#section-7.1.6
|
// See https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.6 for details.
|
||||||
const (
|
const (
|
||||||
StatusPending = "pending"
|
|
||||||
StatusInvalid = "invalid"
|
|
||||||
StatusValid = "valid"
|
|
||||||
StatusProcessing = "processing"
|
|
||||||
StatusDeactivated = "deactivated"
|
StatusDeactivated = "deactivated"
|
||||||
StatusExpired = "expired"
|
StatusExpired = "expired"
|
||||||
|
StatusInvalid = "invalid"
|
||||||
|
StatusPending = "pending"
|
||||||
|
StatusProcessing = "processing"
|
||||||
|
StatusReady = "ready"
|
||||||
StatusRevoked = "revoked"
|
StatusRevoked = "revoked"
|
||||||
|
StatusUnknown = "unknown"
|
||||||
|
StatusValid = "valid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CRL reason codes as defined in RFC 5280.
|
||||||
|
// https://datatracker.ietf.org/doc/html/rfc5280#section-5.3.1
|
||||||
|
const (
|
||||||
|
CRLReasonUnspecified uint = 0
|
||||||
|
CRLReasonKeyCompromise uint = 1
|
||||||
|
CRLReasonCACompromise uint = 2
|
||||||
|
CRLReasonAffiliationChanged uint = 3
|
||||||
|
CRLReasonSuperseded uint = 4
|
||||||
|
CRLReasonCessationOfOperation uint = 5
|
||||||
|
CRLReasonCertificateHold uint = 6
|
||||||
|
CRLReasonRemoveFromCRL uint = 8
|
||||||
|
CRLReasonPrivilegeWithdrawn uint = 9
|
||||||
|
CRLReasonAACompromise uint = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
// Directory the ACME directory object.
|
// Directory the ACME directory object.
|
||||||
// - https://tools.ietf.org/html/rfc8555#section-7.1.1
|
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.1
|
||||||
type Directory struct {
|
type Directory struct {
|
||||||
NewNonceURL string `json:"newNonce"`
|
NewNonceURL string `json:"newNonce"`
|
||||||
NewAccountURL string `json:"newAccount"`
|
NewAccountURL string `json:"newAccount"`
|
||||||
@ -32,7 +49,7 @@ type Directory struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Meta the ACME meta object (related to Directory).
|
// Meta the ACME meta object (related to Directory).
|
||||||
// - https://tools.ietf.org/html/rfc8555#section-7.1.1
|
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.1
|
||||||
type Meta struct {
|
type Meta struct {
|
||||||
// termsOfService (optional, string):
|
// termsOfService (optional, string):
|
||||||
// A URL identifying the current terms of service.
|
// A URL identifying the current terms of service.
|
||||||
@ -65,8 +82,8 @@ type ExtendedAccount struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Account the ACME account Object.
|
// Account the ACME account Object.
|
||||||
// - https://tools.ietf.org/html/rfc8555#section-7.1.2
|
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.2
|
||||||
// - https://tools.ietf.org/html/rfc8555#section-7.3
|
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.3
|
||||||
type Account struct {
|
type Account struct {
|
||||||
// status (required, string):
|
// status (required, string):
|
||||||
// The status of this account.
|
// The status of this account.
|
||||||
@ -112,7 +129,7 @@ type ExtendedOrder struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Order the ACME order Object.
|
// Order the ACME order Object.
|
||||||
// - https://tools.ietf.org/html/rfc8555#section-7.1.3
|
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.3
|
||||||
type Order struct {
|
type Order struct {
|
||||||
// status (required, string):
|
// status (required, string):
|
||||||
// The status of this order.
|
// The status of this order.
|
||||||
@ -165,7 +182,7 @@ type Order struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Authorization the ACME authorization object.
|
// Authorization the ACME authorization object.
|
||||||
// - https://tools.ietf.org/html/rfc8555#section-7.1.4
|
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.4
|
||||||
type Authorization struct {
|
type Authorization struct {
|
||||||
// status (required, string):
|
// status (required, string):
|
||||||
// The status of this authorization.
|
// The status of this authorization.
|
||||||
@ -207,8 +224,8 @@ type ExtendedChallenge struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Challenge the ACME challenge object.
|
// Challenge the ACME challenge object.
|
||||||
// - https://tools.ietf.org/html/rfc8555#section-7.1.5
|
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.5
|
||||||
// - https://tools.ietf.org/html/rfc8555#section-8
|
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-8
|
||||||
type Challenge struct {
|
type Challenge struct {
|
||||||
// type (required, string):
|
// type (required, string):
|
||||||
// The type of challenge encoded in the object.
|
// The type of challenge encoded in the object.
|
||||||
@ -241,23 +258,23 @@ type Challenge struct {
|
|||||||
// It MUST NOT contain any characters outside the base64url alphabet,
|
// It MUST NOT contain any characters outside the base64url alphabet,
|
||||||
// and MUST NOT include base64 padding characters ("=").
|
// and MUST NOT include base64 padding characters ("=").
|
||||||
// See [RFC4086] for additional information on randomness requirements.
|
// See [RFC4086] for additional information on randomness requirements.
|
||||||
// https://tools.ietf.org/html/rfc8555#section-8.3
|
// https://www.rfc-editor.org/rfc/rfc8555.html#section-8.3
|
||||||
// https://tools.ietf.org/html/rfc8555#section-8.4
|
// https://www.rfc-editor.org/rfc/rfc8555.html#section-8.4
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
|
|
||||||
// https://tools.ietf.org/html/rfc8555#section-8.1
|
// https://www.rfc-editor.org/rfc/rfc8555.html#section-8.1
|
||||||
KeyAuthorization string `json:"keyAuthorization"`
|
KeyAuthorization string `json:"keyAuthorization"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Identifier the ACME identifier object.
|
// Identifier the ACME identifier object.
|
||||||
// - https://tools.ietf.org/html/rfc8555#section-9.7.7
|
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-9.7.7
|
||||||
type Identifier struct {
|
type Identifier struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Value string `json:"value"`
|
Value string `json:"value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CSRMessage Certificate Signing Request.
|
// CSRMessage Certificate Signing Request.
|
||||||
// - https://tools.ietf.org/html/rfc8555#section-7.4
|
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.4
|
||||||
type CSRMessage struct {
|
type CSRMessage struct {
|
||||||
// csr (required, string):
|
// csr (required, string):
|
||||||
// A CSR encoding the parameters for the certificate being requested [RFC2986].
|
// A CSR encoding the parameters for the certificate being requested [RFC2986].
|
||||||
@ -267,8 +284,8 @@ type CSRMessage struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RevokeCertMessage a certificate revocation message.
|
// RevokeCertMessage a certificate revocation message.
|
||||||
// - https://tools.ietf.org/html/rfc8555#section-7.6
|
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.6
|
||||||
// - https://tools.ietf.org/html/rfc5280#section-5.3.1
|
// - https://www.rfc-editor.org/rfc/rfc5280.html#section-5.3.1
|
||||||
type RevokeCertMessage struct {
|
type RevokeCertMessage struct {
|
||||||
// certificate (required, string):
|
// certificate (required, string):
|
||||||
// The certificate to be revoked, in the base64url-encoded version of the DER format.
|
// The certificate to be revoked, in the base64url-encoded version of the DER format.
|
||||||
|
6
vendor/github.com/go-acme/lego/v4/acme/errors.go
generated
vendored
6
vendor/github.com/go-acme/lego/v4/acme/errors.go
generated
vendored
@ -11,8 +11,8 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ProblemDetails the problem details object.
|
// ProblemDetails the problem details object.
|
||||||
// - https://tools.ietf.org/html/rfc7807#section-3.1
|
// - https://www.rfc-editor.org/rfc/rfc7807.html#section-3.1
|
||||||
// - https://tools.ietf.org/html/rfc8555#section-7.3.3
|
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.3.3
|
||||||
type ProblemDetails struct {
|
type ProblemDetails struct {
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
Detail string `json:"detail,omitempty"`
|
Detail string `json:"detail,omitempty"`
|
||||||
@ -26,7 +26,7 @@ type ProblemDetails struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SubProblem a "subproblems".
|
// SubProblem a "subproblems".
|
||||||
// - https://tools.ietf.org/html/rfc8555#section-6.7.1
|
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-6.7.1
|
||||||
type SubProblem struct {
|
type SubProblem struct {
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
Detail string `json:"detail,omitempty"`
|
Detail string `json:"detail,omitempty"`
|
||||||
|
5
vendor/github.com/go-acme/lego/v4/certcrypto/crypto.go
generated
vendored
5
vendor/github.com/go-acme/lego/v4/certcrypto/crypto.go
generated
vendored
@ -85,6 +85,9 @@ func ParsePEMBundle(bundle []byte) ([]*x509.Certificate, error) {
|
|||||||
// https://github.com/golang/go/blob/693748e9fa385f1e2c3b91ca9acbb6c0ad2d133d/src/crypto/tls/tls.go#L238)
|
// https://github.com/golang/go/blob/693748e9fa385f1e2c3b91ca9acbb6c0ad2d133d/src/crypto/tls/tls.go#L238)
|
||||||
func ParsePEMPrivateKey(key []byte) (crypto.PrivateKey, error) {
|
func ParsePEMPrivateKey(key []byte) (crypto.PrivateKey, error) {
|
||||||
keyBlockDER, _ := pem.Decode(key)
|
keyBlockDER, _ := pem.Decode(key)
|
||||||
|
if keyBlockDER == nil {
|
||||||
|
return nil, fmt.Errorf("invalid PEM block")
|
||||||
|
}
|
||||||
|
|
||||||
if keyBlockDER.Type != "PRIVATE KEY" && !strings.HasSuffix(keyBlockDER.Type, " PRIVATE KEY") {
|
if keyBlockDER.Type != "PRIVATE KEY" && !strings.HasSuffix(keyBlockDER.Type, " PRIVATE KEY") {
|
||||||
return nil, fmt.Errorf("unknown PEM header %q", keyBlockDER.Type)
|
return nil, fmt.Errorf("unknown PEM header %q", keyBlockDER.Type)
|
||||||
@ -261,7 +264,7 @@ func generateDerCert(privateKey *rsa.PrivateKey, expiration time.Time, domain st
|
|||||||
}
|
}
|
||||||
|
|
||||||
if expiration.IsZero() {
|
if expiration.IsZero() {
|
||||||
expiration = time.Now().Add(365)
|
expiration = time.Now().AddDate(1, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
template := x509.Certificate{
|
template := x509.Certificate{
|
||||||
|
4
vendor/github.com/go-acme/lego/v4/certificate/authorization.go
generated
vendored
4
vendor/github.com/go-acme/lego/v4/certificate/authorization.go
generated
vendored
@ -60,7 +60,7 @@ func (c *Certifier) getAuthorizations(order acme.ExtendedOrder) ([]acme.Authoriz
|
|||||||
return responses, nil
|
return responses, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Certifier) deactivateAuthorizations(order acme.ExtendedOrder) {
|
func (c *Certifier) deactivateAuthorizations(order acme.ExtendedOrder, force bool) {
|
||||||
for _, authzURL := range order.Authorizations {
|
for _, authzURL := range order.Authorizations {
|
||||||
auth, err := c.core.Authorizations.Get(authzURL)
|
auth, err := c.core.Authorizations.Get(authzURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -68,7 +68,7 @@ func (c *Certifier) deactivateAuthorizations(order acme.ExtendedOrder) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if auth.Status == acme.StatusValid {
|
if auth.Status == acme.StatusValid && !force {
|
||||||
log.Infof("Skipping deactivating of valid auth: %s", authzURL)
|
log.Infof("Skipping deactivating of valid auth: %s", authzURL)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
47
vendor/github.com/go-acme/lego/v4/certificate/certificates.go
generated
vendored
47
vendor/github.com/go-acme/lego/v4/certificate/certificates.go
generated
vendored
@ -7,7 +7,7 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -49,22 +49,30 @@ type Resource struct {
|
|||||||
// If you do not want that you can supply your own private key in the privateKey parameter.
|
// If you do not want that you can supply your own private key in the privateKey parameter.
|
||||||
// If this parameter is non-nil it will be used instead of generating a new one.
|
// If this parameter is non-nil it will be used instead of generating a new one.
|
||||||
//
|
//
|
||||||
// If bundle is true, the []byte contains both the issuer certificate and your issued certificate as a bundle.
|
// If `Bundle` is true, the `[]byte` contains both the issuer certificate and your issued certificate as a bundle.
|
||||||
|
//
|
||||||
|
// If `AlwaysDeactivateAuthorizations` is true, the authorizations are also relinquished if the obtain request was successful.
|
||||||
|
// See https://datatracker.ietf.org/doc/html/rfc8555#section-7.5.2.
|
||||||
type ObtainRequest struct {
|
type ObtainRequest struct {
|
||||||
Domains []string
|
Domains []string
|
||||||
Bundle bool
|
Bundle bool
|
||||||
PrivateKey crypto.PrivateKey
|
PrivateKey crypto.PrivateKey
|
||||||
MustStaple bool
|
MustStaple bool
|
||||||
PreferredChain string
|
PreferredChain string
|
||||||
|
AlwaysDeactivateAuthorizations bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObtainForCSRRequest The request to obtain a certificate matching the CSR passed into it.
|
// ObtainForCSRRequest The request to obtain a certificate matching the CSR passed into it.
|
||||||
//
|
//
|
||||||
// If bundle is true, the []byte contains both the issuer certificate and your issued certificate as a bundle.
|
// If `Bundle` is true, the `[]byte` contains both the issuer certificate and your issued certificate as a bundle.
|
||||||
|
//
|
||||||
|
// If `AlwaysDeactivateAuthorizations` is true, the authorizations are also relinquished if the obtain request was successful.
|
||||||
|
// See https://datatracker.ietf.org/doc/html/rfc8555#section-7.5.2.
|
||||||
type ObtainForCSRRequest struct {
|
type ObtainForCSRRequest struct {
|
||||||
CSR *x509.CertificateRequest
|
CSR *x509.CertificateRequest
|
||||||
Bundle bool
|
Bundle bool
|
||||||
PreferredChain string
|
PreferredChain string
|
||||||
|
AlwaysDeactivateAuthorizations bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type resolver interface {
|
type resolver interface {
|
||||||
@ -117,14 +125,14 @@ func (c *Certifier) Obtain(request ObtainRequest) (*Resource, error) {
|
|||||||
authz, err := c.getAuthorizations(order)
|
authz, err := c.getAuthorizations(order)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If any challenge fails, return. Do not generate partial SAN certificates.
|
// If any challenge fails, return. Do not generate partial SAN certificates.
|
||||||
c.deactivateAuthorizations(order)
|
c.deactivateAuthorizations(order, request.AlwaysDeactivateAuthorizations)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.resolver.Solve(authz)
|
err = c.resolver.Solve(authz)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If any challenge fails, return. Do not generate partial SAN certificates.
|
// If any challenge fails, return. Do not generate partial SAN certificates.
|
||||||
c.deactivateAuthorizations(order)
|
c.deactivateAuthorizations(order, request.AlwaysDeactivateAuthorizations)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,6 +146,10 @@ func (c *Certifier) Obtain(request ObtainRequest) (*Resource, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if request.AlwaysDeactivateAuthorizations {
|
||||||
|
c.deactivateAuthorizations(order, true)
|
||||||
|
}
|
||||||
|
|
||||||
// Do not return an empty failures map, because
|
// Do not return an empty failures map, because
|
||||||
// it would still be a non-nil error value
|
// it would still be a non-nil error value
|
||||||
if len(failures) > 0 {
|
if len(failures) > 0 {
|
||||||
@ -178,14 +190,14 @@ func (c *Certifier) ObtainForCSR(request ObtainForCSRRequest) (*Resource, error)
|
|||||||
authz, err := c.getAuthorizations(order)
|
authz, err := c.getAuthorizations(order)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If any challenge fails, return. Do not generate partial SAN certificates.
|
// If any challenge fails, return. Do not generate partial SAN certificates.
|
||||||
c.deactivateAuthorizations(order)
|
c.deactivateAuthorizations(order, request.AlwaysDeactivateAuthorizations)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.resolver.Solve(authz)
|
err = c.resolver.Solve(authz)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If any challenge fails, return. Do not generate partial SAN certificates.
|
// If any challenge fails, return. Do not generate partial SAN certificates.
|
||||||
c.deactivateAuthorizations(order)
|
c.deactivateAuthorizations(order, request.AlwaysDeactivateAuthorizations)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,6 +211,10 @@ func (c *Certifier) ObtainForCSR(request ObtainForCSRRequest) (*Resource, error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if request.AlwaysDeactivateAuthorizations {
|
||||||
|
c.deactivateAuthorizations(order, true)
|
||||||
|
}
|
||||||
|
|
||||||
if cert != nil {
|
if cert != nil {
|
||||||
// Add the CSR to the certificate so that it can be used for renewals.
|
// Add the CSR to the certificate so that it can be used for renewals.
|
||||||
cert.CSR = certcrypto.PEMEncode(request.CSR)
|
cert.CSR = certcrypto.PEMEncode(request.CSR)
|
||||||
@ -225,7 +241,7 @@ func (c *Certifier) getForOrder(domains []string, order acme.ExtendedOrder, bund
|
|||||||
commonName := domains[0]
|
commonName := domains[0]
|
||||||
|
|
||||||
// RFC8555 Section 7.4 "Applying for Certificate Issuance"
|
// RFC8555 Section 7.4 "Applying for Certificate Issuance"
|
||||||
// https://tools.ietf.org/html/rfc8555#section-7.4
|
// https://www.rfc-editor.org/rfc/rfc8555.html#section-7.4
|
||||||
// says:
|
// says:
|
||||||
// Clients SHOULD NOT make any assumptions about the sort order of
|
// Clients SHOULD NOT make any assumptions about the sort order of
|
||||||
// "identifiers" or "authorizations" elements in the returned order
|
// "identifiers" or "authorizations" elements in the returned order
|
||||||
@ -349,6 +365,11 @@ func (c *Certifier) checkResponse(order acme.ExtendedOrder, certRes *Resource, b
|
|||||||
|
|
||||||
// Revoke takes a PEM encoded certificate or bundle and tries to revoke it at the CA.
|
// Revoke takes a PEM encoded certificate or bundle and tries to revoke it at the CA.
|
||||||
func (c *Certifier) Revoke(cert []byte) error {
|
func (c *Certifier) Revoke(cert []byte) error {
|
||||||
|
return c.RevokeWithReason(cert, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RevokeWithReason takes a PEM encoded certificate or bundle and tries to revoke it at the CA.
|
||||||
|
func (c *Certifier) RevokeWithReason(cert []byte, reason *uint) error {
|
||||||
certificates, err := certcrypto.ParsePEMBundle(cert)
|
certificates, err := certcrypto.ParsePEMBundle(cert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -361,6 +382,7 @@ func (c *Certifier) Revoke(cert []byte) error {
|
|||||||
|
|
||||||
revokeMsg := acme.RevokeCertMessage{
|
revokeMsg := acme.RevokeCertMessage{
|
||||||
Certificate: base64.RawURLEncoding.EncodeToString(x509Cert.Raw),
|
Certificate: base64.RawURLEncoding.EncodeToString(x509Cert.Raw),
|
||||||
|
Reason: reason,
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.core.Certificates.Revoke(revokeMsg)
|
return c.core.Certificates.Revoke(revokeMsg)
|
||||||
@ -423,6 +445,7 @@ func (c *Certifier) Renew(certRes Resource, bundle, mustStaple bool, preferredCh
|
|||||||
Bundle: bundle,
|
Bundle: bundle,
|
||||||
PrivateKey: privateKey,
|
PrivateKey: privateKey,
|
||||||
MustStaple: mustStaple,
|
MustStaple: mustStaple,
|
||||||
|
PreferredChain: preferredChain,
|
||||||
}
|
}
|
||||||
return c.Obtain(query)
|
return c.Obtain(query)
|
||||||
}
|
}
|
||||||
@ -465,7 +488,7 @@ func (c *Certifier) GetOCSP(bundle []byte) ([]byte, *ocsp.Response, error) {
|
|||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
issuerBytes, errC := ioutil.ReadAll(http.MaxBytesReader(nil, resp.Body, maxBodySize))
|
issuerBytes, errC := io.ReadAll(http.MaxBytesReader(nil, resp.Body, maxBodySize))
|
||||||
if errC != nil {
|
if errC != nil {
|
||||||
return nil, nil, errC
|
return nil, nil, errC
|
||||||
}
|
}
|
||||||
@ -494,7 +517,7 @@ func (c *Certifier) GetOCSP(bundle []byte) ([]byte, *ocsp.Response, error) {
|
|||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
ocspResBytes, err := ioutil.ReadAll(http.MaxBytesReader(nil, resp.Body, maxBodySize))
|
ocspResBytes, err := io.ReadAll(http.MaxBytesReader(nil, resp.Body, maxBodySize))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -560,11 +583,11 @@ func checkOrderStatus(order acme.ExtendedOrder) (bool, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://tools.ietf.org/html/rfc8555#section-7.1.4
|
// https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.4
|
||||||
// The domain name MUST be encoded in the form in which it would appear in a certificate.
|
// The domain name MUST be encoded in the form in which it would appear in a certificate.
|
||||||
// That is, it MUST be encoded according to the rules in Section 7 of [RFC5280].
|
// That is, it MUST be encoded according to the rules in Section 7 of [RFC5280].
|
||||||
//
|
//
|
||||||
// https://tools.ietf.org/html/rfc5280#section-7
|
// https://www.rfc-editor.org/rfc/rfc5280.html#section-7
|
||||||
func sanitizeDomain(domains []string) []string {
|
func sanitizeDomain(domains []string) []string {
|
||||||
var sanitizedDomains []string
|
var sanitizedDomains []string
|
||||||
for _, domain := range domains {
|
for _, domain := range domains {
|
||||||
|
6
vendor/github.com/go-acme/lego/v4/challenge/challenges.go
generated
vendored
6
vendor/github.com/go-acme/lego/v4/challenge/challenges.go
generated
vendored
@ -10,15 +10,15 @@ import (
|
|||||||
type Type string
|
type Type string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// HTTP01 is the "http-01" ACME challenge https://tools.ietf.org/html/rfc8555#section-8.3
|
// HTTP01 is the "http-01" ACME challenge https://www.rfc-editor.org/rfc/rfc8555.html#section-8.3
|
||||||
// Note: ChallengePath returns the URL path to fulfill this challenge.
|
// Note: ChallengePath returns the URL path to fulfill this challenge.
|
||||||
HTTP01 = Type("http-01")
|
HTTP01 = Type("http-01")
|
||||||
|
|
||||||
// DNS01 is the "dns-01" ACME challenge https://tools.ietf.org/html/rfc8555#section-8.4
|
// DNS01 is the "dns-01" ACME challenge https://www.rfc-editor.org/rfc/rfc8555.html#section-8.4
|
||||||
// Note: GetRecord returns a DNS record which will fulfill this challenge.
|
// Note: GetRecord returns a DNS record which will fulfill this challenge.
|
||||||
DNS01 = Type("dns-01")
|
DNS01 = Type("dns-01")
|
||||||
|
|
||||||
// TLSALPN01 is the "tls-alpn-01" ACME challenge https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-07
|
// TLSALPN01 is the "tls-alpn-01" ACME challenge https://www.rfc-editor.org/rfc/rfc8737.html
|
||||||
TLSALPN01 = Type("tls-alpn-01")
|
TLSALPN01 = Type("tls-alpn-01")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
34
vendor/github.com/go-acme/lego/v4/challenge/dns01/dns_challenge.go
generated
vendored
34
vendor/github.com/go-acme/lego/v4/challenge/dns01/dns_challenge.go
generated
vendored
@ -176,15 +176,33 @@ func GetRecord(domain, keyAuth string) (fqdn, value string) {
|
|||||||
keyAuthShaBytes := sha256.Sum256([]byte(keyAuth))
|
keyAuthShaBytes := sha256.Sum256([]byte(keyAuth))
|
||||||
// base64URL encoding without padding
|
// base64URL encoding without padding
|
||||||
value = base64.RawURLEncoding.EncodeToString(keyAuthShaBytes[:sha256.Size])
|
value = base64.RawURLEncoding.EncodeToString(keyAuthShaBytes[:sha256.Size])
|
||||||
fqdn = fmt.Sprintf("_acme-challenge.%s.", domain)
|
|
||||||
|
|
||||||
if ok, _ := strconv.ParseBool(os.Getenv("LEGO_EXPERIMENTAL_CNAME_SUPPORT")); ok {
|
fqdn = getChallengeFqdn(domain)
|
||||||
r, err := dnsQuery(fqdn, dns.TypeCNAME, recursiveNameservers, true)
|
|
||||||
// Check if the domain has CNAME then return that
|
|
||||||
if err == nil && r.Rcode == dns.RcodeSuccess {
|
|
||||||
fqdn = updateDomainWithCName(r, fqdn)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getChallengeFqdn(domain string) string {
|
||||||
|
fqdn := fmt.Sprintf("_acme-challenge.%s.", domain)
|
||||||
|
|
||||||
|
if ok, _ := strconv.ParseBool(os.Getenv("LEGO_DISABLE_CNAME_SUPPORT")); ok {
|
||||||
|
return fqdn
|
||||||
|
}
|
||||||
|
|
||||||
|
// recursion counter so it doesn't spin out of control
|
||||||
|
for limit := 0; limit < 50; limit++ {
|
||||||
|
// Keep following CNAMEs
|
||||||
|
r, err := dnsQuery(fqdn, dns.TypeCNAME, recursiveNameservers, true)
|
||||||
|
|
||||||
|
// Check if the domain has CNAME then use that
|
||||||
|
if err == nil && r.Rcode == dns.RcodeSuccess {
|
||||||
|
fqdn = updateDomainWithCName(r, fqdn)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// No more CNAME records to follow, exit
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return fqdn
|
||||||
|
}
|
||||||
|
2
vendor/github.com/go-acme/lego/v4/challenge/dns01/dns_challenge_manual.go
generated
vendored
2
vendor/github.com/go-acme/lego/v4/challenge/dns01/dns_challenge_manual.go
generated
vendored
@ -8,7 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
dnsTemplate = `%s %d IN TXT "%s"`
|
dnsTemplate = `%s %d IN TXT %q`
|
||||||
)
|
)
|
||||||
|
|
||||||
// DNSProviderManual is an implementation of the ChallengeProvider interface.
|
// DNSProviderManual is an implementation of the ChallengeProvider interface.
|
||||||
|
3
vendor/github.com/go-acme/lego/v4/challenge/dns01/nameserver.go
generated
vendored
3
vendor/github.com/go-acme/lego/v4/challenge/dns01/nameserver.go
generated
vendored
@ -13,9 +13,6 @@ import (
|
|||||||
|
|
||||||
const defaultResolvConf = "/etc/resolv.conf"
|
const defaultResolvConf = "/etc/resolv.conf"
|
||||||
|
|
||||||
// dnsTimeout is used to override the default DNS timeout of 10 seconds.
|
|
||||||
var dnsTimeout = 10 * time.Second
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
fqdnSoaCache = map[string]*soaCacheEntry{}
|
fqdnSoaCache = map[string]*soaCacheEntry{}
|
||||||
muFqdnSoaCache sync.Mutex
|
muFqdnSoaCache sync.Mutex
|
||||||
|
8
vendor/github.com/go-acme/lego/v4/challenge/dns01/nameserver_unix.go
generated
vendored
Normal file
8
vendor/github.com/go-acme/lego/v4/challenge/dns01/nameserver_unix.go
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
//go:build !windows
|
||||||
|
|
||||||
|
package dns01
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// dnsTimeout is used to override the default DNS timeout of 10 seconds.
|
||||||
|
var dnsTimeout = 10 * time.Second
|
8
vendor/github.com/go-acme/lego/v4/challenge/dns01/nameserver_windows.go
generated
vendored
Normal file
8
vendor/github.com/go-acme/lego/v4/challenge/dns01/nameserver_windows.go
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package dns01
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// dnsTimeout is used to override the default DNS timeout of 20 seconds.
|
||||||
|
var dnsTimeout = 20 * time.Second
|
7
vendor/github.com/go-acme/lego/v4/challenge/http01/domain_matcher.go
generated
vendored
7
vendor/github.com/go-acme/lego/v4/challenge/http01/domain_matcher.go
generated
vendored
@ -23,13 +23,16 @@ import (
|
|||||||
// RFC7239 has standardized the different forwarding headers into a single header named Forwarded.
|
// RFC7239 has standardized the different forwarding headers into a single header named Forwarded.
|
||||||
// The header value has a different format, so you should use forwardedMatcher
|
// The header value has a different format, so you should use forwardedMatcher
|
||||||
// when the http01.ProviderServer operates behind a RFC7239 compatible proxy.
|
// when the http01.ProviderServer operates behind a RFC7239 compatible proxy.
|
||||||
// https://tools.ietf.org/html/rfc7239
|
// https://www.rfc-editor.org/rfc/rfc7239.html
|
||||||
//
|
//
|
||||||
// Note: RFC7239 also reminds us, "that an HTTP list [...] may be split over multiple header fields" (section 7.1),
|
// Note: RFC7239 also reminds us, "that an HTTP list [...] may be split over multiple header fields" (section 7.1),
|
||||||
// meaning that
|
// meaning that
|
||||||
|
//
|
||||||
// X-Header: a
|
// X-Header: a
|
||||||
// X-Header: b
|
// X-Header: b
|
||||||
|
//
|
||||||
// is equal to
|
// is equal to
|
||||||
|
//
|
||||||
// X-Header: a, b
|
// X-Header: a, b
|
||||||
//
|
//
|
||||||
// All matcher implementations (explicitly not excluding arbitraryMatcher!)
|
// All matcher implementations (explicitly not excluding arbitraryMatcher!)
|
||||||
@ -66,7 +69,7 @@ func (m arbitraryMatcher) matches(r *http.Request, domain string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// forwardedMatcher checks whether the Forwarded header contains a "host" element starting with a domain name.
|
// forwardedMatcher checks whether the Forwarded header contains a "host" element starting with a domain name.
|
||||||
// See https://tools.ietf.org/html/rfc7239 for details.
|
// See https://www.rfc-editor.org/rfc/rfc7239.html for details.
|
||||||
type forwardedMatcher struct{}
|
type forwardedMatcher struct{}
|
||||||
|
|
||||||
func (m *forwardedMatcher) name() string {
|
func (m *forwardedMatcher) name() string {
|
||||||
|
31
vendor/github.com/go-acme/lego/v4/challenge/http01/http_challenge_server.go
generated
vendored
31
vendor/github.com/go-acme/lego/v4/challenge/http01/http_challenge_server.go
generated
vendored
@ -2,9 +2,11 @@ package http01
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/textproto"
|
"net/textproto"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-acme/lego/v4/log"
|
"github.com/go-acme/lego/v4/log"
|
||||||
@ -14,8 +16,11 @@ import (
|
|||||||
// It may be instantiated without using the NewProviderServer function if
|
// It may be instantiated without using the NewProviderServer function if
|
||||||
// you want only to use the default values.
|
// you want only to use the default values.
|
||||||
type ProviderServer struct {
|
type ProviderServer struct {
|
||||||
iface string
|
address string
|
||||||
port string
|
network string // must be valid argument to net.Listen
|
||||||
|
|
||||||
|
socketMode fs.FileMode
|
||||||
|
|
||||||
matcher domainMatcher
|
matcher domainMatcher
|
||||||
done chan bool
|
done chan bool
|
||||||
listener net.Listener
|
listener net.Listener
|
||||||
@ -29,24 +34,34 @@ func NewProviderServer(iface, port string) *ProviderServer {
|
|||||||
port = "80"
|
port = "80"
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ProviderServer{iface: iface, port: port, matcher: &hostMatcher{}}
|
return &ProviderServer{network: "tcp", address: net.JoinHostPort(iface, port), matcher: &hostMatcher{}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUnixProviderServer(socketPath string, mode fs.FileMode) *ProviderServer {
|
||||||
|
return &ProviderServer{network: "unix", address: socketPath, socketMode: mode, matcher: &hostMatcher{}}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present starts a web server and makes the token available at `ChallengePath(token)` for web requests.
|
// Present starts a web server and makes the token available at `ChallengePath(token)` for web requests.
|
||||||
func (s *ProviderServer) Present(domain, token, keyAuth string) error {
|
func (s *ProviderServer) Present(domain, token, keyAuth string) error {
|
||||||
var err error
|
var err error
|
||||||
s.listener, err = net.Listen("tcp", s.GetAddress())
|
s.listener, err = net.Listen(s.network, s.GetAddress())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not start HTTP server for challenge: %w", err)
|
return fmt.Errorf("could not start HTTP server for challenge: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.network == "unix" {
|
||||||
|
if err = os.Chmod(s.address, s.socketMode); err != nil {
|
||||||
|
return fmt.Errorf("chmod %s: %w", s.address, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
s.done = make(chan bool)
|
s.done = make(chan bool)
|
||||||
go s.serve(domain, token, keyAuth)
|
go s.serve(domain, token, keyAuth)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ProviderServer) GetAddress() string {
|
func (s *ProviderServer) GetAddress() string {
|
||||||
return net.JoinHostPort(s.iface, s.port)
|
return s.address
|
||||||
}
|
}
|
||||||
|
|
||||||
// CleanUp closes the HTTP server and removes the token from `ChallengePath(token)`.
|
// CleanUp closes the HTTP server and removes the token from `ChallengePath(token)`.
|
||||||
@ -69,7 +84,7 @@ func (s *ProviderServer) CleanUp(domain, token, keyAuth string) error {
|
|||||||
//
|
//
|
||||||
// The exact behavior depends on the value of headerName:
|
// The exact behavior depends on the value of headerName:
|
||||||
// - "" (the empty string) and "Host" will restore the default and only check the Host header
|
// - "" (the empty string) and "Host" will restore the default and only check the Host header
|
||||||
// - "Forwarded" will look for a Forwarded header, and inspect it according to https://tools.ietf.org/html/rfc7239
|
// - "Forwarded" will look for a Forwarded header, and inspect it according to https://www.rfc-editor.org/rfc/rfc7239.html
|
||||||
// - any other value will check the header value with the same name.
|
// - any other value will check the header value with the same name.
|
||||||
func (s *ProviderServer) SetProxyHeader(headerName string) {
|
func (s *ProviderServer) SetProxyHeader(headerName string) {
|
||||||
switch h := textproto.CanonicalMIMEHeaderKey(headerName); h {
|
switch h := textproto.CanonicalMIMEHeaderKey(headerName); h {
|
||||||
@ -85,7 +100,7 @@ func (s *ProviderServer) SetProxyHeader(headerName string) {
|
|||||||
func (s *ProviderServer) serve(domain, token, keyAuth string) {
|
func (s *ProviderServer) serve(domain, token, keyAuth string) {
|
||||||
path := ChallengePath(token)
|
path := ChallengePath(token)
|
||||||
|
|
||||||
// The incoming request must will be validated to prevent DNS rebind attacks.
|
// The incoming request will be validated to prevent DNS rebind attacks.
|
||||||
// We only respond with the keyAuth, when we're receiving a GET requests with
|
// We only respond with the keyAuth, when we're receiving a GET requests with
|
||||||
// the "Host" header matching the domain (the latter is configurable though SetProxyHeader).
|
// the "Host" header matching the domain (the latter is configurable though SetProxyHeader).
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
@ -99,7 +114,7 @@ func (s *ProviderServer) serve(domain, token, keyAuth string) {
|
|||||||
}
|
}
|
||||||
log.Infof("[%s] Served key authentication", domain)
|
log.Infof("[%s] Served key authentication", domain)
|
||||||
} else {
|
} else {
|
||||||
log.Warnf("Received request for domain %s with method %s but the domain did not match any challenge. Please ensure your are passing the %s header properly.", r.Host, r.Method, s.matcher.name())
|
log.Warnf("Received request for domain %s with method %s but the domain did not match any challenge. Please ensure you are passing the %s header properly.", r.Host, r.Method, s.matcher.name())
|
||||||
_, err := w.Write([]byte("TEST"))
|
_, err := w.Write([]byte("TEST"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
11
vendor/github.com/go-acme/lego/v4/challenge/resolver/solver_manager.go
generated
vendored
11
vendor/github.com/go-acme/lego/v4/challenge/resolver/solver_manager.go
generated
vendored
@ -1,7 +1,6 @@
|
|||||||
package resolver
|
package resolver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
@ -107,21 +106,17 @@ func validate(core *api.Core, domain string, chlg acme.Challenge) error {
|
|||||||
bo.MaxInterval = 10 * initialInterval
|
bo.MaxInterval = 10 * initialInterval
|
||||||
bo.MaxElapsedTime = 100 * initialInterval
|
bo.MaxElapsedTime = 100 * initialInterval
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
|
|
||||||
// After the path is sent, the ACME server will access our server.
|
// After the path is sent, the ACME server will access our server.
|
||||||
// Repeatedly check the server for an updated status on our request.
|
// Repeatedly check the server for an updated status on our request.
|
||||||
operation := func() error {
|
operation := func() error {
|
||||||
authz, err := core.Authorizations.Get(chlng.AuthorizationURL)
|
authz, err := core.Authorizations.Get(chlng.AuthorizationURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cancel()
|
return backoff.Permanent(err)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
valid, err := checkAuthorizationStatus(authz)
|
valid, err := checkAuthorizationStatus(authz)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cancel()
|
return backoff.Permanent(err)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if valid {
|
if valid {
|
||||||
@ -132,7 +127,7 @@ func validate(core *api.Core, domain string, chlg acme.Challenge) error {
|
|||||||
return errors.New("the server didn't respond to our request")
|
return errors.New("the server didn't respond to our request")
|
||||||
}
|
}
|
||||||
|
|
||||||
return backoff.Retry(operation, backoff.WithContext(bo, ctx))
|
return backoff.Retry(operation, bo)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkChallengeStatus(chlng acme.ExtendedChallenge) (bool, error) {
|
func checkChallengeStatus(chlng acme.ExtendedChallenge) (bool, error) {
|
||||||
|
4
vendor/github.com/go-acme/lego/v4/challenge/tlsalpn01/tls_alpn_challenge.go
generated
vendored
4
vendor/github.com/go-acme/lego/v4/challenge/tlsalpn01/tls_alpn_challenge.go
generated
vendored
@ -16,7 +16,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// idPeAcmeIdentifierV1 is the SMI Security for PKIX Certification Extension OID referencing the ACME extension.
|
// idPeAcmeIdentifierV1 is the SMI Security for PKIX Certification Extension OID referencing the ACME extension.
|
||||||
// Reference: https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-07#section-6.1
|
// Reference: https://www.rfc-editor.org/rfc/rfc8737.html#section-6.1
|
||||||
var idPeAcmeIdentifierV1 = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 31}
|
var idPeAcmeIdentifierV1 = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 31}
|
||||||
|
|
||||||
type ValidateFunc func(core *api.Core, domain string, chlng acme.Challenge) error
|
type ValidateFunc func(core *api.Core, domain string, chlng acme.Challenge) error
|
||||||
@ -83,7 +83,7 @@ func ChallengeBlocks(domain, keyAuth string) ([]byte, []byte, error) {
|
|||||||
|
|
||||||
// Add the keyAuth digest as the acmeValidation-v1 extension
|
// Add the keyAuth digest as the acmeValidation-v1 extension
|
||||||
// (marked as critical such that it won't be used by non-ACME software).
|
// (marked as critical such that it won't be used by non-ACME software).
|
||||||
// Reference: https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-07#section-3
|
// Reference: https://www.rfc-editor.org/rfc/rfc8737.html#section-3
|
||||||
extensions := []pkix.Extension{
|
extensions := []pkix.Extension{
|
||||||
{
|
{
|
||||||
Id: idPeAcmeIdentifierV1,
|
Id: idPeAcmeIdentifierV1,
|
||||||
|
2
vendor/github.com/go-acme/lego/v4/challenge/tlsalpn01/tls_alpn_challenge_server.go
generated
vendored
2
vendor/github.com/go-acme/lego/v4/challenge/tlsalpn01/tls_alpn_challenge_server.go
generated
vendored
@ -61,7 +61,7 @@ func (s *ProviderServer) Present(domain, token, keyAuth string) error {
|
|||||||
|
|
||||||
// We must set that the `acme-tls/1` application level protocol is supported
|
// We must set that the `acme-tls/1` application level protocol is supported
|
||||||
// so that the protocol negotiation can succeed. Reference:
|
// so that the protocol negotiation can succeed. Reference:
|
||||||
// https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-07#section-6.2
|
// https://www.rfc-editor.org/rfc/rfc8737.html#section-6.2
|
||||||
tlsConf.NextProtos = []string{ACMETLS1Protocol}
|
tlsConf.NextProtos = []string{ACMETLS1Protocol}
|
||||||
|
|
||||||
// Create the listener with the created tls.Config.
|
// Create the listener with the created tls.Config.
|
||||||
|
65
vendor/github.com/go-acme/lego/v4/lego/client_config.go
generated
vendored
65
vendor/github.com/go-acme/lego/v4/lego/client_config.go
generated
vendored
@ -4,10 +4,11 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-acme/lego/v4/certcrypto"
|
"github.com/go-acme/lego/v4/certcrypto"
|
||||||
@ -17,10 +18,15 @@ import (
|
|||||||
const (
|
const (
|
||||||
// caCertificatesEnvVar is the environment variable name that can be used to
|
// caCertificatesEnvVar is the environment variable name that can be used to
|
||||||
// specify the path to PEM encoded CA Certificates that can be used to
|
// specify the path to PEM encoded CA Certificates that can be used to
|
||||||
// authenticate an ACME server with a HTTPS certificate not issued by a CA in
|
// authenticate an ACME server with an HTTPS certificate not issued by a CA in
|
||||||
// the system-wide trusted root list.
|
// the system-wide trusted root list.
|
||||||
|
// Multiple file paths can be added by using os.PathListSeparator as a separator.
|
||||||
caCertificatesEnvVar = "LEGO_CA_CERTIFICATES"
|
caCertificatesEnvVar = "LEGO_CA_CERTIFICATES"
|
||||||
|
|
||||||
|
// caSystemCertPool is the environment variable name that can be used to define
|
||||||
|
// if the certificates pool must use a copy of the system cert pool.
|
||||||
|
caSystemCertPool = "LEGO_CA_SYSTEM_CERT_POOL"
|
||||||
|
|
||||||
// caServerNameEnvVar is the environment variable name that can be used to
|
// caServerNameEnvVar is the environment variable name that can be used to
|
||||||
// specify the CA server name that can be used to
|
// specify the CA server name that can be used to
|
||||||
// authenticate an ACME server with a HTTPS certificate not issued by a CA in
|
// authenticate an ACME server with a HTTPS certificate not issued by a CA in
|
||||||
@ -82,23 +88,44 @@ func createDefaultHTTPClient() *http.Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// initCertPool creates a *x509.CertPool populated with the PEM certificates
|
// initCertPool creates a *x509.CertPool populated with the PEM certificates
|
||||||
// found in the filepath specified in the caCertificatesEnvVar OS environment
|
// found in the filepath specified in the caCertificatesEnvVar OS environment variable.
|
||||||
// variable. If the caCertificatesEnvVar is not set then initCertPool will
|
// If the caCertificatesEnvVar is not set then initCertPool will return nil.
|
||||||
// return nil. If there is an error creating a *x509.CertPool from the provided
|
// If there is an error creating a *x509.CertPool from the provided caCertificatesEnvVar value then initCertPool will panic.
|
||||||
// caCertificatesEnvVar value then initCertPool will panic.
|
// If the caSystemCertPool is set to a "truthy value" (`1`, `t`, `T`, `TRUE`, `true`, `True`) then a copy of system cert pool will be used.
|
||||||
|
// caSystemCertPool requires caCertificatesEnvVar to be set.
|
||||||
func initCertPool() *x509.CertPool {
|
func initCertPool() *x509.CertPool {
|
||||||
if customCACertsPath := os.Getenv(caCertificatesEnvVar); customCACertsPath != "" {
|
customCACertsPath := os.Getenv(caCertificatesEnvVar)
|
||||||
customCAs, err := ioutil.ReadFile(customCACertsPath)
|
if customCACertsPath == "" {
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Sprintf("error reading %s=%q: %v",
|
|
||||||
caCertificatesEnvVar, customCACertsPath, err))
|
|
||||||
}
|
|
||||||
certPool := x509.NewCertPool()
|
|
||||||
if ok := certPool.AppendCertsFromPEM(customCAs); !ok {
|
|
||||||
panic(fmt.Sprintf("error creating x509 cert pool from %s=%q: %v",
|
|
||||||
caCertificatesEnvVar, customCACertsPath, err))
|
|
||||||
}
|
|
||||||
return certPool
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
certPool := getCertPool()
|
||||||
|
|
||||||
|
for _, customPath := range strings.Split(customCACertsPath, string(os.PathListSeparator)) {
|
||||||
|
customCAs, err := os.ReadFile(customPath)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("error reading %s=%q: %v",
|
||||||
|
caCertificatesEnvVar, customPath, err))
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok := certPool.AppendCertsFromPEM(customCAs); !ok {
|
||||||
|
panic(fmt.Sprintf("error creating x509 cert pool from %s=%q: %v",
|
||||||
|
caCertificatesEnvVar, customPath, err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return certPool
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCertPool() *x509.CertPool {
|
||||||
|
useSystemCertPool, _ := strconv.ParseBool(os.Getenv(caSystemCertPool))
|
||||||
|
if !useSystemCertPool {
|
||||||
|
return x509.NewCertPool()
|
||||||
|
}
|
||||||
|
|
||||||
|
pool, err := x509.SystemCertPool()
|
||||||
|
if err == nil {
|
||||||
|
return pool
|
||||||
|
}
|
||||||
|
return x509.NewCertPool()
|
||||||
|
}
|
||||||
|
4
vendor/github.com/go-acme/lego/v4/platform/config/env/env.go
generated
vendored
4
vendor/github.com/go-acme/lego/v4/platform/config/env/env.go
generated
vendored
@ -3,7 +3,6 @@ package env
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -55,7 +54,6 @@ func Get(names ...string) (map[string]string, error) {
|
|||||||
// // LEGO_TWO=""
|
// // LEGO_TWO=""
|
||||||
// env.GetWithFallback([]string{"LEGO_ONE", "LEGO_TWO"})
|
// env.GetWithFallback([]string{"LEGO_ONE", "LEGO_TWO"})
|
||||||
// // => error
|
// // => error
|
||||||
//
|
|
||||||
func GetWithFallback(groups ...[]string) (map[string]string, error) {
|
func GetWithFallback(groups ...[]string) (map[string]string, error) {
|
||||||
values := map[string]string{}
|
values := map[string]string{}
|
||||||
|
|
||||||
@ -155,7 +153,7 @@ func GetOrFile(envVar string) string {
|
|||||||
return envVarValue
|
return envVarValue
|
||||||
}
|
}
|
||||||
|
|
||||||
fileContents, err := ioutil.ReadFile(fileVarValue)
|
fileContents, err := os.ReadFile(fileVarValue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to read the file %s (defined by env var %s): %s", fileVarValue, fileVar, err)
|
log.Printf("Failed to read the file %s (defined by env var %s): %s", fileVarValue, fileVar, err)
|
||||||
return ""
|
return ""
|
||||||
|
10
vendor/github.com/go-acme/lego/v4/providers/dns/ovh/ovh.go
generated
vendored
10
vendor/github.com/go-acme/lego/v4/providers/dns/ovh/ovh.go
generated
vendored
@ -126,9 +126,9 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||||||
fqdn, value := dns01.GetRecord(domain, keyAuth)
|
fqdn, value := dns01.GetRecord(domain, keyAuth)
|
||||||
|
|
||||||
// Parse domain name
|
// Parse domain name
|
||||||
authZone, err := dns01.FindZoneByFqdn(dns01.ToFqdn(domain))
|
authZone, err := dns01.FindZoneByFqdn(fqdn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("ovh: could not determine zone for domain %q: %w", domain, err)
|
return fmt.Errorf("ovh: could not determine zone for domain %q: %w", fqdn, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
authZone = dns01.UnFqdn(authZone)
|
authZone = dns01.UnFqdn(authZone)
|
||||||
@ -170,9 +170,9 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|||||||
return fmt.Errorf("ovh: unknown record ID for '%s'", fqdn)
|
return fmt.Errorf("ovh: unknown record ID for '%s'", fqdn)
|
||||||
}
|
}
|
||||||
|
|
||||||
authZone, err := dns01.FindZoneByFqdn(dns01.ToFqdn(domain))
|
authZone, err := dns01.FindZoneByFqdn(fqdn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("ovh: could not determine zone for domain %q: %w", domain, err)
|
return fmt.Errorf("ovh: could not determine zone for domain %q: %w", fqdn, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
authZone = dns01.UnFqdn(authZone)
|
authZone = dns01.UnFqdn(authZone)
|
||||||
@ -210,5 +210,5 @@ func extractRecordName(fqdn, zone string) string {
|
|||||||
if idx := strings.Index(name, "."+zone); idx != -1 {
|
if idx := strings.Index(name, "."+zone); idx != -1 {
|
||||||
return name[:idx]
|
return name[:idx]
|
||||||
}
|
}
|
||||||
return name
|
return ""
|
||||||
}
|
}
|
||||||
|
2
vendor/github.com/go-acme/lego/v4/providers/dns/ovh/ovh.toml
generated
vendored
2
vendor/github.com/go-acme/lego/v4/providers/dns/ovh/ovh.toml
generated
vendored
@ -9,7 +9,7 @@ OVH_APPLICATION_KEY=1234567898765432 \
|
|||||||
OVH_APPLICATION_SECRET=b9841238feb177a84330febba8a832089 \
|
OVH_APPLICATION_SECRET=b9841238feb177a84330febba8a832089 \
|
||||||
OVH_CONSUMER_KEY=256vfsd347245sdfg \
|
OVH_CONSUMER_KEY=256vfsd347245sdfg \
|
||||||
OVH_ENDPOINT=ovh-eu \
|
OVH_ENDPOINT=ovh-eu \
|
||||||
lego --email myemail@example.com --dns ovh --domains my.example.org run
|
lego --email you@example.com --dns ovh --domains my.example.org run
|
||||||
'''
|
'''
|
||||||
|
|
||||||
Additional = '''
|
Additional = '''
|
||||||
|
2
vendor/github.com/go-acme/lego/v4/registration/registar.go
generated
vendored
2
vendor/github.com/go-acme/lego/v4/registration/registar.go
generated
vendored
@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
// Resource represents all important information about a registration
|
// Resource represents all important information about a registration
|
||||||
// of which the client needs to keep track itself.
|
// of which the client needs to keep track itself.
|
||||||
// WARNING: will be remove in the future (acme.ExtendedAccount), https://github.com/go-acme/lego/issues/855.
|
// WARNING: will be removed in the future (acme.ExtendedAccount), https://github.com/go-acme/lego/issues/855.
|
||||||
type Resource struct {
|
type Resource struct {
|
||||||
Body acme.Account `json:"body,omitempty"`
|
Body acme.Account `json:"body,omitempty"`
|
||||||
URI string `json:"uri,omitempty"`
|
URI string `json:"uri,omitempty"`
|
||||||
|
8
vendor/github.com/goccy/go-json/.golangci.yml
generated
vendored
8
vendor/github.com/goccy/go-json/.golangci.yml
generated
vendored
@ -48,6 +48,14 @@ linters:
|
|||||||
- nlreturn
|
- nlreturn
|
||||||
- testpackage
|
- testpackage
|
||||||
- wsl
|
- wsl
|
||||||
|
- varnamelen
|
||||||
|
- nilnil
|
||||||
|
- ireturn
|
||||||
|
- govet
|
||||||
|
- forcetypeassert
|
||||||
|
- cyclop
|
||||||
|
- containedctx
|
||||||
|
- revive
|
||||||
|
|
||||||
issues:
|
issues:
|
||||||
exclude-rules:
|
exclude-rules:
|
||||||
|
133
vendor/github.com/goccy/go-json/CHANGELOG.md
generated
vendored
133
vendor/github.com/goccy/go-json/CHANGELOG.md
generated
vendored
@ -1,3 +1,136 @@
|
|||||||
|
# v0.9.11 - 2022/08/18
|
||||||
|
|
||||||
|
### Fix bugs
|
||||||
|
|
||||||
|
* Fix unexpected behavior when buffer ends with backslash ( #383 )
|
||||||
|
* Fix stream decoding of escaped character ( #387 )
|
||||||
|
|
||||||
|
# v0.9.10 - 2022/07/15
|
||||||
|
|
||||||
|
### Fix bugs
|
||||||
|
|
||||||
|
* Fix boundary exception of type caching ( #382 )
|
||||||
|
|
||||||
|
# v0.9.9 - 2022/07/15
|
||||||
|
|
||||||
|
### Fix bugs
|
||||||
|
|
||||||
|
* Fix encoding of directed interface with typed nil ( #377 )
|
||||||
|
* Fix embedded primitive type encoding using alias ( #378 )
|
||||||
|
* Fix slice/array type encoding with types implementing MarshalJSON ( #379 )
|
||||||
|
* Fix unicode decoding when the expected buffer state is not met after reading ( #380 )
|
||||||
|
|
||||||
|
# v0.9.8 - 2022/06/30
|
||||||
|
|
||||||
|
### Fix bugs
|
||||||
|
|
||||||
|
* Fix decoding of surrogate-pair ( #365 )
|
||||||
|
* Fix handling of embedded primitive type ( #366 )
|
||||||
|
* Add validation of escape sequence for decoder ( #367 )
|
||||||
|
* Fix stream tokenizing respecting UseNumber ( #369 )
|
||||||
|
* Fix encoding when struct pointer type that implements Marshal JSON is embedded ( #375 )
|
||||||
|
|
||||||
|
### Improve performance
|
||||||
|
|
||||||
|
* Improve performance of linkRecursiveCode ( #368 )
|
||||||
|
|
||||||
|
# v0.9.7 - 2022/04/22
|
||||||
|
|
||||||
|
### Fix bugs
|
||||||
|
|
||||||
|
#### Encoder
|
||||||
|
|
||||||
|
* Add filtering process for encoding on slow path ( #355 )
|
||||||
|
* Fix encoding of interface{} with pointer type ( #363 )
|
||||||
|
|
||||||
|
#### Decoder
|
||||||
|
|
||||||
|
* Fix map key decoder that implements UnmarshalJSON ( #353 )
|
||||||
|
* Fix decoding of []uint8 type ( #361 )
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
* Add DebugWith option for encoder ( #356 )
|
||||||
|
|
||||||
|
# v0.9.6 - 2022/03/22
|
||||||
|
|
||||||
|
### Fix bugs
|
||||||
|
|
||||||
|
* Correct the handling of the minimum value of int type for decoder ( #344 )
|
||||||
|
* Fix bugs of stream decoder's bufferSize ( #349 )
|
||||||
|
* Add a guard to use typeptr more safely ( #351 )
|
||||||
|
|
||||||
|
### Improve decoder performance
|
||||||
|
|
||||||
|
* Improve escapeString's performance ( #345 )
|
||||||
|
|
||||||
|
### Others
|
||||||
|
|
||||||
|
* Update go version for CI ( #347 )
|
||||||
|
|
||||||
|
# v0.9.5 - 2022/03/04
|
||||||
|
|
||||||
|
### Fix bugs
|
||||||
|
|
||||||
|
* Fix panic when decoding time.Time with context ( #328 )
|
||||||
|
* Fix reading the next character in buffer to nul consideration ( #338 )
|
||||||
|
* Fix incorrect handling on skipValue ( #341 )
|
||||||
|
|
||||||
|
### Improve decoder performance
|
||||||
|
|
||||||
|
* Improve performance when a payload contains escape sequence ( #334 )
|
||||||
|
|
||||||
|
# v0.9.4 - 2022/01/21
|
||||||
|
|
||||||
|
* Fix IsNilForMarshaler for string type with omitempty ( #323 )
|
||||||
|
* Fix the case where the embedded field is at the end ( #326 )
|
||||||
|
|
||||||
|
# v0.9.3 - 2022/01/14
|
||||||
|
|
||||||
|
* Fix logic of removing struct field for decoder ( #322 )
|
||||||
|
|
||||||
|
# v0.9.2 - 2022/01/14
|
||||||
|
|
||||||
|
* Add invalid decoder to delay type error judgment at decode ( #321 )
|
||||||
|
|
||||||
|
# v0.9.1 - 2022/01/11
|
||||||
|
|
||||||
|
* Fix encoding of MarshalText/MarshalJSON operation with head offset ( #319 )
|
||||||
|
|
||||||
|
# v0.9.0 - 2022/01/05
|
||||||
|
|
||||||
|
### New feature
|
||||||
|
|
||||||
|
* Supports dynamic filtering of struct fields ( #314 )
|
||||||
|
|
||||||
|
### Improve encoding performance
|
||||||
|
|
||||||
|
* Improve map encoding performance ( #310 )
|
||||||
|
* Optimize encoding path for escaped string ( #311 )
|
||||||
|
* Add encoding option for performance ( #312 )
|
||||||
|
|
||||||
|
### Fix bugs
|
||||||
|
|
||||||
|
* Fix panic at encoding map value on 1.18 ( #310 )
|
||||||
|
* Fix MarshalIndent for interface type ( #317 )
|
||||||
|
|
||||||
|
# v0.8.1 - 2021/12/05
|
||||||
|
|
||||||
|
* Fix operation conversion from PtrHead to Head in Recursive type ( #305 )
|
||||||
|
|
||||||
|
# v0.8.0 - 2021/12/02
|
||||||
|
|
||||||
|
* Fix embedded field conflict behavior ( #300 )
|
||||||
|
* Refactor compiler for encoder ( #301 #302 )
|
||||||
|
|
||||||
|
# v0.7.10 - 2021/10/16
|
||||||
|
|
||||||
|
* Fix conversion from pointer to uint64 ( #294 )
|
||||||
|
|
||||||
|
# v0.7.9 - 2021/09/28
|
||||||
|
|
||||||
|
* Fix encoding of nil value about interface type that has method ( #291 )
|
||||||
|
|
||||||
# v0.7.8 - 2021/09/01
|
# v0.7.8 - 2021/09/01
|
||||||
|
|
||||||
* Fix mapassign_faststr for indirect struct type ( #283 )
|
* Fix mapassign_faststr for indirect struct type ( #283 )
|
||||||
|
6
vendor/github.com/goccy/go-json/README.md
generated
vendored
6
vendor/github.com/goccy/go-json/README.md
generated
vendored
@ -13,7 +13,7 @@ Fast JSON encoder/decoder compatible with encoding/json for Go
|
|||||||
```
|
```
|
||||||
* version ( expected release date )
|
* version ( expected release date )
|
||||||
|
|
||||||
* v0.7.0
|
* v0.9.0
|
||||||
|
|
|
|
||||||
| while maintaining compatibility with encoding/json, we will add convenient APIs
|
| while maintaining compatibility with encoding/json, we will add convenient APIs
|
||||||
|
|
|
|
||||||
@ -21,9 +21,8 @@ Fast JSON encoder/decoder compatible with encoding/json for Go
|
|||||||
* v1.0.0
|
* v1.0.0
|
||||||
```
|
```
|
||||||
|
|
||||||
We are accepting requests for features that will be implemented between v0.7.0 and v.1.0.0.
|
We are accepting requests for features that will be implemented between v0.9.0 and v.1.0.0.
|
||||||
If you have the API you need, please submit your issue [here](https://github.com/goccy/go-json/issues).
|
If you have the API you need, please submit your issue [here](https://github.com/goccy/go-json/issues).
|
||||||
For example, I'm thinking of supporting `context.Context` of `json.Marshaler` and decoding using JSON Path.
|
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
|
|
||||||
@ -32,6 +31,7 @@ For example, I'm thinking of supporting `context.Context` of `json.Marshaler` an
|
|||||||
- Flexible customization with options
|
- Flexible customization with options
|
||||||
- Coloring the encoded string
|
- Coloring the encoded string
|
||||||
- Can propagate context.Context to `MarshalJSON` or `UnmarshalJSON`
|
- Can propagate context.Context to `MarshalJSON` or `UnmarshalJSON`
|
||||||
|
- Can dynamically filter the fields of the structure type-safely
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
|
|
||||||
|
2
vendor/github.com/goccy/go-json/docker-compose.yml
generated
vendored
2
vendor/github.com/goccy/go-json/docker-compose.yml
generated
vendored
@ -1,7 +1,7 @@
|
|||||||
version: '2'
|
version: '2'
|
||||||
services:
|
services:
|
||||||
go-json:
|
go-json:
|
||||||
image: golang:1.16
|
image: golang:1.18
|
||||||
volumes:
|
volumes:
|
||||||
- '.:/go/src/go-json'
|
- '.:/go/src/go-json'
|
||||||
deploy:
|
deploy:
|
||||||
|
17
vendor/github.com/goccy/go-json/encode.go
generated
vendored
17
vendor/github.com/goccy/go-json/encode.go
generated
vendored
@ -3,6 +3,7 @@ package json
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
"os"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goccy/go-json/internal/encoder"
|
"github.com/goccy/go-json/internal/encoder"
|
||||||
@ -61,6 +62,8 @@ func (e *Encoder) encodeWithOption(ctx *encoder.RuntimeContext, v interface{}, o
|
|||||||
if e.enabledHTMLEscape {
|
if e.enabledHTMLEscape {
|
||||||
ctx.Option.Flag |= encoder.HTMLEscapeOption
|
ctx.Option.Flag |= encoder.HTMLEscapeOption
|
||||||
}
|
}
|
||||||
|
ctx.Option.Flag |= encoder.NormalizeUTF8Option
|
||||||
|
ctx.Option.DebugOut = os.Stdout
|
||||||
for _, optFunc := range optFuncs {
|
for _, optFunc := range optFuncs {
|
||||||
optFunc(ctx.Option)
|
optFunc(ctx.Option)
|
||||||
}
|
}
|
||||||
@ -111,7 +114,7 @@ func (e *Encoder) SetIndent(prefix, indent string) {
|
|||||||
func marshalContext(ctx context.Context, v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) {
|
func marshalContext(ctx context.Context, v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) {
|
||||||
rctx := encoder.TakeRuntimeContext()
|
rctx := encoder.TakeRuntimeContext()
|
||||||
rctx.Option.Flag = 0
|
rctx.Option.Flag = 0
|
||||||
rctx.Option.Flag = encoder.HTMLEscapeOption | encoder.ContextOption
|
rctx.Option.Flag = encoder.HTMLEscapeOption | encoder.NormalizeUTF8Option | encoder.ContextOption
|
||||||
rctx.Option.Context = ctx
|
rctx.Option.Context = ctx
|
||||||
for _, optFunc := range optFuncs {
|
for _, optFunc := range optFuncs {
|
||||||
optFunc(rctx.Option)
|
optFunc(rctx.Option)
|
||||||
@ -139,7 +142,7 @@ func marshal(v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) {
|
|||||||
ctx := encoder.TakeRuntimeContext()
|
ctx := encoder.TakeRuntimeContext()
|
||||||
|
|
||||||
ctx.Option.Flag = 0
|
ctx.Option.Flag = 0
|
||||||
ctx.Option.Flag |= encoder.HTMLEscapeOption
|
ctx.Option.Flag |= (encoder.HTMLEscapeOption | encoder.NormalizeUTF8Option)
|
||||||
for _, optFunc := range optFuncs {
|
for _, optFunc := range optFuncs {
|
||||||
optFunc(ctx.Option)
|
optFunc(ctx.Option)
|
||||||
}
|
}
|
||||||
@ -166,7 +169,7 @@ func marshalNoEscape(v interface{}) ([]byte, error) {
|
|||||||
ctx := encoder.TakeRuntimeContext()
|
ctx := encoder.TakeRuntimeContext()
|
||||||
|
|
||||||
ctx.Option.Flag = 0
|
ctx.Option.Flag = 0
|
||||||
ctx.Option.Flag |= encoder.HTMLEscapeOption
|
ctx.Option.Flag |= (encoder.HTMLEscapeOption | encoder.NormalizeUTF8Option)
|
||||||
|
|
||||||
buf, err := encodeNoEscape(ctx, v)
|
buf, err := encodeNoEscape(ctx, v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -190,7 +193,7 @@ func marshalIndent(v interface{}, prefix, indent string, optFuncs ...EncodeOptio
|
|||||||
ctx := encoder.TakeRuntimeContext()
|
ctx := encoder.TakeRuntimeContext()
|
||||||
|
|
||||||
ctx.Option.Flag = 0
|
ctx.Option.Flag = 0
|
||||||
ctx.Option.Flag |= (encoder.HTMLEscapeOption | encoder.IndentOption)
|
ctx.Option.Flag |= (encoder.HTMLEscapeOption | encoder.NormalizeUTF8Option | encoder.IndentOption)
|
||||||
for _, optFunc := range optFuncs {
|
for _, optFunc := range optFuncs {
|
||||||
optFunc(ctx.Option)
|
optFunc(ctx.Option)
|
||||||
}
|
}
|
||||||
@ -220,7 +223,7 @@ func encode(ctx *encoder.RuntimeContext, v interface{}) ([]byte, error) {
|
|||||||
typ := header.typ
|
typ := header.typ
|
||||||
|
|
||||||
typeptr := uintptr(unsafe.Pointer(typ))
|
typeptr := uintptr(unsafe.Pointer(typ))
|
||||||
codeSet, err := encoder.CompileToGetCodeSet(typeptr)
|
codeSet, err := encoder.CompileToGetCodeSet(ctx, typeptr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -248,7 +251,7 @@ func encodeNoEscape(ctx *encoder.RuntimeContext, v interface{}) ([]byte, error)
|
|||||||
typ := header.typ
|
typ := header.typ
|
||||||
|
|
||||||
typeptr := uintptr(unsafe.Pointer(typ))
|
typeptr := uintptr(unsafe.Pointer(typ))
|
||||||
codeSet, err := encoder.CompileToGetCodeSet(typeptr)
|
codeSet, err := encoder.CompileToGetCodeSet(ctx, typeptr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -275,7 +278,7 @@ func encodeIndent(ctx *encoder.RuntimeContext, v interface{}, prefix, indent str
|
|||||||
typ := header.typ
|
typ := header.typ
|
||||||
|
|
||||||
typeptr := uintptr(unsafe.Pointer(typ))
|
typeptr := uintptr(unsafe.Pointer(typ))
|
||||||
codeSet, err := encoder.CompileToGetCodeSet(typeptr)
|
codeSet, err := encoder.CompileToGetCodeSet(ctx, typeptr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
5
vendor/github.com/goccy/go-json/internal/decoder/bytes.go
generated
vendored
5
vendor/github.com/goccy/go-json/internal/decoder/bytes.go
generated
vendored
@ -23,9 +23,8 @@ func byteUnmarshalerSliceDecoder(typ *runtime.Type, structName string, fieldName
|
|||||||
unmarshalDecoder = newUnmarshalJSONDecoder(runtime.PtrTo(typ), structName, fieldName)
|
unmarshalDecoder = newUnmarshalJSONDecoder(runtime.PtrTo(typ), structName, fieldName)
|
||||||
case runtime.PtrTo(typ).Implements(unmarshalTextType):
|
case runtime.PtrTo(typ).Implements(unmarshalTextType):
|
||||||
unmarshalDecoder = newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName)
|
unmarshalDecoder = newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName)
|
||||||
}
|
default:
|
||||||
if unmarshalDecoder == nil {
|
unmarshalDecoder, _ = compileUint8(typ, structName, fieldName)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
return newSliceDecoder(unmarshalDecoder, typ, 1, structName, fieldName)
|
return newSliceDecoder(unmarshalDecoder, typ, 1, structName, fieldName)
|
||||||
}
|
}
|
||||||
|
197
vendor/github.com/goccy/go-json/internal/decoder/compile.go
generated
vendored
197
vendor/github.com/goccy/go-json/internal/decoder/compile.go
generated
vendored
@ -9,7 +9,6 @@ import (
|
|||||||
"unicode"
|
"unicode"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goccy/go-json/internal/errors"
|
|
||||||
"github.com/goccy/go-json/internal/runtime"
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -25,7 +24,7 @@ func init() {
|
|||||||
if typeAddr == nil {
|
if typeAddr == nil {
|
||||||
typeAddr = &runtime.TypeAddr{}
|
typeAddr = &runtime.TypeAddr{}
|
||||||
}
|
}
|
||||||
cachedDecoder = make([]Decoder, typeAddr.AddrRange>>typeAddr.AddrShift)
|
cachedDecoder = make([]Decoder, typeAddr.AddrRange>>typeAddr.AddrShift+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadDecoderMap() map[uintptr]Decoder {
|
func loadDecoderMap() map[uintptr]Decoder {
|
||||||
@ -126,13 +125,7 @@ func compile(typ *runtime.Type, structName, fieldName string, structTypeToDecode
|
|||||||
case reflect.Func:
|
case reflect.Func:
|
||||||
return compileFunc(typ, structName, fieldName)
|
return compileFunc(typ, structName, fieldName)
|
||||||
}
|
}
|
||||||
return nil, &errors.UnmarshalTypeError{
|
return newInvalidDecoder(typ, structName, fieldName), nil
|
||||||
Value: "object",
|
|
||||||
Type: runtime.RType2Type(typ),
|
|
||||||
Offset: 0,
|
|
||||||
Struct: structName,
|
|
||||||
Field: fieldName,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func isStringTagSupportedType(typ *runtime.Type) bool {
|
func isStringTagSupportedType(typ *runtime.Type) bool {
|
||||||
@ -161,6 +154,9 @@ func compileMapKey(typ *runtime.Type, structName, fieldName string, structTypeTo
|
|||||||
if runtime.PtrTo(typ).Implements(unmarshalTextType) {
|
if runtime.PtrTo(typ).Implements(unmarshalTextType) {
|
||||||
return newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName), nil
|
return newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName), nil
|
||||||
}
|
}
|
||||||
|
if typ.Kind() == reflect.String {
|
||||||
|
return newStringDecoder(structName, fieldName), nil
|
||||||
|
}
|
||||||
dec, err := compile(typ, structName, fieldName, structTypeToDecoder)
|
dec, err := compile(typ, structName, fieldName, structTypeToDecoder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -174,17 +170,9 @@ func compileMapKey(typ *runtime.Type, structName, fieldName string, structTypeTo
|
|||||||
case *ptrDecoder:
|
case *ptrDecoder:
|
||||||
dec = t.dec
|
dec = t.dec
|
||||||
default:
|
default:
|
||||||
goto ERROR
|
return newInvalidDecoder(typ, structName, fieldName), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ERROR:
|
|
||||||
return nil, &errors.UnmarshalTypeError{
|
|
||||||
Value: "object",
|
|
||||||
Type: runtime.RType2Type(typ),
|
|
||||||
Offset: 0,
|
|
||||||
Struct: structName,
|
|
||||||
Field: fieldName,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func compilePtr(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
|
func compilePtr(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
|
||||||
@ -322,64 +310,21 @@ func compileFunc(typ *runtime.Type, strutName, fieldName string) (Decoder, error
|
|||||||
return newFuncDecoder(typ, strutName, fieldName), nil
|
return newFuncDecoder(typ, strutName, fieldName), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeConflictFields(fieldMap map[string]*structFieldSet, conflictedMap map[string]struct{}, dec *structDecoder, field reflect.StructField) {
|
func typeToStructTags(typ *runtime.Type) runtime.StructTags {
|
||||||
for k, v := range dec.fieldMap {
|
tags := runtime.StructTags{}
|
||||||
if _, exists := conflictedMap[k]; exists {
|
fieldNum := typ.NumField()
|
||||||
// already conflicted key
|
for i := 0; i < fieldNum; i++ {
|
||||||
|
field := typ.Field(i)
|
||||||
|
if runtime.IsIgnoredStructField(field) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
set, exists := fieldMap[k]
|
tags = append(tags, runtime.StructTagFromField(field))
|
||||||
if !exists {
|
|
||||||
fieldSet := &structFieldSet{
|
|
||||||
dec: v.dec,
|
|
||||||
offset: field.Offset + v.offset,
|
|
||||||
isTaggedKey: v.isTaggedKey,
|
|
||||||
key: k,
|
|
||||||
keyLen: int64(len(k)),
|
|
||||||
}
|
|
||||||
fieldMap[k] = fieldSet
|
|
||||||
lower := strings.ToLower(k)
|
|
||||||
if _, exists := fieldMap[lower]; !exists {
|
|
||||||
fieldMap[lower] = fieldSet
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if set.isTaggedKey {
|
|
||||||
if v.isTaggedKey {
|
|
||||||
// conflict tag key
|
|
||||||
delete(fieldMap, k)
|
|
||||||
delete(fieldMap, strings.ToLower(k))
|
|
||||||
conflictedMap[k] = struct{}{}
|
|
||||||
conflictedMap[strings.ToLower(k)] = struct{}{}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if v.isTaggedKey {
|
|
||||||
fieldSet := &structFieldSet{
|
|
||||||
dec: v.dec,
|
|
||||||
offset: field.Offset + v.offset,
|
|
||||||
isTaggedKey: v.isTaggedKey,
|
|
||||||
key: k,
|
|
||||||
keyLen: int64(len(k)),
|
|
||||||
}
|
|
||||||
fieldMap[k] = fieldSet
|
|
||||||
lower := strings.ToLower(k)
|
|
||||||
if _, exists := fieldMap[lower]; !exists {
|
|
||||||
fieldMap[lower] = fieldSet
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// conflict tag key
|
|
||||||
delete(fieldMap, k)
|
|
||||||
delete(fieldMap, strings.ToLower(k))
|
|
||||||
conflictedMap[k] = struct{}{}
|
|
||||||
conflictedMap[strings.ToLower(k)] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return tags
|
||||||
}
|
}
|
||||||
|
|
||||||
func compileStruct(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
|
func compileStruct(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
|
||||||
fieldNum := typ.NumField()
|
fieldNum := typ.NumField()
|
||||||
conflictedMap := map[string]struct{}{}
|
|
||||||
fieldMap := map[string]*structFieldSet{}
|
fieldMap := map[string]*structFieldSet{}
|
||||||
typeptr := uintptr(unsafe.Pointer(typ))
|
typeptr := uintptr(unsafe.Pointer(typ))
|
||||||
if dec, exists := structTypeToDecoder[typeptr]; exists {
|
if dec, exists := structTypeToDecoder[typeptr]; exists {
|
||||||
@ -388,6 +333,8 @@ func compileStruct(typ *runtime.Type, structName, fieldName string, structTypeTo
|
|||||||
structDec := newStructDecoder(structName, fieldName, fieldMap)
|
structDec := newStructDecoder(structName, fieldName, fieldMap)
|
||||||
structTypeToDecoder[typeptr] = structDec
|
structTypeToDecoder[typeptr] = structDec
|
||||||
structName = typ.Name()
|
structName = typ.Name()
|
||||||
|
tags := typeToStructTags(typ)
|
||||||
|
allFields := []*structFieldSet{}
|
||||||
for i := 0; i < fieldNum; i++ {
|
for i := 0; i < fieldNum; i++ {
|
||||||
field := typ.Field(i)
|
field := typ.Field(i)
|
||||||
if runtime.IsIgnoredStructField(field) {
|
if runtime.IsIgnoredStructField(field) {
|
||||||
@ -405,7 +352,19 @@ func compileStruct(typ *runtime.Type, structName, fieldName string, structTypeTo
|
|||||||
// recursive definition
|
// recursive definition
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
removeConflictFields(fieldMap, conflictedMap, stDec, field)
|
for k, v := range stDec.fieldMap {
|
||||||
|
if tags.ExistsKey(k) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fieldSet := &structFieldSet{
|
||||||
|
dec: v.dec,
|
||||||
|
offset: field.Offset + v.offset,
|
||||||
|
isTaggedKey: v.isTaggedKey,
|
||||||
|
key: k,
|
||||||
|
keyLen: int64(len(k)),
|
||||||
|
}
|
||||||
|
allFields = append(allFields, fieldSet)
|
||||||
|
}
|
||||||
} else if pdec, ok := dec.(*ptrDecoder); ok {
|
} else if pdec, ok := dec.(*ptrDecoder); ok {
|
||||||
contentDec := pdec.contentDecoder()
|
contentDec := pdec.contentDecoder()
|
||||||
if pdec.typ == typ {
|
if pdec.typ == typ {
|
||||||
@ -421,12 +380,9 @@ func compileStruct(typ *runtime.Type, structName, fieldName string, structTypeTo
|
|||||||
}
|
}
|
||||||
if dec, ok := contentDec.(*structDecoder); ok {
|
if dec, ok := contentDec.(*structDecoder); ok {
|
||||||
for k, v := range dec.fieldMap {
|
for k, v := range dec.fieldMap {
|
||||||
if _, exists := conflictedMap[k]; exists {
|
if tags.ExistsKey(k) {
|
||||||
// already conflicted key
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
set, exists := fieldMap[k]
|
|
||||||
if !exists {
|
|
||||||
fieldSet := &structFieldSet{
|
fieldSet := &structFieldSet{
|
||||||
dec: newAnonymousFieldDecoder(pdec.typ, v.offset, v.dec),
|
dec: newAnonymousFieldDecoder(pdec.typ, v.offset, v.dec),
|
||||||
offset: field.Offset,
|
offset: field.Offset,
|
||||||
@ -435,46 +391,27 @@ func compileStruct(typ *runtime.Type, structName, fieldName string, structTypeTo
|
|||||||
keyLen: int64(len(k)),
|
keyLen: int64(len(k)),
|
||||||
err: fieldSetErr,
|
err: fieldSetErr,
|
||||||
}
|
}
|
||||||
fieldMap[k] = fieldSet
|
allFields = append(allFields, fieldSet)
|
||||||
lower := strings.ToLower(k)
|
|
||||||
if _, exists := fieldMap[lower]; !exists {
|
|
||||||
fieldMap[lower] = fieldSet
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if set.isTaggedKey {
|
|
||||||
if v.isTaggedKey {
|
|
||||||
// conflict tag key
|
|
||||||
delete(fieldMap, k)
|
|
||||||
delete(fieldMap, strings.ToLower(k))
|
|
||||||
conflictedMap[k] = struct{}{}
|
|
||||||
conflictedMap[strings.ToLower(k)] = struct{}{}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if v.isTaggedKey {
|
|
||||||
fieldSet := &structFieldSet{
|
fieldSet := &structFieldSet{
|
||||||
dec: newAnonymousFieldDecoder(pdec.typ, v.offset, v.dec),
|
dec: pdec,
|
||||||
offset: field.Offset,
|
offset: field.Offset,
|
||||||
isTaggedKey: v.isTaggedKey,
|
isTaggedKey: tag.IsTaggedKey,
|
||||||
key: k,
|
key: field.Name,
|
||||||
keyLen: int64(len(k)),
|
keyLen: int64(len(field.Name)),
|
||||||
err: fieldSetErr,
|
|
||||||
}
|
}
|
||||||
fieldMap[k] = fieldSet
|
allFields = append(allFields, fieldSet)
|
||||||
lower := strings.ToLower(k)
|
|
||||||
if _, exists := fieldMap[lower]; !exists {
|
|
||||||
fieldMap[lower] = fieldSet
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// conflict tag key
|
fieldSet := &structFieldSet{
|
||||||
delete(fieldMap, k)
|
dec: dec,
|
||||||
delete(fieldMap, strings.ToLower(k))
|
offset: field.Offset,
|
||||||
conflictedMap[k] = struct{}{}
|
isTaggedKey: tag.IsTaggedKey,
|
||||||
conflictedMap[strings.ToLower(k)] = struct{}{}
|
key: field.Name,
|
||||||
}
|
keyLen: int64(len(field.Name)),
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
allFields = append(allFields, fieldSet)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if tag.IsString && isStringTagSupportedType(runtime.Type2RType(field.Type)) {
|
if tag.IsString && isStringTagSupportedType(runtime.Type2RType(field.Type)) {
|
||||||
@ -493,18 +430,58 @@ func compileStruct(typ *runtime.Type, structName, fieldName string, structTypeTo
|
|||||||
key: key,
|
key: key,
|
||||||
keyLen: int64(len(key)),
|
keyLen: int64(len(key)),
|
||||||
}
|
}
|
||||||
fieldMap[key] = fieldSet
|
allFields = append(allFields, fieldSet)
|
||||||
lower := strings.ToLower(key)
|
|
||||||
if _, exists := fieldMap[lower]; !exists {
|
|
||||||
fieldMap[lower] = fieldSet
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, set := range filterDuplicatedFields(allFields) {
|
||||||
|
fieldMap[set.key] = set
|
||||||
|
lower := strings.ToLower(set.key)
|
||||||
|
if _, exists := fieldMap[lower]; !exists {
|
||||||
|
// first win
|
||||||
|
fieldMap[lower] = set
|
||||||
|
}
|
||||||
}
|
}
|
||||||
delete(structTypeToDecoder, typeptr)
|
delete(structTypeToDecoder, typeptr)
|
||||||
structDec.tryOptimize()
|
structDec.tryOptimize()
|
||||||
return structDec, nil
|
return structDec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func filterDuplicatedFields(allFields []*structFieldSet) []*structFieldSet {
|
||||||
|
fieldMap := map[string][]*structFieldSet{}
|
||||||
|
for _, field := range allFields {
|
||||||
|
fieldMap[field.key] = append(fieldMap[field.key], field)
|
||||||
|
}
|
||||||
|
duplicatedFieldMap := map[string]struct{}{}
|
||||||
|
for k, sets := range fieldMap {
|
||||||
|
sets = filterFieldSets(sets)
|
||||||
|
if len(sets) != 1 {
|
||||||
|
duplicatedFieldMap[k] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
filtered := make([]*structFieldSet, 0, len(allFields))
|
||||||
|
for _, field := range allFields {
|
||||||
|
if _, exists := duplicatedFieldMap[field.key]; exists {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
filtered = append(filtered, field)
|
||||||
|
}
|
||||||
|
return filtered
|
||||||
|
}
|
||||||
|
|
||||||
|
func filterFieldSets(sets []*structFieldSet) []*structFieldSet {
|
||||||
|
if len(sets) == 1 {
|
||||||
|
return sets
|
||||||
|
}
|
||||||
|
filtered := make([]*structFieldSet, 0, len(sets))
|
||||||
|
for _, set := range sets {
|
||||||
|
if set.isTaggedKey {
|
||||||
|
filtered = append(filtered, set)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filtered
|
||||||
|
}
|
||||||
|
|
||||||
func implementsUnmarshalJSONType(typ *runtime.Type) bool {
|
func implementsUnmarshalJSONType(typ *runtime.Type) bool {
|
||||||
return typ.Implements(unmarshalJSONType) || typ.Implements(unmarshalJSONContextType)
|
return typ.Implements(unmarshalJSONType) || typ.Implements(unmarshalJSONContextType)
|
||||||
}
|
}
|
||||||
|
1
vendor/github.com/goccy/go-json/internal/decoder/compile_norace.go
generated
vendored
1
vendor/github.com/goccy/go-json/internal/decoder/compile_norace.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build !race
|
||||||
// +build !race
|
// +build !race
|
||||||
|
|
||||||
package decoder
|
package decoder
|
||||||
|
1
vendor/github.com/goccy/go-json/internal/decoder/compile_race.go
generated
vendored
1
vendor/github.com/goccy/go-json/internal/decoder/compile_race.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build race
|
||||||
// +build race
|
// +build race
|
||||||
|
|
||||||
package decoder
|
package decoder
|
||||||
|
12
vendor/github.com/goccy/go-json/internal/decoder/int.go
generated
vendored
12
vendor/github.com/goccy/go-json/internal/decoder/int.go
generated
vendored
@ -192,15 +192,15 @@ func (d *intDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) erro
|
|||||||
}
|
}
|
||||||
switch d.kind {
|
switch d.kind {
|
||||||
case reflect.Int8:
|
case reflect.Int8:
|
||||||
if i64 <= -1*(1<<7) || (1<<7) <= i64 {
|
if i64 < -1*(1<<7) || (1<<7) <= i64 {
|
||||||
return d.typeError(bytes, s.totalOffset())
|
return d.typeError(bytes, s.totalOffset())
|
||||||
}
|
}
|
||||||
case reflect.Int16:
|
case reflect.Int16:
|
||||||
if i64 <= -1*(1<<15) || (1<<15) <= i64 {
|
if i64 < -1*(1<<15) || (1<<15) <= i64 {
|
||||||
return d.typeError(bytes, s.totalOffset())
|
return d.typeError(bytes, s.totalOffset())
|
||||||
}
|
}
|
||||||
case reflect.Int32:
|
case reflect.Int32:
|
||||||
if i64 <= -1*(1<<31) || (1<<31) <= i64 {
|
if i64 < -1*(1<<31) || (1<<31) <= i64 {
|
||||||
return d.typeError(bytes, s.totalOffset())
|
return d.typeError(bytes, s.totalOffset())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -225,15 +225,15 @@ func (d *intDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.P
|
|||||||
}
|
}
|
||||||
switch d.kind {
|
switch d.kind {
|
||||||
case reflect.Int8:
|
case reflect.Int8:
|
||||||
if i64 <= -1*(1<<7) || (1<<7) <= i64 {
|
if i64 < -1*(1<<7) || (1<<7) <= i64 {
|
||||||
return 0, d.typeError(bytes, cursor)
|
return 0, d.typeError(bytes, cursor)
|
||||||
}
|
}
|
||||||
case reflect.Int16:
|
case reflect.Int16:
|
||||||
if i64 <= -1*(1<<15) || (1<<15) <= i64 {
|
if i64 < -1*(1<<15) || (1<<15) <= i64 {
|
||||||
return 0, d.typeError(bytes, cursor)
|
return 0, d.typeError(bytes, cursor)
|
||||||
}
|
}
|
||||||
case reflect.Int32:
|
case reflect.Int32:
|
||||||
if i64 <= -1*(1<<31) || (1<<31) <= i64 {
|
if i64 < -1*(1<<31) || (1<<31) <= i64 {
|
||||||
return 0, d.typeError(bytes, cursor)
|
return 0, d.typeError(bytes, cursor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
45
vendor/github.com/goccy/go-json/internal/decoder/invalid.go
generated
vendored
Normal file
45
vendor/github.com/goccy/go-json/internal/decoder/invalid.go
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package decoder
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/errors"
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
type invalidDecoder struct {
|
||||||
|
typ *runtime.Type
|
||||||
|
kind reflect.Kind
|
||||||
|
structName string
|
||||||
|
fieldName string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newInvalidDecoder(typ *runtime.Type, structName, fieldName string) *invalidDecoder {
|
||||||
|
return &invalidDecoder{
|
||||||
|
typ: typ,
|
||||||
|
kind: typ.Kind(),
|
||||||
|
structName: structName,
|
||||||
|
fieldName: fieldName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *invalidDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||||
|
return &errors.UnmarshalTypeError{
|
||||||
|
Value: "object",
|
||||||
|
Type: runtime.RType2Type(d.typ),
|
||||||
|
Offset: s.totalOffset(),
|
||||||
|
Struct: d.structName,
|
||||||
|
Field: d.fieldName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *invalidDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||||
|
return 0, &errors.UnmarshalTypeError{
|
||||||
|
Value: "object",
|
||||||
|
Type: runtime.RType2Type(d.typ),
|
||||||
|
Offset: cursor,
|
||||||
|
Struct: d.structName,
|
||||||
|
Field: d.fieldName,
|
||||||
|
}
|
||||||
|
}
|
7
vendor/github.com/goccy/go-json/internal/decoder/map.go
generated
vendored
7
vendor/github.com/goccy/go-json/internal/decoder/map.go
generated
vendored
@ -87,13 +87,13 @@ func (d *mapDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) erro
|
|||||||
if mapValue == nil {
|
if mapValue == nil {
|
||||||
mapValue = makemap(d.mapType, 0)
|
mapValue = makemap(d.mapType, 0)
|
||||||
}
|
}
|
||||||
if s.buf[s.cursor+1] == '}' {
|
s.cursor++
|
||||||
|
if s.equalChar('}') {
|
||||||
*(*unsafe.Pointer)(p) = mapValue
|
*(*unsafe.Pointer)(p) = mapValue
|
||||||
s.cursor += 2
|
s.cursor++
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
s.cursor++
|
|
||||||
k := unsafe_New(d.keyType)
|
k := unsafe_New(d.keyType)
|
||||||
if err := d.keyDecoder.DecodeStream(s, depth, k); err != nil {
|
if err := d.keyDecoder.DecodeStream(s, depth, k); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -117,6 +117,7 @@ func (d *mapDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) erro
|
|||||||
if !s.equalChar(',') {
|
if !s.equalChar(',') {
|
||||||
return errors.ErrExpected("comma after object value", s.totalOffset())
|
return errors.ErrExpected("comma after object value", s.totalOffset())
|
||||||
}
|
}
|
||||||
|
s.cursor++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
vendor/github.com/goccy/go-json/internal/decoder/stream.go
generated
vendored
16
vendor/github.com/goccy/go-json/internal/decoder/stream.go
generated
vendored
@ -103,7 +103,7 @@ func (s *Stream) statForRetry() ([]byte, int64, unsafe.Pointer) {
|
|||||||
|
|
||||||
func (s *Stream) Reset() {
|
func (s *Stream) Reset() {
|
||||||
s.reset()
|
s.reset()
|
||||||
s.bufSize = initBufSize
|
s.bufSize = int64(len(s.buf))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stream) More() bool {
|
func (s *Stream) More() bool {
|
||||||
@ -138,8 +138,11 @@ func (s *Stream) Token() (interface{}, error) {
|
|||||||
s.cursor++
|
s.cursor++
|
||||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
bytes := floatBytes(s)
|
bytes := floatBytes(s)
|
||||||
s := *(*string)(unsafe.Pointer(&bytes))
|
str := *(*string)(unsafe.Pointer(&bytes))
|
||||||
f64, err := strconv.ParseFloat(s, 64)
|
if s.UseNumber {
|
||||||
|
return json.Number(str), nil
|
||||||
|
}
|
||||||
|
f64, err := strconv.ParseFloat(str, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -277,7 +280,7 @@ func (s *Stream) skipObject(depth int64) error {
|
|||||||
if char(p, cursor) == nul {
|
if char(p, cursor) == nul {
|
||||||
s.cursor = cursor
|
s.cursor = cursor
|
||||||
if s.read() {
|
if s.read() {
|
||||||
_, cursor, p = s.statForRetry()
|
_, cursor, p = s.stat()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||||
@ -340,7 +343,7 @@ func (s *Stream) skipArray(depth int64) error {
|
|||||||
if char(p, cursor) == nul {
|
if char(p, cursor) == nul {
|
||||||
s.cursor = cursor
|
s.cursor = cursor
|
||||||
if s.read() {
|
if s.read() {
|
||||||
_, cursor, p = s.statForRetry()
|
_, cursor, p = s.stat()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||||
@ -398,7 +401,7 @@ func (s *Stream) skipValue(depth int64) error {
|
|||||||
if char(p, cursor) == nul {
|
if char(p, cursor) == nul {
|
||||||
s.cursor = cursor
|
s.cursor = cursor
|
||||||
if s.read() {
|
if s.read() {
|
||||||
_, cursor, p = s.statForRetry()
|
_, cursor, p = s.stat()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset())
|
return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset())
|
||||||
@ -423,7 +426,6 @@ func (s *Stream) skipValue(depth int64) error {
|
|||||||
continue
|
continue
|
||||||
} else if c == nul {
|
} else if c == nul {
|
||||||
if s.read() {
|
if s.read() {
|
||||||
s.cursor-- // for retry current character
|
|
||||||
_, cursor, p = s.stat()
|
_, cursor, p = s.stat()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
140
vendor/github.com/goccy/go-json/internal/decoder/string.go
generated
vendored
140
vendor/github.com/goccy/go-json/internal/decoder/string.go
generated
vendored
@ -1,6 +1,8 @@
|
|||||||
package decoder
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf16"
|
"unicode/utf16"
|
||||||
@ -93,24 +95,30 @@ func unicodeToRune(code []byte) rune {
|
|||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func readAtLeast(s *Stream, n int64, p *unsafe.Pointer) bool {
|
||||||
|
for s.cursor+n >= s.length {
|
||||||
|
if !s.read() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
*p = s.bufptr()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func decodeUnicodeRune(s *Stream, p unsafe.Pointer) (rune, int64, unsafe.Pointer, error) {
|
func decodeUnicodeRune(s *Stream, p unsafe.Pointer) (rune, int64, unsafe.Pointer, error) {
|
||||||
const defaultOffset = 5
|
const defaultOffset = 5
|
||||||
const surrogateOffset = 11
|
const surrogateOffset = 11
|
||||||
|
|
||||||
if s.cursor+defaultOffset >= s.length {
|
if !readAtLeast(s, defaultOffset, &p) {
|
||||||
if !s.read() {
|
|
||||||
return rune(0), 0, nil, errors.ErrInvalidCharacter(s.char(), "escaped string", s.totalOffset())
|
return rune(0), 0, nil, errors.ErrInvalidCharacter(s.char(), "escaped string", s.totalOffset())
|
||||||
}
|
}
|
||||||
p = s.bufptr()
|
|
||||||
}
|
|
||||||
|
|
||||||
r := unicodeToRune(s.buf[s.cursor+1 : s.cursor+defaultOffset])
|
r := unicodeToRune(s.buf[s.cursor+1 : s.cursor+defaultOffset])
|
||||||
if utf16.IsSurrogate(r) {
|
if utf16.IsSurrogate(r) {
|
||||||
if s.cursor+surrogateOffset >= s.length {
|
if !readAtLeast(s, surrogateOffset, &p) {
|
||||||
s.read()
|
return unicode.ReplacementChar, defaultOffset, p, nil
|
||||||
p = s.bufptr()
|
|
||||||
}
|
}
|
||||||
if s.cursor+surrogateOffset >= s.length || s.buf[s.cursor+defaultOffset] != '\\' || s.buf[s.cursor+defaultOffset+1] != 'u' {
|
if s.buf[s.cursor+defaultOffset] != '\\' || s.buf[s.cursor+defaultOffset+1] != 'u' {
|
||||||
return unicode.ReplacementChar, defaultOffset, p, nil
|
return unicode.ReplacementChar, defaultOffset, p, nil
|
||||||
}
|
}
|
||||||
r2 := unicodeToRune(s.buf[s.cursor+defaultOffset+2 : s.cursor+surrogateOffset])
|
r2 := unicodeToRune(s.buf[s.cursor+defaultOffset+2 : s.cursor+surrogateOffset])
|
||||||
@ -163,6 +171,7 @@ RETRY:
|
|||||||
if !s.read() {
|
if !s.read() {
|
||||||
return nil, errors.ErrInvalidCharacter(s.char(), "escaped string", s.totalOffset())
|
return nil, errors.ErrInvalidCharacter(s.char(), "escaped string", s.totalOffset())
|
||||||
}
|
}
|
||||||
|
p = s.bufptr()
|
||||||
goto RETRY
|
goto RETRY
|
||||||
default:
|
default:
|
||||||
return nil, errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
return nil, errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||||
@ -308,49 +317,36 @@ func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, err
|
|||||||
cursor++
|
cursor++
|
||||||
start := cursor
|
start := cursor
|
||||||
b := (*sliceHeader)(unsafe.Pointer(&buf)).data
|
b := (*sliceHeader)(unsafe.Pointer(&buf)).data
|
||||||
|
escaped := 0
|
||||||
for {
|
for {
|
||||||
switch char(b, cursor) {
|
switch char(b, cursor) {
|
||||||
case '\\':
|
case '\\':
|
||||||
|
escaped++
|
||||||
cursor++
|
cursor++
|
||||||
switch char(b, cursor) {
|
switch char(b, cursor) {
|
||||||
case '"':
|
case '"', '\\', '/', 'b', 'f', 'n', 'r', 't':
|
||||||
buf[cursor] = '"'
|
cursor++
|
||||||
buf = append(buf[:cursor-1], buf[cursor:]...)
|
|
||||||
case '\\':
|
|
||||||
buf[cursor] = '\\'
|
|
||||||
buf = append(buf[:cursor-1], buf[cursor:]...)
|
|
||||||
case '/':
|
|
||||||
buf[cursor] = '/'
|
|
||||||
buf = append(buf[:cursor-1], buf[cursor:]...)
|
|
||||||
case 'b':
|
|
||||||
buf[cursor] = '\b'
|
|
||||||
buf = append(buf[:cursor-1], buf[cursor:]...)
|
|
||||||
case 'f':
|
|
||||||
buf[cursor] = '\f'
|
|
||||||
buf = append(buf[:cursor-1], buf[cursor:]...)
|
|
||||||
case 'n':
|
|
||||||
buf[cursor] = '\n'
|
|
||||||
buf = append(buf[:cursor-1], buf[cursor:]...)
|
|
||||||
case 'r':
|
|
||||||
buf[cursor] = '\r'
|
|
||||||
buf = append(buf[:cursor-1], buf[cursor:]...)
|
|
||||||
case 't':
|
|
||||||
buf[cursor] = '\t'
|
|
||||||
buf = append(buf[:cursor-1], buf[cursor:]...)
|
|
||||||
case 'u':
|
case 'u':
|
||||||
buflen := int64(len(buf))
|
buflen := int64(len(buf))
|
||||||
if cursor+5 >= buflen {
|
if cursor+5 >= buflen {
|
||||||
return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", cursor)
|
return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", cursor)
|
||||||
}
|
}
|
||||||
code := unicodeToRune(buf[cursor+1 : cursor+5])
|
for i := int64(1); i <= 4; i++ {
|
||||||
unicode := []byte(string(code))
|
c := char(b, cursor+i)
|
||||||
buf = append(append(buf[:cursor-1], unicode...), buf[cursor+5:]...)
|
if !(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')) {
|
||||||
|
return nil, 0, errors.ErrSyntax(fmt.Sprintf("json: invalid character %c in \\u hexadecimal character escape", c), cursor+i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cursor += 5
|
||||||
default:
|
default:
|
||||||
return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", cursor)
|
return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", cursor)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
case '"':
|
case '"':
|
||||||
literal := buf[start:cursor]
|
literal := buf[start:cursor]
|
||||||
|
if escaped > 0 {
|
||||||
|
literal = literal[:unescapeString(literal)]
|
||||||
|
}
|
||||||
cursor++
|
cursor++
|
||||||
return literal, cursor, nil
|
return literal, cursor, nil
|
||||||
case nul:
|
case nul:
|
||||||
@ -369,3 +365,77 @@ func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, err
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var unescapeMap = [256]byte{
|
||||||
|
'"': '"',
|
||||||
|
'\\': '\\',
|
||||||
|
'/': '/',
|
||||||
|
'b': '\b',
|
||||||
|
'f': '\f',
|
||||||
|
'n': '\n',
|
||||||
|
'r': '\r',
|
||||||
|
't': '\t',
|
||||||
|
}
|
||||||
|
|
||||||
|
func unsafeAdd(ptr unsafe.Pointer, offset int) unsafe.Pointer {
|
||||||
|
return unsafe.Pointer(uintptr(ptr) + uintptr(offset))
|
||||||
|
}
|
||||||
|
|
||||||
|
func unescapeString(buf []byte) int {
|
||||||
|
p := (*sliceHeader)(unsafe.Pointer(&buf)).data
|
||||||
|
end := unsafeAdd(p, len(buf))
|
||||||
|
src := unsafeAdd(p, bytes.IndexByte(buf, '\\'))
|
||||||
|
dst := src
|
||||||
|
for src != end {
|
||||||
|
c := char(src, 0)
|
||||||
|
if c == '\\' {
|
||||||
|
escapeChar := char(src, 1)
|
||||||
|
if escapeChar != 'u' {
|
||||||
|
*(*byte)(dst) = unescapeMap[escapeChar]
|
||||||
|
src = unsafeAdd(src, 2)
|
||||||
|
dst = unsafeAdd(dst, 1)
|
||||||
|
} else {
|
||||||
|
v1 := hexToInt[char(src, 2)]
|
||||||
|
v2 := hexToInt[char(src, 3)]
|
||||||
|
v3 := hexToInt[char(src, 4)]
|
||||||
|
v4 := hexToInt[char(src, 5)]
|
||||||
|
code := rune((v1 << 12) | (v2 << 8) | (v3 << 4) | v4)
|
||||||
|
if code >= 0xd800 && code < 0xdc00 && uintptr(unsafeAdd(src, 11)) < uintptr(end) {
|
||||||
|
if char(src, 6) == '\\' && char(src, 7) == 'u' {
|
||||||
|
v1 := hexToInt[char(src, 8)]
|
||||||
|
v2 := hexToInt[char(src, 9)]
|
||||||
|
v3 := hexToInt[char(src, 10)]
|
||||||
|
v4 := hexToInt[char(src, 11)]
|
||||||
|
lo := rune((v1 << 12) | (v2 << 8) | (v3 << 4) | v4)
|
||||||
|
if lo >= 0xdc00 && lo < 0xe000 {
|
||||||
|
code = (code-0xd800)<<10 | (lo - 0xdc00) + 0x10000
|
||||||
|
src = unsafeAdd(src, 6)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var b [utf8.UTFMax]byte
|
||||||
|
n := utf8.EncodeRune(b[:], code)
|
||||||
|
switch n {
|
||||||
|
case 4:
|
||||||
|
*(*byte)(unsafeAdd(dst, 3)) = b[3]
|
||||||
|
fallthrough
|
||||||
|
case 3:
|
||||||
|
*(*byte)(unsafeAdd(dst, 2)) = b[2]
|
||||||
|
fallthrough
|
||||||
|
case 2:
|
||||||
|
*(*byte)(unsafeAdd(dst, 1)) = b[1]
|
||||||
|
fallthrough
|
||||||
|
case 1:
|
||||||
|
*(*byte)(unsafeAdd(dst, 0)) = b[0]
|
||||||
|
}
|
||||||
|
src = unsafeAdd(src, 6)
|
||||||
|
dst = unsafeAdd(dst, n)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*(*byte)(dst) = c
|
||||||
|
src = unsafeAdd(src, 1)
|
||||||
|
dst = unsafeAdd(dst, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return int(uintptr(dst) - uintptr(p))
|
||||||
|
}
|
||||||
|
14
vendor/github.com/goccy/go-json/internal/decoder/unmarshal_json.go
generated
vendored
14
vendor/github.com/goccy/go-json/internal/decoder/unmarshal_json.go
generated
vendored
@ -1,6 +1,7 @@
|
|||||||
package decoder
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
@ -46,13 +47,20 @@ func (d *unmarshalJSONDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Poi
|
|||||||
typ: d.typ,
|
typ: d.typ,
|
||||||
ptr: p,
|
ptr: p,
|
||||||
}))
|
}))
|
||||||
|
switch v := v.(type) {
|
||||||
|
case unmarshalerContext:
|
||||||
|
var ctx context.Context
|
||||||
if (s.Option.Flags & ContextOption) != 0 {
|
if (s.Option.Flags & ContextOption) != 0 {
|
||||||
if err := v.(unmarshalerContext).UnmarshalJSON(s.Option.Context, dst); err != nil {
|
ctx = s.Option.Context
|
||||||
|
} else {
|
||||||
|
ctx = context.Background()
|
||||||
|
}
|
||||||
|
if err := v.UnmarshalJSON(ctx, dst); err != nil {
|
||||||
d.annotateError(s.cursor, err)
|
d.annotateError(s.cursor, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
case json.Unmarshaler:
|
||||||
if err := v.(json.Unmarshaler).UnmarshalJSON(dst); err != nil {
|
if err := v.UnmarshalJSON(dst); err != nil {
|
||||||
d.annotateError(s.cursor, err)
|
d.annotateError(s.cursor, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
1017
vendor/github.com/goccy/go-json/internal/encoder/code.go
generated
vendored
Normal file
1017
vendor/github.com/goccy/go-json/internal/encoder/code.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2120
vendor/github.com/goccy/go-json/internal/encoder/compiler.go
generated
vendored
2120
vendor/github.com/goccy/go-json/internal/encoder/compiler.go
generated
vendored
File diff suppressed because it is too large
Load Diff
56
vendor/github.com/goccy/go-json/internal/encoder/compiler_norace.go
generated
vendored
56
vendor/github.com/goccy/go-json/internal/encoder/compiler_norace.go
generated
vendored
@ -1,56 +1,32 @@
|
|||||||
|
//go:build !race
|
||||||
// +build !race
|
// +build !race
|
||||||
|
|
||||||
package encoder
|
package encoder
|
||||||
|
|
||||||
import (
|
func CompileToGetCodeSet(ctx *RuntimeContext, typeptr uintptr) (*OpcodeSet, error) {
|
||||||
"unsafe"
|
if typeptr > typeAddr.MaxTypeAddr || typeptr < typeAddr.BaseTypeAddr {
|
||||||
|
codeSet, err := compileToGetCodeSetSlowPath(typeptr)
|
||||||
"github.com/goccy/go-json/internal/runtime"
|
if err != nil {
|
||||||
)
|
return nil, err
|
||||||
|
}
|
||||||
func CompileToGetCodeSet(typeptr uintptr) (*OpcodeSet, error) {
|
return getFilteredCodeSetIfNeeded(ctx, codeSet)
|
||||||
if typeptr > typeAddr.MaxTypeAddr {
|
|
||||||
return compileToGetCodeSetSlowPath(typeptr)
|
|
||||||
}
|
}
|
||||||
index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift
|
index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift
|
||||||
if codeSet := cachedOpcodeSets[index]; codeSet != nil {
|
if codeSet := cachedOpcodeSets[index]; codeSet != nil {
|
||||||
return codeSet, nil
|
filtered, err := getFilteredCodeSetIfNeeded(ctx, codeSet)
|
||||||
}
|
|
||||||
|
|
||||||
// noescape trick for header.typ ( reflect.*rtype )
|
|
||||||
copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr))
|
|
||||||
|
|
||||||
noescapeKeyCode, err := compileHead(&compileContext{
|
|
||||||
typ: copiedType,
|
|
||||||
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
escapeKeyCode, err := compileHead(&compileContext{
|
return filtered, nil
|
||||||
typ: copiedType,
|
}
|
||||||
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
|
codeSet, err := newCompiler().compile(typeptr)
|
||||||
escapeKey: true,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
noescapeKeyCode = copyOpcode(noescapeKeyCode)
|
filtered, err := getFilteredCodeSetIfNeeded(ctx, codeSet)
|
||||||
escapeKeyCode = copyOpcode(escapeKeyCode)
|
if err != nil {
|
||||||
setTotalLengthToInterfaceOp(noescapeKeyCode)
|
return nil, err
|
||||||
setTotalLengthToInterfaceOp(escapeKeyCode)
|
|
||||||
interfaceNoescapeKeyCode := copyToInterfaceOpcode(noescapeKeyCode)
|
|
||||||
interfaceEscapeKeyCode := copyToInterfaceOpcode(escapeKeyCode)
|
|
||||||
codeLength := noescapeKeyCode.TotalLength()
|
|
||||||
codeSet := &OpcodeSet{
|
|
||||||
Type: copiedType,
|
|
||||||
NoescapeKeyCode: noescapeKeyCode,
|
|
||||||
EscapeKeyCode: escapeKeyCode,
|
|
||||||
InterfaceNoescapeKeyCode: interfaceNoescapeKeyCode,
|
|
||||||
InterfaceEscapeKeyCode: interfaceEscapeKeyCode,
|
|
||||||
CodeLength: codeLength,
|
|
||||||
EndCode: ToEndCode(interfaceNoescapeKeyCode),
|
|
||||||
}
|
}
|
||||||
cachedOpcodeSets[index] = codeSet
|
cachedOpcodeSets[index] = codeSet
|
||||||
return codeSet, nil
|
return filtered, nil
|
||||||
}
|
}
|
||||||
|
54
vendor/github.com/goccy/go-json/internal/encoder/compiler_race.go
generated
vendored
54
vendor/github.com/goccy/go-json/internal/encoder/compiler_race.go
generated
vendored
@ -1,65 +1,45 @@
|
|||||||
|
//go:build race
|
||||||
// +build race
|
// +build race
|
||||||
|
|
||||||
package encoder
|
package encoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/goccy/go-json/internal/runtime"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var setsMu sync.RWMutex
|
var setsMu sync.RWMutex
|
||||||
|
|
||||||
func CompileToGetCodeSet(typeptr uintptr) (*OpcodeSet, error) {
|
func CompileToGetCodeSet(ctx *RuntimeContext, typeptr uintptr) (*OpcodeSet, error) {
|
||||||
if typeptr > typeAddr.MaxTypeAddr {
|
if typeptr > typeAddr.MaxTypeAddr || typeptr < typeAddr.BaseTypeAddr {
|
||||||
return compileToGetCodeSetSlowPath(typeptr)
|
codeSet, err := compileToGetCodeSetSlowPath(typeptr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return getFilteredCodeSetIfNeeded(ctx, codeSet)
|
||||||
}
|
}
|
||||||
index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift
|
index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift
|
||||||
setsMu.RLock()
|
setsMu.RLock()
|
||||||
if codeSet := cachedOpcodeSets[index]; codeSet != nil {
|
if codeSet := cachedOpcodeSets[index]; codeSet != nil {
|
||||||
|
filtered, err := getFilteredCodeSetIfNeeded(ctx, codeSet)
|
||||||
|
if err != nil {
|
||||||
setsMu.RUnlock()
|
setsMu.RUnlock()
|
||||||
return codeSet, nil
|
return nil, err
|
||||||
|
}
|
||||||
|
setsMu.RUnlock()
|
||||||
|
return filtered, nil
|
||||||
}
|
}
|
||||||
setsMu.RUnlock()
|
setsMu.RUnlock()
|
||||||
|
|
||||||
// noescape trick for header.typ ( reflect.*rtype )
|
codeSet, err := newCompiler().compile(typeptr)
|
||||||
copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr))
|
|
||||||
|
|
||||||
noescapeKeyCode, err := compileHead(&compileContext{
|
|
||||||
typ: copiedType,
|
|
||||||
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
escapeKeyCode, err := compileHead(&compileContext{
|
filtered, err := getFilteredCodeSetIfNeeded(ctx, codeSet)
|
||||||
typ: copiedType,
|
|
||||||
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
|
|
||||||
escapeKey: true,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
noescapeKeyCode = copyOpcode(noescapeKeyCode)
|
|
||||||
escapeKeyCode = copyOpcode(escapeKeyCode)
|
|
||||||
setTotalLengthToInterfaceOp(noescapeKeyCode)
|
|
||||||
setTotalLengthToInterfaceOp(escapeKeyCode)
|
|
||||||
interfaceNoescapeKeyCode := copyToInterfaceOpcode(noescapeKeyCode)
|
|
||||||
interfaceEscapeKeyCode := copyToInterfaceOpcode(escapeKeyCode)
|
|
||||||
codeLength := noescapeKeyCode.TotalLength()
|
|
||||||
codeSet := &OpcodeSet{
|
|
||||||
Type: copiedType,
|
|
||||||
NoescapeKeyCode: noescapeKeyCode,
|
|
||||||
EscapeKeyCode: escapeKeyCode,
|
|
||||||
InterfaceNoescapeKeyCode: interfaceNoescapeKeyCode,
|
|
||||||
InterfaceEscapeKeyCode: interfaceEscapeKeyCode,
|
|
||||||
CodeLength: codeLength,
|
|
||||||
EndCode: ToEndCode(interfaceNoescapeKeyCode),
|
|
||||||
}
|
|
||||||
setsMu.Lock()
|
setsMu.Lock()
|
||||||
cachedOpcodeSets[index] = codeSet
|
cachedOpcodeSets[index] = codeSet
|
||||||
setsMu.Unlock()
|
setsMu.Unlock()
|
||||||
return codeSet, nil
|
return filtered, nil
|
||||||
}
|
}
|
||||||
|
48
vendor/github.com/goccy/go-json/internal/encoder/context.go
generated
vendored
48
vendor/github.com/goccy/go-json/internal/encoder/context.go
generated
vendored
@ -9,44 +9,20 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type compileContext struct {
|
type compileContext struct {
|
||||||
typ *runtime.Type
|
|
||||||
opcodeIndex uint32
|
opcodeIndex uint32
|
||||||
ptrIndex int
|
ptrIndex int
|
||||||
indent uint32
|
indent uint32
|
||||||
escapeKey bool
|
escapeKey bool
|
||||||
structTypeToCompiledCode map[uintptr]*CompiledCode
|
structTypeToCodes map[uintptr]Opcodes
|
||||||
|
recursiveCodes *Opcodes
|
||||||
parent *compileContext
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *compileContext) context() *compileContext {
|
func (c *compileContext) incIndent() {
|
||||||
return &compileContext{
|
c.indent++
|
||||||
typ: c.typ,
|
|
||||||
opcodeIndex: c.opcodeIndex,
|
|
||||||
ptrIndex: c.ptrIndex,
|
|
||||||
indent: c.indent,
|
|
||||||
escapeKey: c.escapeKey,
|
|
||||||
structTypeToCompiledCode: c.structTypeToCompiledCode,
|
|
||||||
parent: c,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *compileContext) withType(typ *runtime.Type) *compileContext {
|
func (c *compileContext) decIndent() {
|
||||||
ctx := c.context()
|
c.indent--
|
||||||
ctx.typ = typ
|
|
||||||
return ctx
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *compileContext) incIndent() *compileContext {
|
|
||||||
ctx := c.context()
|
|
||||||
ctx.indent++
|
|
||||||
return ctx
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *compileContext) decIndent() *compileContext {
|
|
||||||
ctx := c.context()
|
|
||||||
ctx.indent--
|
|
||||||
return ctx
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *compileContext) incIndex() {
|
func (c *compileContext) incIndex() {
|
||||||
@ -61,30 +37,18 @@ func (c *compileContext) decIndex() {
|
|||||||
|
|
||||||
func (c *compileContext) incOpcodeIndex() {
|
func (c *compileContext) incOpcodeIndex() {
|
||||||
c.opcodeIndex++
|
c.opcodeIndex++
|
||||||
if c.parent != nil {
|
|
||||||
c.parent.incOpcodeIndex()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *compileContext) decOpcodeIndex() {
|
func (c *compileContext) decOpcodeIndex() {
|
||||||
c.opcodeIndex--
|
c.opcodeIndex--
|
||||||
if c.parent != nil {
|
|
||||||
c.parent.decOpcodeIndex()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *compileContext) incPtrIndex() {
|
func (c *compileContext) incPtrIndex() {
|
||||||
c.ptrIndex++
|
c.ptrIndex++
|
||||||
if c.parent != nil {
|
|
||||||
c.parent.incPtrIndex()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *compileContext) decPtrIndex() {
|
func (c *compileContext) decPtrIndex() {
|
||||||
c.ptrIndex--
|
c.ptrIndex--
|
||||||
if c.parent != nil {
|
|
||||||
c.parent.decPtrIndex()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
126
vendor/github.com/goccy/go-json/internal/encoder/decode_rune.go
generated
vendored
Normal file
126
vendor/github.com/goccy/go-json/internal/encoder/decode_rune.go
generated
vendored
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
package encoder
|
||||||
|
|
||||||
|
import "unicode/utf8"
|
||||||
|
|
||||||
|
const (
|
||||||
|
// The default lowest and highest continuation byte.
|
||||||
|
locb = 128 //0b10000000
|
||||||
|
hicb = 191 //0b10111111
|
||||||
|
|
||||||
|
// These names of these constants are chosen to give nice alignment in the
|
||||||
|
// table below. The first nibble is an index into acceptRanges or F for
|
||||||
|
// special one-byte cases. The second nibble is the Rune length or the
|
||||||
|
// Status for the special one-byte case.
|
||||||
|
xx = 0xF1 // invalid: size 1
|
||||||
|
as = 0xF0 // ASCII: size 1
|
||||||
|
s1 = 0x02 // accept 0, size 2
|
||||||
|
s2 = 0x13 // accept 1, size 3
|
||||||
|
s3 = 0x03 // accept 0, size 3
|
||||||
|
s4 = 0x23 // accept 2, size 3
|
||||||
|
s5 = 0x34 // accept 3, size 4
|
||||||
|
s6 = 0x04 // accept 0, size 4
|
||||||
|
s7 = 0x44 // accept 4, size 4
|
||||||
|
)
|
||||||
|
|
||||||
|
// first is information about the first byte in a UTF-8 sequence.
|
||||||
|
var first = [256]uint8{
|
||||||
|
// 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||||
|
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x00-0x0F
|
||||||
|
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x10-0x1F
|
||||||
|
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x20-0x2F
|
||||||
|
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x30-0x3F
|
||||||
|
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x40-0x4F
|
||||||
|
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x50-0x5F
|
||||||
|
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x60-0x6F
|
||||||
|
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x70-0x7F
|
||||||
|
// 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||||
|
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x80-0x8F
|
||||||
|
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x90-0x9F
|
||||||
|
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xA0-0xAF
|
||||||
|
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xB0-0xBF
|
||||||
|
xx, xx, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xC0-0xCF
|
||||||
|
s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xD0-0xDF
|
||||||
|
s2, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s4, s3, s3, // 0xE0-0xEF
|
||||||
|
s5, s6, s6, s6, s7, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xF0-0xFF
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
lineSep = byte(168) //'\u2028'
|
||||||
|
paragraphSep = byte(169) //'\u2029'
|
||||||
|
)
|
||||||
|
|
||||||
|
type decodeRuneState int
|
||||||
|
|
||||||
|
const (
|
||||||
|
validUTF8State decodeRuneState = iota
|
||||||
|
runeErrorState
|
||||||
|
lineSepState
|
||||||
|
paragraphSepState
|
||||||
|
)
|
||||||
|
|
||||||
|
func decodeRuneInString(s string) (decodeRuneState, int) {
|
||||||
|
n := len(s)
|
||||||
|
s0 := s[0]
|
||||||
|
x := first[s0]
|
||||||
|
if x >= as {
|
||||||
|
// The following code simulates an additional check for x == xx and
|
||||||
|
// handling the ASCII and invalid cases accordingly. This mask-and-or
|
||||||
|
// approach prevents an additional branch.
|
||||||
|
mask := rune(x) << 31 >> 31 // Create 0x0000 or 0xFFFF.
|
||||||
|
if rune(s[0])&^mask|utf8.RuneError&mask == utf8.RuneError {
|
||||||
|
return runeErrorState, 1
|
||||||
|
}
|
||||||
|
return validUTF8State, 1
|
||||||
|
}
|
||||||
|
sz := int(x & 7)
|
||||||
|
if n < sz {
|
||||||
|
return runeErrorState, 1
|
||||||
|
}
|
||||||
|
s1 := s[1]
|
||||||
|
switch x >> 4 {
|
||||||
|
case 0:
|
||||||
|
if s1 < locb || hicb < s1 {
|
||||||
|
return runeErrorState, 1
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
if s1 < 0xA0 || hicb < s1 {
|
||||||
|
return runeErrorState, 1
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if s1 < locb || 0x9F < s1 {
|
||||||
|
return runeErrorState, 1
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
if s1 < 0x90 || hicb < s1 {
|
||||||
|
return runeErrorState, 1
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
if s1 < locb || 0x8F < s1 {
|
||||||
|
return runeErrorState, 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if sz <= 2 {
|
||||||
|
return validUTF8State, 2
|
||||||
|
}
|
||||||
|
s2 := s[2]
|
||||||
|
if s2 < locb || hicb < s2 {
|
||||||
|
return runeErrorState, 1
|
||||||
|
}
|
||||||
|
if sz <= 3 {
|
||||||
|
// separator character prefixes: [2]byte{226, 128}
|
||||||
|
if s0 == 226 && s1 == 128 {
|
||||||
|
switch s2 {
|
||||||
|
case lineSep:
|
||||||
|
return lineSepState, 3
|
||||||
|
case paragraphSep:
|
||||||
|
return paragraphSepState, 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return validUTF8State, 3
|
||||||
|
}
|
||||||
|
s3 := s[3]
|
||||||
|
if s3 < locb || hicb < s3 {
|
||||||
|
return runeErrorState, 1
|
||||||
|
}
|
||||||
|
return validUTF8State, 4
|
||||||
|
}
|
81
vendor/github.com/goccy/go-json/internal/encoder/encoder.go
generated
vendored
81
vendor/github.com/goccy/go-json/internal/encoder/encoder.go
generated
vendored
@ -101,6 +101,22 @@ type OpcodeSet struct {
|
|||||||
InterfaceEscapeKeyCode *Opcode
|
InterfaceEscapeKeyCode *Opcode
|
||||||
CodeLength int
|
CodeLength int
|
||||||
EndCode *Opcode
|
EndCode *Opcode
|
||||||
|
Code Code
|
||||||
|
QueryCache map[string]*OpcodeSet
|
||||||
|
cacheMu sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *OpcodeSet) getQueryCache(hash string) *OpcodeSet {
|
||||||
|
s.cacheMu.RLock()
|
||||||
|
codeSet := s.QueryCache[hash]
|
||||||
|
s.cacheMu.RUnlock()
|
||||||
|
return codeSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *OpcodeSet) setQueryCache(hash string, codeSet *OpcodeSet) {
|
||||||
|
s.cacheMu.Lock()
|
||||||
|
s.QueryCache[hash] = codeSet
|
||||||
|
s.cacheMu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
type CompiledCode struct {
|
type CompiledCode struct {
|
||||||
@ -222,33 +238,56 @@ func (m *Mapslice) Swap(i, j int) {
|
|||||||
m.Items[i], m.Items[j] = m.Items[j], m.Items[i]
|
m.Items[i], m.Items[j] = m.Items[j], m.Items[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint:structcheck,unused
|
||||||
|
type mapIter struct {
|
||||||
|
key unsafe.Pointer
|
||||||
|
elem unsafe.Pointer
|
||||||
|
t unsafe.Pointer
|
||||||
|
h unsafe.Pointer
|
||||||
|
buckets unsafe.Pointer
|
||||||
|
bptr unsafe.Pointer
|
||||||
|
overflow unsafe.Pointer
|
||||||
|
oldoverflow unsafe.Pointer
|
||||||
|
startBucket uintptr
|
||||||
|
offset uint8
|
||||||
|
wrapped bool
|
||||||
|
B uint8
|
||||||
|
i uint8
|
||||||
|
bucket uintptr
|
||||||
|
checkBucket uintptr
|
||||||
|
}
|
||||||
|
|
||||||
type MapContext struct {
|
type MapContext struct {
|
||||||
Pos []int
|
Start int
|
||||||
|
First int
|
||||||
|
Idx int
|
||||||
Slice *Mapslice
|
Slice *Mapslice
|
||||||
Buf []byte
|
Buf []byte
|
||||||
|
Len int
|
||||||
|
Iter mapIter
|
||||||
}
|
}
|
||||||
|
|
||||||
var mapContextPool = sync.Pool{
|
var mapContextPool = sync.Pool{
|
||||||
New: func() interface{} {
|
New: func() interface{} {
|
||||||
return &MapContext{}
|
return &MapContext{
|
||||||
|
Slice: &Mapslice{},
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMapContext(mapLen int) *MapContext {
|
func NewMapContext(mapLen int, unorderedMap bool) *MapContext {
|
||||||
ctx := mapContextPool.Get().(*MapContext)
|
ctx := mapContextPool.Get().(*MapContext)
|
||||||
if ctx.Slice == nil {
|
if !unorderedMap {
|
||||||
ctx.Slice = &Mapslice{
|
if len(ctx.Slice.Items) < mapLen {
|
||||||
Items: make([]MapItem, 0, mapLen),
|
ctx.Slice.Items = make([]MapItem, mapLen)
|
||||||
}
|
|
||||||
}
|
|
||||||
if cap(ctx.Pos) < (mapLen*2 + 1) {
|
|
||||||
ctx.Pos = make([]int, 0, mapLen*2+1)
|
|
||||||
ctx.Slice.Items = make([]MapItem, 0, mapLen)
|
|
||||||
} else {
|
} else {
|
||||||
ctx.Pos = ctx.Pos[:0]
|
ctx.Slice.Items = ctx.Slice.Items[:mapLen]
|
||||||
ctx.Slice.Items = ctx.Slice.Items[:0]
|
}
|
||||||
}
|
}
|
||||||
ctx.Buf = ctx.Buf[:0]
|
ctx.Buf = ctx.Buf[:0]
|
||||||
|
ctx.Iter = mapIter{}
|
||||||
|
ctx.Idx = 0
|
||||||
|
ctx.Len = mapLen
|
||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,17 +295,17 @@ func ReleaseMapContext(c *MapContext) {
|
|||||||
mapContextPool.Put(c)
|
mapContextPool.Put(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname MapIterInit reflect.mapiterinit
|
//go:linkname MapIterInit runtime.mapiterinit
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func MapIterInit(mapType *runtime.Type, m unsafe.Pointer) unsafe.Pointer
|
func MapIterInit(mapType *runtime.Type, m unsafe.Pointer, it *mapIter)
|
||||||
|
|
||||||
//go:linkname MapIterKey reflect.mapiterkey
|
//go:linkname MapIterKey reflect.mapiterkey
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func MapIterKey(it unsafe.Pointer) unsafe.Pointer
|
func MapIterKey(it *mapIter) unsafe.Pointer
|
||||||
|
|
||||||
//go:linkname MapIterNext reflect.mapiternext
|
//go:linkname MapIterNext reflect.mapiternext
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func MapIterNext(it unsafe.Pointer)
|
func MapIterNext(it *mapIter)
|
||||||
|
|
||||||
//go:linkname MapLen reflect.maplen
|
//go:linkname MapLen reflect.maplen
|
||||||
//go:noescape
|
//go:noescape
|
||||||
@ -374,7 +413,11 @@ func AppendMarshalJSON(ctx *RuntimeContext, code *Opcode, b []byte, v interface{
|
|||||||
if !ok {
|
if !ok {
|
||||||
return AppendNull(ctx, b), nil
|
return AppendNull(ctx, b), nil
|
||||||
}
|
}
|
||||||
b, err := marshaler.MarshalJSON(ctx.Option.Context)
|
stdctx := ctx.Option.Context
|
||||||
|
if ctx.Option.Flag&FieldQueryOption != 0 {
|
||||||
|
stdctx = SetFieldQueryToContext(stdctx, code.FieldQuery)
|
||||||
|
}
|
||||||
|
b, err := marshaler.MarshalJSON(stdctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
|
return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
|
||||||
}
|
}
|
||||||
@ -546,6 +589,8 @@ func IsNilForMarshaler(v interface{}) bool {
|
|||||||
return rv.IsNil()
|
return rv.IsNil()
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
return rv.IsNil() || rv.Len() == 0
|
return rv.IsNil() || rv.Len() == 0
|
||||||
|
case reflect.String:
|
||||||
|
return rv.Len() == 0
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
26
vendor/github.com/goccy/go-json/internal/encoder/int.go
generated
vendored
26
vendor/github.com/goccy/go-json/internal/encoder/int.go
generated
vendored
@ -53,7 +53,18 @@ func numMask(numBitSize uint8) uint64 {
|
|||||||
return 1<<numBitSize - 1
|
return 1<<numBitSize - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func AppendInt(_ *RuntimeContext, out []byte, u64 uint64, code *Opcode) []byte {
|
func AppendInt(_ *RuntimeContext, out []byte, p uintptr, code *Opcode) []byte {
|
||||||
|
var u64 uint64
|
||||||
|
switch code.NumBitSize {
|
||||||
|
case 8:
|
||||||
|
u64 = (uint64)(**(**uint8)(unsafe.Pointer(&p)))
|
||||||
|
case 16:
|
||||||
|
u64 = (uint64)(**(**uint16)(unsafe.Pointer(&p)))
|
||||||
|
case 32:
|
||||||
|
u64 = (uint64)(**(**uint32)(unsafe.Pointer(&p)))
|
||||||
|
case 64:
|
||||||
|
u64 = **(**uint64)(unsafe.Pointer(&p))
|
||||||
|
}
|
||||||
mask := numMask(code.NumBitSize)
|
mask := numMask(code.NumBitSize)
|
||||||
n := u64 & mask
|
n := u64 & mask
|
||||||
negative := (u64>>(code.NumBitSize-1))&1 == 1
|
negative := (u64>>(code.NumBitSize-1))&1 == 1
|
||||||
@ -96,7 +107,18 @@ func AppendInt(_ *RuntimeContext, out []byte, u64 uint64, code *Opcode) []byte {
|
|||||||
return append(out, b[i:]...)
|
return append(out, b[i:]...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func AppendUint(_ *RuntimeContext, out []byte, u64 uint64, code *Opcode) []byte {
|
func AppendUint(_ *RuntimeContext, out []byte, p uintptr, code *Opcode) []byte {
|
||||||
|
var u64 uint64
|
||||||
|
switch code.NumBitSize {
|
||||||
|
case 8:
|
||||||
|
u64 = (uint64)(**(**uint8)(unsafe.Pointer(&p)))
|
||||||
|
case 16:
|
||||||
|
u64 = (uint64)(**(**uint16)(unsafe.Pointer(&p)))
|
||||||
|
case 32:
|
||||||
|
u64 = (uint64)(**(**uint32)(unsafe.Pointer(&p)))
|
||||||
|
case 64:
|
||||||
|
u64 = **(**uint64)(unsafe.Pointer(&p))
|
||||||
|
}
|
||||||
mask := numMask(code.NumBitSize)
|
mask := numMask(code.NumBitSize)
|
||||||
n := u64 & mask
|
n := u64 & mask
|
||||||
if n < 10 {
|
if n < 10 {
|
||||||
|
3
vendor/github.com/goccy/go-json/internal/encoder/map112.go
generated
vendored
3
vendor/github.com/goccy/go-json/internal/encoder/map112.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build !go1.13
|
||||||
// +build !go1.13
|
// +build !go1.13
|
||||||
|
|
||||||
package encoder
|
package encoder
|
||||||
@ -5,4 +6,4 @@ package encoder
|
|||||||
import "unsafe"
|
import "unsafe"
|
||||||
|
|
||||||
//go:linkname MapIterValue reflect.mapitervalue
|
//go:linkname MapIterValue reflect.mapitervalue
|
||||||
func MapIterValue(it unsafe.Pointer) unsafe.Pointer
|
func MapIterValue(it *mapIter) unsafe.Pointer
|
||||||
|
3
vendor/github.com/goccy/go-json/internal/encoder/map113.go
generated
vendored
3
vendor/github.com/goccy/go-json/internal/encoder/map113.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build go1.13
|
||||||
// +build go1.13
|
// +build go1.13
|
||||||
|
|
||||||
package encoder
|
package encoder
|
||||||
@ -5,4 +6,4 @@ package encoder
|
|||||||
import "unsafe"
|
import "unsafe"
|
||||||
|
|
||||||
//go:linkname MapIterValue reflect.mapiterelem
|
//go:linkname MapIterValue reflect.mapiterelem
|
||||||
func MapIterValue(it unsafe.Pointer) unsafe.Pointer
|
func MapIterValue(it *mapIter) unsafe.Pointer
|
||||||
|
361
vendor/github.com/goccy/go-json/internal/encoder/opcode.go
generated
vendored
361
vendor/github.com/goccy/go-json/internal/encoder/opcode.go
generated
vendored
@ -38,26 +38,58 @@ type Opcode struct {
|
|||||||
Flags OpFlags
|
Flags OpFlags
|
||||||
|
|
||||||
Type *runtime.Type // go type
|
Type *runtime.Type // go type
|
||||||
PrevField *Opcode // prev struct field
|
|
||||||
Jmp *CompiledCode // for recursive call
|
Jmp *CompiledCode // for recursive call
|
||||||
ElemIdx uint32 // offset to access array/slice/map elem
|
FieldQuery *FieldQuery // field query for Interface / MarshalJSON / MarshalText
|
||||||
Length uint32 // offset to access slice/map length or array length
|
ElemIdx uint32 // offset to access array/slice elem
|
||||||
MapIter uint32 // offset to access map iterator
|
Length uint32 // offset to access slice length or array length
|
||||||
MapPos uint32 // offset to access position list for sorted map
|
|
||||||
Indent uint32 // indent number
|
Indent uint32 // indent number
|
||||||
Size uint32 // array/slice elem size
|
Size uint32 // array/slice elem size
|
||||||
DisplayIdx uint32 // opcode index
|
DisplayIdx uint32 // opcode index
|
||||||
DisplayKey string // key text to display
|
DisplayKey string // key text to display
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Opcode) Validate() error {
|
||||||
|
var prevIdx uint32
|
||||||
|
for code := c; !code.IsEnd(); {
|
||||||
|
if prevIdx != 0 {
|
||||||
|
if code.DisplayIdx != prevIdx+1 {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"invalid index. previous display index is %d but next is %d. dump = %s",
|
||||||
|
prevIdx, code.DisplayIdx, c.Dump(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prevIdx = code.DisplayIdx
|
||||||
|
code = code.IterNext()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Opcode) IterNext() *Opcode {
|
||||||
|
if c == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
switch c.Op.CodeType() {
|
||||||
|
case CodeArrayElem, CodeSliceElem, CodeMapKey:
|
||||||
|
return c.End
|
||||||
|
default:
|
||||||
|
return c.Next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Opcode) IsEnd() bool {
|
||||||
|
if c == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return c.Op == OpEnd || c.Op == OpInterfaceEnd || c.Op == OpRecursiveEnd
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Opcode) MaxIdx() uint32 {
|
func (c *Opcode) MaxIdx() uint32 {
|
||||||
max := uint32(0)
|
max := uint32(0)
|
||||||
for _, value := range []uint32{
|
for _, value := range []uint32{
|
||||||
c.Idx,
|
c.Idx,
|
||||||
c.ElemIdx,
|
c.ElemIdx,
|
||||||
c.Length,
|
c.Length,
|
||||||
c.MapIter,
|
|
||||||
c.MapPos,
|
|
||||||
c.Size,
|
c.Size,
|
||||||
} {
|
} {
|
||||||
if max < value {
|
if max < value {
|
||||||
@ -273,43 +305,75 @@ func (c *Opcode) ToFieldType(isString bool) OpType {
|
|||||||
return OpStructField
|
return OpStructField
|
||||||
}
|
}
|
||||||
|
|
||||||
func newOpCode(ctx *compileContext, op OpType) *Opcode {
|
func newOpCode(ctx *compileContext, typ *runtime.Type, op OpType) *Opcode {
|
||||||
return newOpCodeWithNext(ctx, op, newEndOp(ctx))
|
return newOpCodeWithNext(ctx, typ, op, newEndOp(ctx, typ))
|
||||||
}
|
}
|
||||||
|
|
||||||
func opcodeOffset(idx int) uint32 {
|
func opcodeOffset(idx int) uint32 {
|
||||||
return uint32(idx) * uintptrSize
|
return uint32(idx) * uintptrSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getCodeAddrByIdx(head *Opcode, idx uint32) *Opcode {
|
||||||
|
addr := uintptr(unsafe.Pointer(head)) + uintptr(idx)*unsafe.Sizeof(Opcode{})
|
||||||
|
return *(**Opcode)(unsafe.Pointer(&addr))
|
||||||
|
}
|
||||||
|
|
||||||
func copyOpcode(code *Opcode) *Opcode {
|
func copyOpcode(code *Opcode) *Opcode {
|
||||||
codeMap := map[uintptr]*Opcode{}
|
codeNum := ToEndCode(code).DisplayIdx + 1
|
||||||
return code.copy(codeMap)
|
codeSlice := make([]Opcode, codeNum)
|
||||||
|
head := (*Opcode)((*runtime.SliceHeader)(unsafe.Pointer(&codeSlice)).Data)
|
||||||
|
ptr := head
|
||||||
|
c := code
|
||||||
|
for {
|
||||||
|
*ptr = Opcode{
|
||||||
|
Op: c.Op,
|
||||||
|
Key: c.Key,
|
||||||
|
PtrNum: c.PtrNum,
|
||||||
|
NumBitSize: c.NumBitSize,
|
||||||
|
Flags: c.Flags,
|
||||||
|
Idx: c.Idx,
|
||||||
|
Offset: c.Offset,
|
||||||
|
Type: c.Type,
|
||||||
|
FieldQuery: c.FieldQuery,
|
||||||
|
DisplayIdx: c.DisplayIdx,
|
||||||
|
DisplayKey: c.DisplayKey,
|
||||||
|
ElemIdx: c.ElemIdx,
|
||||||
|
Length: c.Length,
|
||||||
|
Size: c.Size,
|
||||||
|
Indent: c.Indent,
|
||||||
|
Jmp: c.Jmp,
|
||||||
|
}
|
||||||
|
if c.End != nil {
|
||||||
|
ptr.End = getCodeAddrByIdx(head, c.End.DisplayIdx)
|
||||||
|
}
|
||||||
|
if c.NextField != nil {
|
||||||
|
ptr.NextField = getCodeAddrByIdx(head, c.NextField.DisplayIdx)
|
||||||
|
}
|
||||||
|
if c.Next != nil {
|
||||||
|
ptr.Next = getCodeAddrByIdx(head, c.Next.DisplayIdx)
|
||||||
|
}
|
||||||
|
if c.IsEnd() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
ptr = getCodeAddrByIdx(head, c.DisplayIdx+1)
|
||||||
|
c = c.IterNext()
|
||||||
|
}
|
||||||
|
return head
|
||||||
}
|
}
|
||||||
|
|
||||||
func setTotalLengthToInterfaceOp(code *Opcode) {
|
func setTotalLengthToInterfaceOp(code *Opcode) {
|
||||||
c := code
|
for c := code; !c.IsEnd(); {
|
||||||
for c.Op != OpEnd && c.Op != OpInterfaceEnd {
|
if c.Op == OpInterface || c.Op == OpInterfacePtr {
|
||||||
if c.Op == OpInterface {
|
|
||||||
c.Length = uint32(code.TotalLength())
|
c.Length = uint32(code.TotalLength())
|
||||||
}
|
}
|
||||||
switch c.Op.CodeType() {
|
c = c.IterNext()
|
||||||
case CodeArrayElem, CodeSliceElem, CodeMapKey:
|
|
||||||
c = c.End
|
|
||||||
default:
|
|
||||||
c = c.Next
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ToEndCode(code *Opcode) *Opcode {
|
func ToEndCode(code *Opcode) *Opcode {
|
||||||
c := code
|
c := code
|
||||||
for c.Op != OpEnd && c.Op != OpInterfaceEnd {
|
for !c.IsEnd() {
|
||||||
switch c.Op.CodeType() {
|
c = c.IterNext()
|
||||||
case CodeArrayElem, CodeSliceElem, CodeMapKey:
|
|
||||||
c = c.End
|
|
||||||
default:
|
|
||||||
c = c.Next
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
@ -325,77 +389,25 @@ func copyToInterfaceOpcode(code *Opcode) *Opcode {
|
|||||||
return copied
|
return copied
|
||||||
}
|
}
|
||||||
|
|
||||||
func newOpCodeWithNext(ctx *compileContext, op OpType, next *Opcode) *Opcode {
|
func newOpCodeWithNext(ctx *compileContext, typ *runtime.Type, op OpType, next *Opcode) *Opcode {
|
||||||
return &Opcode{
|
return &Opcode{
|
||||||
Op: op,
|
Op: op,
|
||||||
Idx: opcodeOffset(ctx.ptrIndex),
|
Idx: opcodeOffset(ctx.ptrIndex),
|
||||||
Next: next,
|
Next: next,
|
||||||
Type: ctx.typ,
|
Type: typ,
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
Indent: ctx.indent,
|
Indent: ctx.indent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newEndOp(ctx *compileContext) *Opcode {
|
func newEndOp(ctx *compileContext, typ *runtime.Type) *Opcode {
|
||||||
return newOpCodeWithNext(ctx, OpEnd, nil)
|
return newOpCodeWithNext(ctx, typ, OpEnd, nil)
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Opcode) copy(codeMap map[uintptr]*Opcode) *Opcode {
|
|
||||||
if c == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
addr := uintptr(unsafe.Pointer(c))
|
|
||||||
if code, exists := codeMap[addr]; exists {
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
copied := &Opcode{
|
|
||||||
Op: c.Op,
|
|
||||||
Key: c.Key,
|
|
||||||
PtrNum: c.PtrNum,
|
|
||||||
NumBitSize: c.NumBitSize,
|
|
||||||
Flags: c.Flags,
|
|
||||||
Idx: c.Idx,
|
|
||||||
Offset: c.Offset,
|
|
||||||
Type: c.Type,
|
|
||||||
DisplayIdx: c.DisplayIdx,
|
|
||||||
DisplayKey: c.DisplayKey,
|
|
||||||
ElemIdx: c.ElemIdx,
|
|
||||||
Length: c.Length,
|
|
||||||
MapIter: c.MapIter,
|
|
||||||
MapPos: c.MapPos,
|
|
||||||
Size: c.Size,
|
|
||||||
Indent: c.Indent,
|
|
||||||
}
|
|
||||||
codeMap[addr] = copied
|
|
||||||
copied.End = c.End.copy(codeMap)
|
|
||||||
copied.PrevField = c.PrevField.copy(codeMap)
|
|
||||||
copied.NextField = c.NextField.copy(codeMap)
|
|
||||||
copied.Next = c.Next.copy(codeMap)
|
|
||||||
copied.Jmp = c.Jmp
|
|
||||||
return copied
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Opcode) BeforeLastCode() *Opcode {
|
|
||||||
code := c
|
|
||||||
for {
|
|
||||||
var nextCode *Opcode
|
|
||||||
switch code.Op.CodeType() {
|
|
||||||
case CodeArrayElem, CodeSliceElem, CodeMapKey:
|
|
||||||
nextCode = code.End
|
|
||||||
default:
|
|
||||||
nextCode = code.Next
|
|
||||||
}
|
|
||||||
if nextCode.Op == OpEnd {
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
code = nextCode
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Opcode) TotalLength() int {
|
func (c *Opcode) TotalLength() int {
|
||||||
var idx int
|
var idx int
|
||||||
code := c
|
code := c
|
||||||
for code.Op != OpEnd && code.Op != OpInterfaceEnd {
|
for !code.IsEnd() {
|
||||||
maxIdx := int(code.MaxIdx() / uintptrSize)
|
maxIdx := int(code.MaxIdx() / uintptrSize)
|
||||||
if idx < maxIdx {
|
if idx < maxIdx {
|
||||||
idx = maxIdx
|
idx = maxIdx
|
||||||
@ -403,12 +415,7 @@ func (c *Opcode) TotalLength() int {
|
|||||||
if code.Op == OpRecursiveEnd {
|
if code.Op == OpRecursiveEnd {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
switch code.Op.CodeType() {
|
code = code.IterNext()
|
||||||
case CodeArrayElem, CodeSliceElem, CodeMapKey:
|
|
||||||
code = code.End
|
|
||||||
default:
|
|
||||||
code = code.Next
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
maxIdx := int(code.MaxIdx() / uintptrSize)
|
maxIdx := int(code.MaxIdx() / uintptrSize)
|
||||||
if idx < maxIdx {
|
if idx < maxIdx {
|
||||||
@ -417,42 +424,6 @@ func (c *Opcode) TotalLength() int {
|
|||||||
return idx + 1
|
return idx + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Opcode) decOpcodeIndex() {
|
|
||||||
for code := c; code.Op != OpEnd; {
|
|
||||||
code.DisplayIdx--
|
|
||||||
if code.Idx > 0 {
|
|
||||||
code.Idx -= uintptrSize
|
|
||||||
}
|
|
||||||
if code.ElemIdx > 0 {
|
|
||||||
code.ElemIdx -= uintptrSize
|
|
||||||
}
|
|
||||||
if code.MapIter > 0 {
|
|
||||||
code.MapIter -= uintptrSize
|
|
||||||
}
|
|
||||||
if code.Length > 0 && code.Op.CodeType() != CodeArrayHead && code.Op.CodeType() != CodeArrayElem {
|
|
||||||
code.Length -= uintptrSize
|
|
||||||
}
|
|
||||||
switch code.Op.CodeType() {
|
|
||||||
case CodeArrayElem, CodeSliceElem, CodeMapKey:
|
|
||||||
code = code.End
|
|
||||||
default:
|
|
||||||
code = code.Next
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Opcode) decIndent() {
|
|
||||||
for code := c; code.Op != OpEnd; {
|
|
||||||
code.Indent--
|
|
||||||
switch code.Op.CodeType() {
|
|
||||||
case CodeArrayElem, CodeSliceElem, CodeMapKey:
|
|
||||||
code = code.End
|
|
||||||
default:
|
|
||||||
code = code.Next
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Opcode) dumpHead(code *Opcode) string {
|
func (c *Opcode) dumpHead(code *Opcode) string {
|
||||||
var length uint32
|
var length uint32
|
||||||
if code.Op.CodeType() == CodeArrayHead {
|
if code.Op.CodeType() == CodeArrayHead {
|
||||||
@ -461,7 +432,7 @@ func (c *Opcode) dumpHead(code *Opcode) string {
|
|||||||
length = code.Length / uintptrSize
|
length = code.Length / uintptrSize
|
||||||
}
|
}
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
`[%d]%s%s ([idx:%d][elemIdx:%d][length:%d])`,
|
`[%03d]%s%s ([idx:%d][elemIdx:%d][length:%d])`,
|
||||||
code.DisplayIdx,
|
code.DisplayIdx,
|
||||||
strings.Repeat("-", int(code.Indent)),
|
strings.Repeat("-", int(code.Indent)),
|
||||||
code.Op,
|
code.Op,
|
||||||
@ -473,26 +444,21 @@ func (c *Opcode) dumpHead(code *Opcode) string {
|
|||||||
|
|
||||||
func (c *Opcode) dumpMapHead(code *Opcode) string {
|
func (c *Opcode) dumpMapHead(code *Opcode) string {
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
`[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][mapIter:%d])`,
|
`[%03d]%s%s ([idx:%d])`,
|
||||||
code.DisplayIdx,
|
code.DisplayIdx,
|
||||||
strings.Repeat("-", int(code.Indent)),
|
strings.Repeat("-", int(code.Indent)),
|
||||||
code.Op,
|
code.Op,
|
||||||
code.Idx/uintptrSize,
|
code.Idx/uintptrSize,
|
||||||
code.ElemIdx/uintptrSize,
|
|
||||||
code.Length/uintptrSize,
|
|
||||||
code.MapIter/uintptrSize,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Opcode) dumpMapEnd(code *Opcode) string {
|
func (c *Opcode) dumpMapEnd(code *Opcode) string {
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
`[%d]%s%s ([idx:%d][mapPos:%d][length:%d])`,
|
`[%03d]%s%s ([idx:%d])`,
|
||||||
code.DisplayIdx,
|
code.DisplayIdx,
|
||||||
strings.Repeat("-", int(code.Indent)),
|
strings.Repeat("-", int(code.Indent)),
|
||||||
code.Op,
|
code.Op,
|
||||||
code.Idx/uintptrSize,
|
code.Idx/uintptrSize,
|
||||||
code.MapPos/uintptrSize,
|
|
||||||
code.Length/uintptrSize,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,7 +470,7 @@ func (c *Opcode) dumpElem(code *Opcode) string {
|
|||||||
length = code.Length / uintptrSize
|
length = code.Length / uintptrSize
|
||||||
}
|
}
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
`[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][size:%d])`,
|
`[%03d]%s%s ([idx:%d][elemIdx:%d][length:%d][size:%d])`,
|
||||||
code.DisplayIdx,
|
code.DisplayIdx,
|
||||||
strings.Repeat("-", int(code.Indent)),
|
strings.Repeat("-", int(code.Indent)),
|
||||||
code.Op,
|
code.Op,
|
||||||
@ -517,7 +483,7 @@ func (c *Opcode) dumpElem(code *Opcode) string {
|
|||||||
|
|
||||||
func (c *Opcode) dumpField(code *Opcode) string {
|
func (c *Opcode) dumpField(code *Opcode) string {
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
`[%d]%s%s ([idx:%d][key:%s][offset:%d])`,
|
`[%03d]%s%s ([idx:%d][key:%s][offset:%d])`,
|
||||||
code.DisplayIdx,
|
code.DisplayIdx,
|
||||||
strings.Repeat("-", int(code.Indent)),
|
strings.Repeat("-", int(code.Indent)),
|
||||||
code.Op,
|
code.Op,
|
||||||
@ -529,31 +495,27 @@ func (c *Opcode) dumpField(code *Opcode) string {
|
|||||||
|
|
||||||
func (c *Opcode) dumpKey(code *Opcode) string {
|
func (c *Opcode) dumpKey(code *Opcode) string {
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
`[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][mapIter:%d])`,
|
`[%03d]%s%s ([idx:%d])`,
|
||||||
code.DisplayIdx,
|
code.DisplayIdx,
|
||||||
strings.Repeat("-", int(code.Indent)),
|
strings.Repeat("-", int(code.Indent)),
|
||||||
code.Op,
|
code.Op,
|
||||||
code.Idx/uintptrSize,
|
code.Idx/uintptrSize,
|
||||||
code.ElemIdx/uintptrSize,
|
|
||||||
code.Length/uintptrSize,
|
|
||||||
code.MapIter/uintptrSize,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Opcode) dumpValue(code *Opcode) string {
|
func (c *Opcode) dumpValue(code *Opcode) string {
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
`[%d]%s%s ([idx:%d][mapIter:%d])`,
|
`[%03d]%s%s ([idx:%d])`,
|
||||||
code.DisplayIdx,
|
code.DisplayIdx,
|
||||||
strings.Repeat("-", int(code.Indent)),
|
strings.Repeat("-", int(code.Indent)),
|
||||||
code.Op,
|
code.Op,
|
||||||
code.Idx/uintptrSize,
|
code.Idx/uintptrSize,
|
||||||
code.MapIter/uintptrSize,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Opcode) Dump() string {
|
func (c *Opcode) Dump() string {
|
||||||
codes := []string{}
|
codes := []string{}
|
||||||
for code := c; code.Op != OpEnd && code.Op != OpInterfaceEnd; {
|
for code := c; !code.IsEnd(); {
|
||||||
switch code.Op.CodeType() {
|
switch code.Op.CodeType() {
|
||||||
case CodeSliceHead:
|
case CodeSliceHead:
|
||||||
codes = append(codes, c.dumpHead(code))
|
codes = append(codes, c.dumpHead(code))
|
||||||
@ -581,7 +543,7 @@ func (c *Opcode) Dump() string {
|
|||||||
code = code.Next
|
code = code.Next
|
||||||
default:
|
default:
|
||||||
codes = append(codes, fmt.Sprintf(
|
codes = append(codes, fmt.Sprintf(
|
||||||
"[%d]%s%s ([idx:%d])",
|
"[%03d]%s%s ([idx:%d])",
|
||||||
code.DisplayIdx,
|
code.DisplayIdx,
|
||||||
strings.Repeat("-", int(code.Indent)),
|
strings.Repeat("-", int(code.Indent)),
|
||||||
code.Op,
|
code.Op,
|
||||||
@ -593,44 +555,7 @@ func (c *Opcode) Dump() string {
|
|||||||
return strings.Join(codes, "\n")
|
return strings.Join(codes, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func prevField(code *Opcode, removedFields map[*Opcode]struct{}) *Opcode {
|
func newSliceHeaderCode(ctx *compileContext, typ *runtime.Type) *Opcode {
|
||||||
if _, exists := removedFields[code]; exists {
|
|
||||||
return prevField(code.PrevField, removedFields)
|
|
||||||
}
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
|
|
||||||
func nextField(code *Opcode, removedFields map[*Opcode]struct{}) *Opcode {
|
|
||||||
if _, exists := removedFields[code]; exists {
|
|
||||||
return nextField(code.NextField, removedFields)
|
|
||||||
}
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
|
|
||||||
func linkPrevToNextField(cur *Opcode, removedFields map[*Opcode]struct{}) {
|
|
||||||
prev := prevField(cur.PrevField, removedFields)
|
|
||||||
prev.NextField = nextField(cur.NextField, removedFields)
|
|
||||||
code := prev
|
|
||||||
fcode := cur
|
|
||||||
for {
|
|
||||||
var nextCode *Opcode
|
|
||||||
switch code.Op.CodeType() {
|
|
||||||
case CodeArrayElem, CodeSliceElem, CodeMapKey:
|
|
||||||
nextCode = code.End
|
|
||||||
default:
|
|
||||||
nextCode = code.Next
|
|
||||||
}
|
|
||||||
if nextCode == fcode {
|
|
||||||
code.Next = fcode.Next
|
|
||||||
break
|
|
||||||
} else if nextCode.Op == OpEnd {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
code = nextCode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newSliceHeaderCode(ctx *compileContext) *Opcode {
|
|
||||||
idx := opcodeOffset(ctx.ptrIndex)
|
idx := opcodeOffset(ctx.ptrIndex)
|
||||||
ctx.incPtrIndex()
|
ctx.incPtrIndex()
|
||||||
elemIdx := opcodeOffset(ctx.ptrIndex)
|
elemIdx := opcodeOffset(ctx.ptrIndex)
|
||||||
@ -638,6 +563,7 @@ func newSliceHeaderCode(ctx *compileContext) *Opcode {
|
|||||||
length := opcodeOffset(ctx.ptrIndex)
|
length := opcodeOffset(ctx.ptrIndex)
|
||||||
return &Opcode{
|
return &Opcode{
|
||||||
Op: OpSlice,
|
Op: OpSlice,
|
||||||
|
Type: typ,
|
||||||
Idx: idx,
|
Idx: idx,
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
ElemIdx: elemIdx,
|
ElemIdx: elemIdx,
|
||||||
@ -646,9 +572,10 @@ func newSliceHeaderCode(ctx *compileContext) *Opcode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSliceElemCode(ctx *compileContext, head *Opcode, size uintptr) *Opcode {
|
func newSliceElemCode(ctx *compileContext, typ *runtime.Type, head *Opcode, size uintptr) *Opcode {
|
||||||
return &Opcode{
|
return &Opcode{
|
||||||
Op: OpSliceElem,
|
Op: OpSliceElem,
|
||||||
|
Type: typ,
|
||||||
Idx: head.Idx,
|
Idx: head.Idx,
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
ElemIdx: head.ElemIdx,
|
ElemIdx: head.ElemIdx,
|
||||||
@ -658,12 +585,13 @@ func newSliceElemCode(ctx *compileContext, head *Opcode, size uintptr) *Opcode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newArrayHeaderCode(ctx *compileContext, alen int) *Opcode {
|
func newArrayHeaderCode(ctx *compileContext, typ *runtime.Type, alen int) *Opcode {
|
||||||
idx := opcodeOffset(ctx.ptrIndex)
|
idx := opcodeOffset(ctx.ptrIndex)
|
||||||
ctx.incPtrIndex()
|
ctx.incPtrIndex()
|
||||||
elemIdx := opcodeOffset(ctx.ptrIndex)
|
elemIdx := opcodeOffset(ctx.ptrIndex)
|
||||||
return &Opcode{
|
return &Opcode{
|
||||||
Op: OpArray,
|
Op: OpArray,
|
||||||
|
Type: typ,
|
||||||
Idx: idx,
|
Idx: idx,
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
ElemIdx: elemIdx,
|
ElemIdx: elemIdx,
|
||||||
@ -672,9 +600,10 @@ func newArrayHeaderCode(ctx *compileContext, alen int) *Opcode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newArrayElemCode(ctx *compileContext, head *Opcode, length int, size uintptr) *Opcode {
|
func newArrayElemCode(ctx *compileContext, typ *runtime.Type, head *Opcode, length int, size uintptr) *Opcode {
|
||||||
return &Opcode{
|
return &Opcode{
|
||||||
Op: OpArrayElem,
|
Op: OpArrayElem,
|
||||||
|
Type: typ,
|
||||||
Idx: head.Idx,
|
Idx: head.Idx,
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
ElemIdx: head.ElemIdx,
|
ElemIdx: head.ElemIdx,
|
||||||
@ -684,87 +613,55 @@ func newArrayElemCode(ctx *compileContext, head *Opcode, length int, size uintpt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMapHeaderCode(ctx *compileContext) *Opcode {
|
func newMapHeaderCode(ctx *compileContext, typ *runtime.Type) *Opcode {
|
||||||
idx := opcodeOffset(ctx.ptrIndex)
|
idx := opcodeOffset(ctx.ptrIndex)
|
||||||
ctx.incPtrIndex()
|
ctx.incPtrIndex()
|
||||||
elemIdx := opcodeOffset(ctx.ptrIndex)
|
|
||||||
ctx.incPtrIndex()
|
|
||||||
length := opcodeOffset(ctx.ptrIndex)
|
|
||||||
ctx.incPtrIndex()
|
|
||||||
mapIter := opcodeOffset(ctx.ptrIndex)
|
|
||||||
return &Opcode{
|
return &Opcode{
|
||||||
Op: OpMap,
|
Op: OpMap,
|
||||||
|
Type: typ,
|
||||||
Idx: idx,
|
Idx: idx,
|
||||||
Type: ctx.typ,
|
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
ElemIdx: elemIdx,
|
|
||||||
Length: length,
|
|
||||||
MapIter: mapIter,
|
|
||||||
Indent: ctx.indent,
|
Indent: ctx.indent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMapKeyCode(ctx *compileContext, head *Opcode) *Opcode {
|
func newMapKeyCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode {
|
||||||
return &Opcode{
|
return &Opcode{
|
||||||
Op: OpMapKey,
|
Op: OpMapKey,
|
||||||
Idx: opcodeOffset(ctx.ptrIndex),
|
Type: typ,
|
||||||
|
Idx: head.Idx,
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
ElemIdx: head.ElemIdx,
|
|
||||||
Length: head.Length,
|
|
||||||
MapIter: head.MapIter,
|
|
||||||
Indent: ctx.indent,
|
Indent: ctx.indent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMapValueCode(ctx *compileContext, head *Opcode) *Opcode {
|
func newMapValueCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode {
|
||||||
return &Opcode{
|
return &Opcode{
|
||||||
Op: OpMapValue,
|
Op: OpMapValue,
|
||||||
Idx: opcodeOffset(ctx.ptrIndex),
|
Type: typ,
|
||||||
|
Idx: head.Idx,
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
ElemIdx: head.ElemIdx,
|
|
||||||
Length: head.Length,
|
|
||||||
MapIter: head.MapIter,
|
|
||||||
Indent: ctx.indent,
|
Indent: ctx.indent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMapEndCode(ctx *compileContext, head *Opcode) *Opcode {
|
func newMapEndCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode {
|
||||||
mapPos := opcodeOffset(ctx.ptrIndex)
|
|
||||||
ctx.incPtrIndex()
|
|
||||||
idx := opcodeOffset(ctx.ptrIndex)
|
|
||||||
return &Opcode{
|
return &Opcode{
|
||||||
Op: OpMapEnd,
|
Op: OpMapEnd,
|
||||||
Idx: idx,
|
Type: typ,
|
||||||
Next: newEndOp(ctx),
|
Idx: head.Idx,
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
Length: head.Length,
|
|
||||||
MapPos: mapPos,
|
|
||||||
Indent: ctx.indent,
|
Indent: ctx.indent,
|
||||||
|
Next: newEndOp(ctx, typ),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newInterfaceCode(ctx *compileContext) *Opcode {
|
func newRecursiveCode(ctx *compileContext, typ *runtime.Type, jmp *CompiledCode) *Opcode {
|
||||||
var flag OpFlags
|
|
||||||
if ctx.typ.NumMethod() > 0 {
|
|
||||||
flag |= NonEmptyInterfaceFlags
|
|
||||||
}
|
|
||||||
return &Opcode{
|
|
||||||
Op: OpInterface,
|
|
||||||
Idx: opcodeOffset(ctx.ptrIndex),
|
|
||||||
Next: newEndOp(ctx),
|
|
||||||
Type: ctx.typ,
|
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
|
||||||
Indent: ctx.indent,
|
|
||||||
Flags: flag,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newRecursiveCode(ctx *compileContext, jmp *CompiledCode) *Opcode {
|
|
||||||
return &Opcode{
|
return &Opcode{
|
||||||
Op: OpRecursive,
|
Op: OpRecursive,
|
||||||
|
Type: typ,
|
||||||
Idx: opcodeOffset(ctx.ptrIndex),
|
Idx: opcodeOffset(ctx.ptrIndex),
|
||||||
Next: newEndOp(ctx),
|
Next: newEndOp(ctx, typ),
|
||||||
Type: ctx.typ,
|
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
Indent: ctx.indent,
|
Indent: ctx.indent,
|
||||||
Jmp: jmp,
|
Jmp: jmp,
|
||||||
|
8
vendor/github.com/goccy/go-json/internal/encoder/option.go
generated
vendored
8
vendor/github.com/goccy/go-json/internal/encoder/option.go
generated
vendored
@ -1,6 +1,9 @@
|
|||||||
package encoder
|
package encoder
|
||||||
|
|
||||||
import "context"
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
type OptionFlag uint8
|
type OptionFlag uint8
|
||||||
|
|
||||||
@ -11,12 +14,15 @@ const (
|
|||||||
DebugOption
|
DebugOption
|
||||||
ColorizeOption
|
ColorizeOption
|
||||||
ContextOption
|
ContextOption
|
||||||
|
NormalizeUTF8Option
|
||||||
|
FieldQueryOption
|
||||||
)
|
)
|
||||||
|
|
||||||
type Option struct {
|
type Option struct {
|
||||||
Flag OptionFlag
|
Flag OptionFlag
|
||||||
ColorScheme *ColorScheme
|
ColorScheme *ColorScheme
|
||||||
Context context.Context
|
Context context.Context
|
||||||
|
DebugOut io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
type EncodeFormat struct {
|
type EncodeFormat struct {
|
||||||
|
780
vendor/github.com/goccy/go-json/internal/encoder/optype.go
generated
vendored
780
vendor/github.com/goccy/go-json/internal/encoder/optype.go
generated
vendored
@ -22,7 +22,7 @@ const (
|
|||||||
CodeStructEnd CodeType = 11
|
CodeStructEnd CodeType = 11
|
||||||
)
|
)
|
||||||
|
|
||||||
var opTypeStrings = [401]string{
|
var opTypeStrings = [400]string{
|
||||||
"End",
|
"End",
|
||||||
"Interface",
|
"Interface",
|
||||||
"Ptr",
|
"Ptr",
|
||||||
@ -37,7 +37,6 @@ var opTypeStrings = [401]string{
|
|||||||
"RecursivePtr",
|
"RecursivePtr",
|
||||||
"RecursiveEnd",
|
"RecursiveEnd",
|
||||||
"InterfaceEnd",
|
"InterfaceEnd",
|
||||||
"StructAnonymousEnd",
|
|
||||||
"Int",
|
"Int",
|
||||||
"Uint",
|
"Uint",
|
||||||
"Float32",
|
"Float32",
|
||||||
@ -443,397 +442,396 @@ const (
|
|||||||
OpRecursivePtr OpType = 11
|
OpRecursivePtr OpType = 11
|
||||||
OpRecursiveEnd OpType = 12
|
OpRecursiveEnd OpType = 12
|
||||||
OpInterfaceEnd OpType = 13
|
OpInterfaceEnd OpType = 13
|
||||||
OpStructAnonymousEnd OpType = 14
|
OpInt OpType = 14
|
||||||
OpInt OpType = 15
|
OpUint OpType = 15
|
||||||
OpUint OpType = 16
|
OpFloat32 OpType = 16
|
||||||
OpFloat32 OpType = 17
|
OpFloat64 OpType = 17
|
||||||
OpFloat64 OpType = 18
|
OpBool OpType = 18
|
||||||
OpBool OpType = 19
|
OpString OpType = 19
|
||||||
OpString OpType = 20
|
OpBytes OpType = 20
|
||||||
OpBytes OpType = 21
|
OpNumber OpType = 21
|
||||||
OpNumber OpType = 22
|
OpArray OpType = 22
|
||||||
OpArray OpType = 23
|
OpMap OpType = 23
|
||||||
OpMap OpType = 24
|
OpSlice OpType = 24
|
||||||
OpSlice OpType = 25
|
OpStruct OpType = 25
|
||||||
OpStruct OpType = 26
|
OpMarshalJSON OpType = 26
|
||||||
OpMarshalJSON OpType = 27
|
OpMarshalText OpType = 27
|
||||||
OpMarshalText OpType = 28
|
OpIntString OpType = 28
|
||||||
OpIntString OpType = 29
|
OpUintString OpType = 29
|
||||||
OpUintString OpType = 30
|
OpFloat32String OpType = 30
|
||||||
OpFloat32String OpType = 31
|
OpFloat64String OpType = 31
|
||||||
OpFloat64String OpType = 32
|
OpBoolString OpType = 32
|
||||||
OpBoolString OpType = 33
|
OpStringString OpType = 33
|
||||||
OpStringString OpType = 34
|
OpNumberString OpType = 34
|
||||||
OpNumberString OpType = 35
|
OpIntPtr OpType = 35
|
||||||
OpIntPtr OpType = 36
|
OpUintPtr OpType = 36
|
||||||
OpUintPtr OpType = 37
|
OpFloat32Ptr OpType = 37
|
||||||
OpFloat32Ptr OpType = 38
|
OpFloat64Ptr OpType = 38
|
||||||
OpFloat64Ptr OpType = 39
|
OpBoolPtr OpType = 39
|
||||||
OpBoolPtr OpType = 40
|
OpStringPtr OpType = 40
|
||||||
OpStringPtr OpType = 41
|
OpBytesPtr OpType = 41
|
||||||
OpBytesPtr OpType = 42
|
OpNumberPtr OpType = 42
|
||||||
OpNumberPtr OpType = 43
|
OpArrayPtr OpType = 43
|
||||||
OpArrayPtr OpType = 44
|
OpMapPtr OpType = 44
|
||||||
OpMapPtr OpType = 45
|
OpSlicePtr OpType = 45
|
||||||
OpSlicePtr OpType = 46
|
OpMarshalJSONPtr OpType = 46
|
||||||
OpMarshalJSONPtr OpType = 47
|
OpMarshalTextPtr OpType = 47
|
||||||
OpMarshalTextPtr OpType = 48
|
OpInterfacePtr OpType = 48
|
||||||
OpInterfacePtr OpType = 49
|
OpIntPtrString OpType = 49
|
||||||
OpIntPtrString OpType = 50
|
OpUintPtrString OpType = 50
|
||||||
OpUintPtrString OpType = 51
|
OpFloat32PtrString OpType = 51
|
||||||
OpFloat32PtrString OpType = 52
|
OpFloat64PtrString OpType = 52
|
||||||
OpFloat64PtrString OpType = 53
|
OpBoolPtrString OpType = 53
|
||||||
OpBoolPtrString OpType = 54
|
OpStringPtrString OpType = 54
|
||||||
OpStringPtrString OpType = 55
|
OpNumberPtrString OpType = 55
|
||||||
OpNumberPtrString OpType = 56
|
OpStructHeadInt OpType = 56
|
||||||
OpStructHeadInt OpType = 57
|
OpStructHeadOmitEmptyInt OpType = 57
|
||||||
OpStructHeadOmitEmptyInt OpType = 58
|
OpStructPtrHeadInt OpType = 58
|
||||||
OpStructPtrHeadInt OpType = 59
|
OpStructPtrHeadOmitEmptyInt OpType = 59
|
||||||
OpStructPtrHeadOmitEmptyInt OpType = 60
|
OpStructHeadUint OpType = 60
|
||||||
OpStructHeadUint OpType = 61
|
OpStructHeadOmitEmptyUint OpType = 61
|
||||||
OpStructHeadOmitEmptyUint OpType = 62
|
OpStructPtrHeadUint OpType = 62
|
||||||
OpStructPtrHeadUint OpType = 63
|
OpStructPtrHeadOmitEmptyUint OpType = 63
|
||||||
OpStructPtrHeadOmitEmptyUint OpType = 64
|
OpStructHeadFloat32 OpType = 64
|
||||||
OpStructHeadFloat32 OpType = 65
|
OpStructHeadOmitEmptyFloat32 OpType = 65
|
||||||
OpStructHeadOmitEmptyFloat32 OpType = 66
|
OpStructPtrHeadFloat32 OpType = 66
|
||||||
OpStructPtrHeadFloat32 OpType = 67
|
OpStructPtrHeadOmitEmptyFloat32 OpType = 67
|
||||||
OpStructPtrHeadOmitEmptyFloat32 OpType = 68
|
OpStructHeadFloat64 OpType = 68
|
||||||
OpStructHeadFloat64 OpType = 69
|
OpStructHeadOmitEmptyFloat64 OpType = 69
|
||||||
OpStructHeadOmitEmptyFloat64 OpType = 70
|
OpStructPtrHeadFloat64 OpType = 70
|
||||||
OpStructPtrHeadFloat64 OpType = 71
|
OpStructPtrHeadOmitEmptyFloat64 OpType = 71
|
||||||
OpStructPtrHeadOmitEmptyFloat64 OpType = 72
|
OpStructHeadBool OpType = 72
|
||||||
OpStructHeadBool OpType = 73
|
OpStructHeadOmitEmptyBool OpType = 73
|
||||||
OpStructHeadOmitEmptyBool OpType = 74
|
OpStructPtrHeadBool OpType = 74
|
||||||
OpStructPtrHeadBool OpType = 75
|
OpStructPtrHeadOmitEmptyBool OpType = 75
|
||||||
OpStructPtrHeadOmitEmptyBool OpType = 76
|
OpStructHeadString OpType = 76
|
||||||
OpStructHeadString OpType = 77
|
OpStructHeadOmitEmptyString OpType = 77
|
||||||
OpStructHeadOmitEmptyString OpType = 78
|
OpStructPtrHeadString OpType = 78
|
||||||
OpStructPtrHeadString OpType = 79
|
OpStructPtrHeadOmitEmptyString OpType = 79
|
||||||
OpStructPtrHeadOmitEmptyString OpType = 80
|
OpStructHeadBytes OpType = 80
|
||||||
OpStructHeadBytes OpType = 81
|
OpStructHeadOmitEmptyBytes OpType = 81
|
||||||
OpStructHeadOmitEmptyBytes OpType = 82
|
OpStructPtrHeadBytes OpType = 82
|
||||||
OpStructPtrHeadBytes OpType = 83
|
OpStructPtrHeadOmitEmptyBytes OpType = 83
|
||||||
OpStructPtrHeadOmitEmptyBytes OpType = 84
|
OpStructHeadNumber OpType = 84
|
||||||
OpStructHeadNumber OpType = 85
|
OpStructHeadOmitEmptyNumber OpType = 85
|
||||||
OpStructHeadOmitEmptyNumber OpType = 86
|
OpStructPtrHeadNumber OpType = 86
|
||||||
OpStructPtrHeadNumber OpType = 87
|
OpStructPtrHeadOmitEmptyNumber OpType = 87
|
||||||
OpStructPtrHeadOmitEmptyNumber OpType = 88
|
OpStructHeadArray OpType = 88
|
||||||
OpStructHeadArray OpType = 89
|
OpStructHeadOmitEmptyArray OpType = 89
|
||||||
OpStructHeadOmitEmptyArray OpType = 90
|
OpStructPtrHeadArray OpType = 90
|
||||||
OpStructPtrHeadArray OpType = 91
|
OpStructPtrHeadOmitEmptyArray OpType = 91
|
||||||
OpStructPtrHeadOmitEmptyArray OpType = 92
|
OpStructHeadMap OpType = 92
|
||||||
OpStructHeadMap OpType = 93
|
OpStructHeadOmitEmptyMap OpType = 93
|
||||||
OpStructHeadOmitEmptyMap OpType = 94
|
OpStructPtrHeadMap OpType = 94
|
||||||
OpStructPtrHeadMap OpType = 95
|
OpStructPtrHeadOmitEmptyMap OpType = 95
|
||||||
OpStructPtrHeadOmitEmptyMap OpType = 96
|
OpStructHeadSlice OpType = 96
|
||||||
OpStructHeadSlice OpType = 97
|
OpStructHeadOmitEmptySlice OpType = 97
|
||||||
OpStructHeadOmitEmptySlice OpType = 98
|
OpStructPtrHeadSlice OpType = 98
|
||||||
OpStructPtrHeadSlice OpType = 99
|
OpStructPtrHeadOmitEmptySlice OpType = 99
|
||||||
OpStructPtrHeadOmitEmptySlice OpType = 100
|
OpStructHeadStruct OpType = 100
|
||||||
OpStructHeadStruct OpType = 101
|
OpStructHeadOmitEmptyStruct OpType = 101
|
||||||
OpStructHeadOmitEmptyStruct OpType = 102
|
OpStructPtrHeadStruct OpType = 102
|
||||||
OpStructPtrHeadStruct OpType = 103
|
OpStructPtrHeadOmitEmptyStruct OpType = 103
|
||||||
OpStructPtrHeadOmitEmptyStruct OpType = 104
|
OpStructHeadMarshalJSON OpType = 104
|
||||||
OpStructHeadMarshalJSON OpType = 105
|
OpStructHeadOmitEmptyMarshalJSON OpType = 105
|
||||||
OpStructHeadOmitEmptyMarshalJSON OpType = 106
|
OpStructPtrHeadMarshalJSON OpType = 106
|
||||||
OpStructPtrHeadMarshalJSON OpType = 107
|
OpStructPtrHeadOmitEmptyMarshalJSON OpType = 107
|
||||||
OpStructPtrHeadOmitEmptyMarshalJSON OpType = 108
|
OpStructHeadMarshalText OpType = 108
|
||||||
OpStructHeadMarshalText OpType = 109
|
OpStructHeadOmitEmptyMarshalText OpType = 109
|
||||||
OpStructHeadOmitEmptyMarshalText OpType = 110
|
OpStructPtrHeadMarshalText OpType = 110
|
||||||
OpStructPtrHeadMarshalText OpType = 111
|
OpStructPtrHeadOmitEmptyMarshalText OpType = 111
|
||||||
OpStructPtrHeadOmitEmptyMarshalText OpType = 112
|
OpStructHeadIntString OpType = 112
|
||||||
OpStructHeadIntString OpType = 113
|
OpStructHeadOmitEmptyIntString OpType = 113
|
||||||
OpStructHeadOmitEmptyIntString OpType = 114
|
OpStructPtrHeadIntString OpType = 114
|
||||||
OpStructPtrHeadIntString OpType = 115
|
OpStructPtrHeadOmitEmptyIntString OpType = 115
|
||||||
OpStructPtrHeadOmitEmptyIntString OpType = 116
|
OpStructHeadUintString OpType = 116
|
||||||
OpStructHeadUintString OpType = 117
|
OpStructHeadOmitEmptyUintString OpType = 117
|
||||||
OpStructHeadOmitEmptyUintString OpType = 118
|
OpStructPtrHeadUintString OpType = 118
|
||||||
OpStructPtrHeadUintString OpType = 119
|
OpStructPtrHeadOmitEmptyUintString OpType = 119
|
||||||
OpStructPtrHeadOmitEmptyUintString OpType = 120
|
OpStructHeadFloat32String OpType = 120
|
||||||
OpStructHeadFloat32String OpType = 121
|
OpStructHeadOmitEmptyFloat32String OpType = 121
|
||||||
OpStructHeadOmitEmptyFloat32String OpType = 122
|
OpStructPtrHeadFloat32String OpType = 122
|
||||||
OpStructPtrHeadFloat32String OpType = 123
|
OpStructPtrHeadOmitEmptyFloat32String OpType = 123
|
||||||
OpStructPtrHeadOmitEmptyFloat32String OpType = 124
|
OpStructHeadFloat64String OpType = 124
|
||||||
OpStructHeadFloat64String OpType = 125
|
OpStructHeadOmitEmptyFloat64String OpType = 125
|
||||||
OpStructHeadOmitEmptyFloat64String OpType = 126
|
OpStructPtrHeadFloat64String OpType = 126
|
||||||
OpStructPtrHeadFloat64String OpType = 127
|
OpStructPtrHeadOmitEmptyFloat64String OpType = 127
|
||||||
OpStructPtrHeadOmitEmptyFloat64String OpType = 128
|
OpStructHeadBoolString OpType = 128
|
||||||
OpStructHeadBoolString OpType = 129
|
OpStructHeadOmitEmptyBoolString OpType = 129
|
||||||
OpStructHeadOmitEmptyBoolString OpType = 130
|
OpStructPtrHeadBoolString OpType = 130
|
||||||
OpStructPtrHeadBoolString OpType = 131
|
OpStructPtrHeadOmitEmptyBoolString OpType = 131
|
||||||
OpStructPtrHeadOmitEmptyBoolString OpType = 132
|
OpStructHeadStringString OpType = 132
|
||||||
OpStructHeadStringString OpType = 133
|
OpStructHeadOmitEmptyStringString OpType = 133
|
||||||
OpStructHeadOmitEmptyStringString OpType = 134
|
OpStructPtrHeadStringString OpType = 134
|
||||||
OpStructPtrHeadStringString OpType = 135
|
OpStructPtrHeadOmitEmptyStringString OpType = 135
|
||||||
OpStructPtrHeadOmitEmptyStringString OpType = 136
|
OpStructHeadNumberString OpType = 136
|
||||||
OpStructHeadNumberString OpType = 137
|
OpStructHeadOmitEmptyNumberString OpType = 137
|
||||||
OpStructHeadOmitEmptyNumberString OpType = 138
|
OpStructPtrHeadNumberString OpType = 138
|
||||||
OpStructPtrHeadNumberString OpType = 139
|
OpStructPtrHeadOmitEmptyNumberString OpType = 139
|
||||||
OpStructPtrHeadOmitEmptyNumberString OpType = 140
|
OpStructHeadIntPtr OpType = 140
|
||||||
OpStructHeadIntPtr OpType = 141
|
OpStructHeadOmitEmptyIntPtr OpType = 141
|
||||||
OpStructHeadOmitEmptyIntPtr OpType = 142
|
OpStructPtrHeadIntPtr OpType = 142
|
||||||
OpStructPtrHeadIntPtr OpType = 143
|
OpStructPtrHeadOmitEmptyIntPtr OpType = 143
|
||||||
OpStructPtrHeadOmitEmptyIntPtr OpType = 144
|
OpStructHeadUintPtr OpType = 144
|
||||||
OpStructHeadUintPtr OpType = 145
|
OpStructHeadOmitEmptyUintPtr OpType = 145
|
||||||
OpStructHeadOmitEmptyUintPtr OpType = 146
|
OpStructPtrHeadUintPtr OpType = 146
|
||||||
OpStructPtrHeadUintPtr OpType = 147
|
OpStructPtrHeadOmitEmptyUintPtr OpType = 147
|
||||||
OpStructPtrHeadOmitEmptyUintPtr OpType = 148
|
OpStructHeadFloat32Ptr OpType = 148
|
||||||
OpStructHeadFloat32Ptr OpType = 149
|
OpStructHeadOmitEmptyFloat32Ptr OpType = 149
|
||||||
OpStructHeadOmitEmptyFloat32Ptr OpType = 150
|
OpStructPtrHeadFloat32Ptr OpType = 150
|
||||||
OpStructPtrHeadFloat32Ptr OpType = 151
|
OpStructPtrHeadOmitEmptyFloat32Ptr OpType = 151
|
||||||
OpStructPtrHeadOmitEmptyFloat32Ptr OpType = 152
|
OpStructHeadFloat64Ptr OpType = 152
|
||||||
OpStructHeadFloat64Ptr OpType = 153
|
OpStructHeadOmitEmptyFloat64Ptr OpType = 153
|
||||||
OpStructHeadOmitEmptyFloat64Ptr OpType = 154
|
OpStructPtrHeadFloat64Ptr OpType = 154
|
||||||
OpStructPtrHeadFloat64Ptr OpType = 155
|
OpStructPtrHeadOmitEmptyFloat64Ptr OpType = 155
|
||||||
OpStructPtrHeadOmitEmptyFloat64Ptr OpType = 156
|
OpStructHeadBoolPtr OpType = 156
|
||||||
OpStructHeadBoolPtr OpType = 157
|
OpStructHeadOmitEmptyBoolPtr OpType = 157
|
||||||
OpStructHeadOmitEmptyBoolPtr OpType = 158
|
OpStructPtrHeadBoolPtr OpType = 158
|
||||||
OpStructPtrHeadBoolPtr OpType = 159
|
OpStructPtrHeadOmitEmptyBoolPtr OpType = 159
|
||||||
OpStructPtrHeadOmitEmptyBoolPtr OpType = 160
|
OpStructHeadStringPtr OpType = 160
|
||||||
OpStructHeadStringPtr OpType = 161
|
OpStructHeadOmitEmptyStringPtr OpType = 161
|
||||||
OpStructHeadOmitEmptyStringPtr OpType = 162
|
OpStructPtrHeadStringPtr OpType = 162
|
||||||
OpStructPtrHeadStringPtr OpType = 163
|
OpStructPtrHeadOmitEmptyStringPtr OpType = 163
|
||||||
OpStructPtrHeadOmitEmptyStringPtr OpType = 164
|
OpStructHeadBytesPtr OpType = 164
|
||||||
OpStructHeadBytesPtr OpType = 165
|
OpStructHeadOmitEmptyBytesPtr OpType = 165
|
||||||
OpStructHeadOmitEmptyBytesPtr OpType = 166
|
OpStructPtrHeadBytesPtr OpType = 166
|
||||||
OpStructPtrHeadBytesPtr OpType = 167
|
OpStructPtrHeadOmitEmptyBytesPtr OpType = 167
|
||||||
OpStructPtrHeadOmitEmptyBytesPtr OpType = 168
|
OpStructHeadNumberPtr OpType = 168
|
||||||
OpStructHeadNumberPtr OpType = 169
|
OpStructHeadOmitEmptyNumberPtr OpType = 169
|
||||||
OpStructHeadOmitEmptyNumberPtr OpType = 170
|
OpStructPtrHeadNumberPtr OpType = 170
|
||||||
OpStructPtrHeadNumberPtr OpType = 171
|
OpStructPtrHeadOmitEmptyNumberPtr OpType = 171
|
||||||
OpStructPtrHeadOmitEmptyNumberPtr OpType = 172
|
OpStructHeadArrayPtr OpType = 172
|
||||||
OpStructHeadArrayPtr OpType = 173
|
OpStructHeadOmitEmptyArrayPtr OpType = 173
|
||||||
OpStructHeadOmitEmptyArrayPtr OpType = 174
|
OpStructPtrHeadArrayPtr OpType = 174
|
||||||
OpStructPtrHeadArrayPtr OpType = 175
|
OpStructPtrHeadOmitEmptyArrayPtr OpType = 175
|
||||||
OpStructPtrHeadOmitEmptyArrayPtr OpType = 176
|
OpStructHeadMapPtr OpType = 176
|
||||||
OpStructHeadMapPtr OpType = 177
|
OpStructHeadOmitEmptyMapPtr OpType = 177
|
||||||
OpStructHeadOmitEmptyMapPtr OpType = 178
|
OpStructPtrHeadMapPtr OpType = 178
|
||||||
OpStructPtrHeadMapPtr OpType = 179
|
OpStructPtrHeadOmitEmptyMapPtr OpType = 179
|
||||||
OpStructPtrHeadOmitEmptyMapPtr OpType = 180
|
OpStructHeadSlicePtr OpType = 180
|
||||||
OpStructHeadSlicePtr OpType = 181
|
OpStructHeadOmitEmptySlicePtr OpType = 181
|
||||||
OpStructHeadOmitEmptySlicePtr OpType = 182
|
OpStructPtrHeadSlicePtr OpType = 182
|
||||||
OpStructPtrHeadSlicePtr OpType = 183
|
OpStructPtrHeadOmitEmptySlicePtr OpType = 183
|
||||||
OpStructPtrHeadOmitEmptySlicePtr OpType = 184
|
OpStructHeadMarshalJSONPtr OpType = 184
|
||||||
OpStructHeadMarshalJSONPtr OpType = 185
|
OpStructHeadOmitEmptyMarshalJSONPtr OpType = 185
|
||||||
OpStructHeadOmitEmptyMarshalJSONPtr OpType = 186
|
OpStructPtrHeadMarshalJSONPtr OpType = 186
|
||||||
OpStructPtrHeadMarshalJSONPtr OpType = 187
|
OpStructPtrHeadOmitEmptyMarshalJSONPtr OpType = 187
|
||||||
OpStructPtrHeadOmitEmptyMarshalJSONPtr OpType = 188
|
OpStructHeadMarshalTextPtr OpType = 188
|
||||||
OpStructHeadMarshalTextPtr OpType = 189
|
OpStructHeadOmitEmptyMarshalTextPtr OpType = 189
|
||||||
OpStructHeadOmitEmptyMarshalTextPtr OpType = 190
|
OpStructPtrHeadMarshalTextPtr OpType = 190
|
||||||
OpStructPtrHeadMarshalTextPtr OpType = 191
|
OpStructPtrHeadOmitEmptyMarshalTextPtr OpType = 191
|
||||||
OpStructPtrHeadOmitEmptyMarshalTextPtr OpType = 192
|
OpStructHeadInterfacePtr OpType = 192
|
||||||
OpStructHeadInterfacePtr OpType = 193
|
OpStructHeadOmitEmptyInterfacePtr OpType = 193
|
||||||
OpStructHeadOmitEmptyInterfacePtr OpType = 194
|
OpStructPtrHeadInterfacePtr OpType = 194
|
||||||
OpStructPtrHeadInterfacePtr OpType = 195
|
OpStructPtrHeadOmitEmptyInterfacePtr OpType = 195
|
||||||
OpStructPtrHeadOmitEmptyInterfacePtr OpType = 196
|
OpStructHeadIntPtrString OpType = 196
|
||||||
OpStructHeadIntPtrString OpType = 197
|
OpStructHeadOmitEmptyIntPtrString OpType = 197
|
||||||
OpStructHeadOmitEmptyIntPtrString OpType = 198
|
OpStructPtrHeadIntPtrString OpType = 198
|
||||||
OpStructPtrHeadIntPtrString OpType = 199
|
OpStructPtrHeadOmitEmptyIntPtrString OpType = 199
|
||||||
OpStructPtrHeadOmitEmptyIntPtrString OpType = 200
|
OpStructHeadUintPtrString OpType = 200
|
||||||
OpStructHeadUintPtrString OpType = 201
|
OpStructHeadOmitEmptyUintPtrString OpType = 201
|
||||||
OpStructHeadOmitEmptyUintPtrString OpType = 202
|
OpStructPtrHeadUintPtrString OpType = 202
|
||||||
OpStructPtrHeadUintPtrString OpType = 203
|
OpStructPtrHeadOmitEmptyUintPtrString OpType = 203
|
||||||
OpStructPtrHeadOmitEmptyUintPtrString OpType = 204
|
OpStructHeadFloat32PtrString OpType = 204
|
||||||
OpStructHeadFloat32PtrString OpType = 205
|
OpStructHeadOmitEmptyFloat32PtrString OpType = 205
|
||||||
OpStructHeadOmitEmptyFloat32PtrString OpType = 206
|
OpStructPtrHeadFloat32PtrString OpType = 206
|
||||||
OpStructPtrHeadFloat32PtrString OpType = 207
|
OpStructPtrHeadOmitEmptyFloat32PtrString OpType = 207
|
||||||
OpStructPtrHeadOmitEmptyFloat32PtrString OpType = 208
|
OpStructHeadFloat64PtrString OpType = 208
|
||||||
OpStructHeadFloat64PtrString OpType = 209
|
OpStructHeadOmitEmptyFloat64PtrString OpType = 209
|
||||||
OpStructHeadOmitEmptyFloat64PtrString OpType = 210
|
OpStructPtrHeadFloat64PtrString OpType = 210
|
||||||
OpStructPtrHeadFloat64PtrString OpType = 211
|
OpStructPtrHeadOmitEmptyFloat64PtrString OpType = 211
|
||||||
OpStructPtrHeadOmitEmptyFloat64PtrString OpType = 212
|
OpStructHeadBoolPtrString OpType = 212
|
||||||
OpStructHeadBoolPtrString OpType = 213
|
OpStructHeadOmitEmptyBoolPtrString OpType = 213
|
||||||
OpStructHeadOmitEmptyBoolPtrString OpType = 214
|
OpStructPtrHeadBoolPtrString OpType = 214
|
||||||
OpStructPtrHeadBoolPtrString OpType = 215
|
OpStructPtrHeadOmitEmptyBoolPtrString OpType = 215
|
||||||
OpStructPtrHeadOmitEmptyBoolPtrString OpType = 216
|
OpStructHeadStringPtrString OpType = 216
|
||||||
OpStructHeadStringPtrString OpType = 217
|
OpStructHeadOmitEmptyStringPtrString OpType = 217
|
||||||
OpStructHeadOmitEmptyStringPtrString OpType = 218
|
OpStructPtrHeadStringPtrString OpType = 218
|
||||||
OpStructPtrHeadStringPtrString OpType = 219
|
OpStructPtrHeadOmitEmptyStringPtrString OpType = 219
|
||||||
OpStructPtrHeadOmitEmptyStringPtrString OpType = 220
|
OpStructHeadNumberPtrString OpType = 220
|
||||||
OpStructHeadNumberPtrString OpType = 221
|
OpStructHeadOmitEmptyNumberPtrString OpType = 221
|
||||||
OpStructHeadOmitEmptyNumberPtrString OpType = 222
|
OpStructPtrHeadNumberPtrString OpType = 222
|
||||||
OpStructPtrHeadNumberPtrString OpType = 223
|
OpStructPtrHeadOmitEmptyNumberPtrString OpType = 223
|
||||||
OpStructPtrHeadOmitEmptyNumberPtrString OpType = 224
|
OpStructHead OpType = 224
|
||||||
OpStructHead OpType = 225
|
OpStructHeadOmitEmpty OpType = 225
|
||||||
OpStructHeadOmitEmpty OpType = 226
|
OpStructPtrHead OpType = 226
|
||||||
OpStructPtrHead OpType = 227
|
OpStructPtrHeadOmitEmpty OpType = 227
|
||||||
OpStructPtrHeadOmitEmpty OpType = 228
|
OpStructFieldInt OpType = 228
|
||||||
OpStructFieldInt OpType = 229
|
OpStructFieldOmitEmptyInt OpType = 229
|
||||||
OpStructFieldOmitEmptyInt OpType = 230
|
OpStructEndInt OpType = 230
|
||||||
OpStructEndInt OpType = 231
|
OpStructEndOmitEmptyInt OpType = 231
|
||||||
OpStructEndOmitEmptyInt OpType = 232
|
OpStructFieldUint OpType = 232
|
||||||
OpStructFieldUint OpType = 233
|
OpStructFieldOmitEmptyUint OpType = 233
|
||||||
OpStructFieldOmitEmptyUint OpType = 234
|
OpStructEndUint OpType = 234
|
||||||
OpStructEndUint OpType = 235
|
OpStructEndOmitEmptyUint OpType = 235
|
||||||
OpStructEndOmitEmptyUint OpType = 236
|
OpStructFieldFloat32 OpType = 236
|
||||||
OpStructFieldFloat32 OpType = 237
|
OpStructFieldOmitEmptyFloat32 OpType = 237
|
||||||
OpStructFieldOmitEmptyFloat32 OpType = 238
|
OpStructEndFloat32 OpType = 238
|
||||||
OpStructEndFloat32 OpType = 239
|
OpStructEndOmitEmptyFloat32 OpType = 239
|
||||||
OpStructEndOmitEmptyFloat32 OpType = 240
|
OpStructFieldFloat64 OpType = 240
|
||||||
OpStructFieldFloat64 OpType = 241
|
OpStructFieldOmitEmptyFloat64 OpType = 241
|
||||||
OpStructFieldOmitEmptyFloat64 OpType = 242
|
OpStructEndFloat64 OpType = 242
|
||||||
OpStructEndFloat64 OpType = 243
|
OpStructEndOmitEmptyFloat64 OpType = 243
|
||||||
OpStructEndOmitEmptyFloat64 OpType = 244
|
OpStructFieldBool OpType = 244
|
||||||
OpStructFieldBool OpType = 245
|
OpStructFieldOmitEmptyBool OpType = 245
|
||||||
OpStructFieldOmitEmptyBool OpType = 246
|
OpStructEndBool OpType = 246
|
||||||
OpStructEndBool OpType = 247
|
OpStructEndOmitEmptyBool OpType = 247
|
||||||
OpStructEndOmitEmptyBool OpType = 248
|
OpStructFieldString OpType = 248
|
||||||
OpStructFieldString OpType = 249
|
OpStructFieldOmitEmptyString OpType = 249
|
||||||
OpStructFieldOmitEmptyString OpType = 250
|
OpStructEndString OpType = 250
|
||||||
OpStructEndString OpType = 251
|
OpStructEndOmitEmptyString OpType = 251
|
||||||
OpStructEndOmitEmptyString OpType = 252
|
OpStructFieldBytes OpType = 252
|
||||||
OpStructFieldBytes OpType = 253
|
OpStructFieldOmitEmptyBytes OpType = 253
|
||||||
OpStructFieldOmitEmptyBytes OpType = 254
|
OpStructEndBytes OpType = 254
|
||||||
OpStructEndBytes OpType = 255
|
OpStructEndOmitEmptyBytes OpType = 255
|
||||||
OpStructEndOmitEmptyBytes OpType = 256
|
OpStructFieldNumber OpType = 256
|
||||||
OpStructFieldNumber OpType = 257
|
OpStructFieldOmitEmptyNumber OpType = 257
|
||||||
OpStructFieldOmitEmptyNumber OpType = 258
|
OpStructEndNumber OpType = 258
|
||||||
OpStructEndNumber OpType = 259
|
OpStructEndOmitEmptyNumber OpType = 259
|
||||||
OpStructEndOmitEmptyNumber OpType = 260
|
OpStructFieldArray OpType = 260
|
||||||
OpStructFieldArray OpType = 261
|
OpStructFieldOmitEmptyArray OpType = 261
|
||||||
OpStructFieldOmitEmptyArray OpType = 262
|
OpStructEndArray OpType = 262
|
||||||
OpStructEndArray OpType = 263
|
OpStructEndOmitEmptyArray OpType = 263
|
||||||
OpStructEndOmitEmptyArray OpType = 264
|
OpStructFieldMap OpType = 264
|
||||||
OpStructFieldMap OpType = 265
|
OpStructFieldOmitEmptyMap OpType = 265
|
||||||
OpStructFieldOmitEmptyMap OpType = 266
|
OpStructEndMap OpType = 266
|
||||||
OpStructEndMap OpType = 267
|
OpStructEndOmitEmptyMap OpType = 267
|
||||||
OpStructEndOmitEmptyMap OpType = 268
|
OpStructFieldSlice OpType = 268
|
||||||
OpStructFieldSlice OpType = 269
|
OpStructFieldOmitEmptySlice OpType = 269
|
||||||
OpStructFieldOmitEmptySlice OpType = 270
|
OpStructEndSlice OpType = 270
|
||||||
OpStructEndSlice OpType = 271
|
OpStructEndOmitEmptySlice OpType = 271
|
||||||
OpStructEndOmitEmptySlice OpType = 272
|
OpStructFieldStruct OpType = 272
|
||||||
OpStructFieldStruct OpType = 273
|
OpStructFieldOmitEmptyStruct OpType = 273
|
||||||
OpStructFieldOmitEmptyStruct OpType = 274
|
OpStructEndStruct OpType = 274
|
||||||
OpStructEndStruct OpType = 275
|
OpStructEndOmitEmptyStruct OpType = 275
|
||||||
OpStructEndOmitEmptyStruct OpType = 276
|
OpStructFieldMarshalJSON OpType = 276
|
||||||
OpStructFieldMarshalJSON OpType = 277
|
OpStructFieldOmitEmptyMarshalJSON OpType = 277
|
||||||
OpStructFieldOmitEmptyMarshalJSON OpType = 278
|
OpStructEndMarshalJSON OpType = 278
|
||||||
OpStructEndMarshalJSON OpType = 279
|
OpStructEndOmitEmptyMarshalJSON OpType = 279
|
||||||
OpStructEndOmitEmptyMarshalJSON OpType = 280
|
OpStructFieldMarshalText OpType = 280
|
||||||
OpStructFieldMarshalText OpType = 281
|
OpStructFieldOmitEmptyMarshalText OpType = 281
|
||||||
OpStructFieldOmitEmptyMarshalText OpType = 282
|
OpStructEndMarshalText OpType = 282
|
||||||
OpStructEndMarshalText OpType = 283
|
OpStructEndOmitEmptyMarshalText OpType = 283
|
||||||
OpStructEndOmitEmptyMarshalText OpType = 284
|
OpStructFieldIntString OpType = 284
|
||||||
OpStructFieldIntString OpType = 285
|
OpStructFieldOmitEmptyIntString OpType = 285
|
||||||
OpStructFieldOmitEmptyIntString OpType = 286
|
OpStructEndIntString OpType = 286
|
||||||
OpStructEndIntString OpType = 287
|
OpStructEndOmitEmptyIntString OpType = 287
|
||||||
OpStructEndOmitEmptyIntString OpType = 288
|
OpStructFieldUintString OpType = 288
|
||||||
OpStructFieldUintString OpType = 289
|
OpStructFieldOmitEmptyUintString OpType = 289
|
||||||
OpStructFieldOmitEmptyUintString OpType = 290
|
OpStructEndUintString OpType = 290
|
||||||
OpStructEndUintString OpType = 291
|
OpStructEndOmitEmptyUintString OpType = 291
|
||||||
OpStructEndOmitEmptyUintString OpType = 292
|
OpStructFieldFloat32String OpType = 292
|
||||||
OpStructFieldFloat32String OpType = 293
|
OpStructFieldOmitEmptyFloat32String OpType = 293
|
||||||
OpStructFieldOmitEmptyFloat32String OpType = 294
|
OpStructEndFloat32String OpType = 294
|
||||||
OpStructEndFloat32String OpType = 295
|
OpStructEndOmitEmptyFloat32String OpType = 295
|
||||||
OpStructEndOmitEmptyFloat32String OpType = 296
|
OpStructFieldFloat64String OpType = 296
|
||||||
OpStructFieldFloat64String OpType = 297
|
OpStructFieldOmitEmptyFloat64String OpType = 297
|
||||||
OpStructFieldOmitEmptyFloat64String OpType = 298
|
OpStructEndFloat64String OpType = 298
|
||||||
OpStructEndFloat64String OpType = 299
|
OpStructEndOmitEmptyFloat64String OpType = 299
|
||||||
OpStructEndOmitEmptyFloat64String OpType = 300
|
OpStructFieldBoolString OpType = 300
|
||||||
OpStructFieldBoolString OpType = 301
|
OpStructFieldOmitEmptyBoolString OpType = 301
|
||||||
OpStructFieldOmitEmptyBoolString OpType = 302
|
OpStructEndBoolString OpType = 302
|
||||||
OpStructEndBoolString OpType = 303
|
OpStructEndOmitEmptyBoolString OpType = 303
|
||||||
OpStructEndOmitEmptyBoolString OpType = 304
|
OpStructFieldStringString OpType = 304
|
||||||
OpStructFieldStringString OpType = 305
|
OpStructFieldOmitEmptyStringString OpType = 305
|
||||||
OpStructFieldOmitEmptyStringString OpType = 306
|
OpStructEndStringString OpType = 306
|
||||||
OpStructEndStringString OpType = 307
|
OpStructEndOmitEmptyStringString OpType = 307
|
||||||
OpStructEndOmitEmptyStringString OpType = 308
|
OpStructFieldNumberString OpType = 308
|
||||||
OpStructFieldNumberString OpType = 309
|
OpStructFieldOmitEmptyNumberString OpType = 309
|
||||||
OpStructFieldOmitEmptyNumberString OpType = 310
|
OpStructEndNumberString OpType = 310
|
||||||
OpStructEndNumberString OpType = 311
|
OpStructEndOmitEmptyNumberString OpType = 311
|
||||||
OpStructEndOmitEmptyNumberString OpType = 312
|
OpStructFieldIntPtr OpType = 312
|
||||||
OpStructFieldIntPtr OpType = 313
|
OpStructFieldOmitEmptyIntPtr OpType = 313
|
||||||
OpStructFieldOmitEmptyIntPtr OpType = 314
|
OpStructEndIntPtr OpType = 314
|
||||||
OpStructEndIntPtr OpType = 315
|
OpStructEndOmitEmptyIntPtr OpType = 315
|
||||||
OpStructEndOmitEmptyIntPtr OpType = 316
|
OpStructFieldUintPtr OpType = 316
|
||||||
OpStructFieldUintPtr OpType = 317
|
OpStructFieldOmitEmptyUintPtr OpType = 317
|
||||||
OpStructFieldOmitEmptyUintPtr OpType = 318
|
OpStructEndUintPtr OpType = 318
|
||||||
OpStructEndUintPtr OpType = 319
|
OpStructEndOmitEmptyUintPtr OpType = 319
|
||||||
OpStructEndOmitEmptyUintPtr OpType = 320
|
OpStructFieldFloat32Ptr OpType = 320
|
||||||
OpStructFieldFloat32Ptr OpType = 321
|
OpStructFieldOmitEmptyFloat32Ptr OpType = 321
|
||||||
OpStructFieldOmitEmptyFloat32Ptr OpType = 322
|
OpStructEndFloat32Ptr OpType = 322
|
||||||
OpStructEndFloat32Ptr OpType = 323
|
OpStructEndOmitEmptyFloat32Ptr OpType = 323
|
||||||
OpStructEndOmitEmptyFloat32Ptr OpType = 324
|
OpStructFieldFloat64Ptr OpType = 324
|
||||||
OpStructFieldFloat64Ptr OpType = 325
|
OpStructFieldOmitEmptyFloat64Ptr OpType = 325
|
||||||
OpStructFieldOmitEmptyFloat64Ptr OpType = 326
|
OpStructEndFloat64Ptr OpType = 326
|
||||||
OpStructEndFloat64Ptr OpType = 327
|
OpStructEndOmitEmptyFloat64Ptr OpType = 327
|
||||||
OpStructEndOmitEmptyFloat64Ptr OpType = 328
|
OpStructFieldBoolPtr OpType = 328
|
||||||
OpStructFieldBoolPtr OpType = 329
|
OpStructFieldOmitEmptyBoolPtr OpType = 329
|
||||||
OpStructFieldOmitEmptyBoolPtr OpType = 330
|
OpStructEndBoolPtr OpType = 330
|
||||||
OpStructEndBoolPtr OpType = 331
|
OpStructEndOmitEmptyBoolPtr OpType = 331
|
||||||
OpStructEndOmitEmptyBoolPtr OpType = 332
|
OpStructFieldStringPtr OpType = 332
|
||||||
OpStructFieldStringPtr OpType = 333
|
OpStructFieldOmitEmptyStringPtr OpType = 333
|
||||||
OpStructFieldOmitEmptyStringPtr OpType = 334
|
OpStructEndStringPtr OpType = 334
|
||||||
OpStructEndStringPtr OpType = 335
|
OpStructEndOmitEmptyStringPtr OpType = 335
|
||||||
OpStructEndOmitEmptyStringPtr OpType = 336
|
OpStructFieldBytesPtr OpType = 336
|
||||||
OpStructFieldBytesPtr OpType = 337
|
OpStructFieldOmitEmptyBytesPtr OpType = 337
|
||||||
OpStructFieldOmitEmptyBytesPtr OpType = 338
|
OpStructEndBytesPtr OpType = 338
|
||||||
OpStructEndBytesPtr OpType = 339
|
OpStructEndOmitEmptyBytesPtr OpType = 339
|
||||||
OpStructEndOmitEmptyBytesPtr OpType = 340
|
OpStructFieldNumberPtr OpType = 340
|
||||||
OpStructFieldNumberPtr OpType = 341
|
OpStructFieldOmitEmptyNumberPtr OpType = 341
|
||||||
OpStructFieldOmitEmptyNumberPtr OpType = 342
|
OpStructEndNumberPtr OpType = 342
|
||||||
OpStructEndNumberPtr OpType = 343
|
OpStructEndOmitEmptyNumberPtr OpType = 343
|
||||||
OpStructEndOmitEmptyNumberPtr OpType = 344
|
OpStructFieldArrayPtr OpType = 344
|
||||||
OpStructFieldArrayPtr OpType = 345
|
OpStructFieldOmitEmptyArrayPtr OpType = 345
|
||||||
OpStructFieldOmitEmptyArrayPtr OpType = 346
|
OpStructEndArrayPtr OpType = 346
|
||||||
OpStructEndArrayPtr OpType = 347
|
OpStructEndOmitEmptyArrayPtr OpType = 347
|
||||||
OpStructEndOmitEmptyArrayPtr OpType = 348
|
OpStructFieldMapPtr OpType = 348
|
||||||
OpStructFieldMapPtr OpType = 349
|
OpStructFieldOmitEmptyMapPtr OpType = 349
|
||||||
OpStructFieldOmitEmptyMapPtr OpType = 350
|
OpStructEndMapPtr OpType = 350
|
||||||
OpStructEndMapPtr OpType = 351
|
OpStructEndOmitEmptyMapPtr OpType = 351
|
||||||
OpStructEndOmitEmptyMapPtr OpType = 352
|
OpStructFieldSlicePtr OpType = 352
|
||||||
OpStructFieldSlicePtr OpType = 353
|
OpStructFieldOmitEmptySlicePtr OpType = 353
|
||||||
OpStructFieldOmitEmptySlicePtr OpType = 354
|
OpStructEndSlicePtr OpType = 354
|
||||||
OpStructEndSlicePtr OpType = 355
|
OpStructEndOmitEmptySlicePtr OpType = 355
|
||||||
OpStructEndOmitEmptySlicePtr OpType = 356
|
OpStructFieldMarshalJSONPtr OpType = 356
|
||||||
OpStructFieldMarshalJSONPtr OpType = 357
|
OpStructFieldOmitEmptyMarshalJSONPtr OpType = 357
|
||||||
OpStructFieldOmitEmptyMarshalJSONPtr OpType = 358
|
OpStructEndMarshalJSONPtr OpType = 358
|
||||||
OpStructEndMarshalJSONPtr OpType = 359
|
OpStructEndOmitEmptyMarshalJSONPtr OpType = 359
|
||||||
OpStructEndOmitEmptyMarshalJSONPtr OpType = 360
|
OpStructFieldMarshalTextPtr OpType = 360
|
||||||
OpStructFieldMarshalTextPtr OpType = 361
|
OpStructFieldOmitEmptyMarshalTextPtr OpType = 361
|
||||||
OpStructFieldOmitEmptyMarshalTextPtr OpType = 362
|
OpStructEndMarshalTextPtr OpType = 362
|
||||||
OpStructEndMarshalTextPtr OpType = 363
|
OpStructEndOmitEmptyMarshalTextPtr OpType = 363
|
||||||
OpStructEndOmitEmptyMarshalTextPtr OpType = 364
|
OpStructFieldInterfacePtr OpType = 364
|
||||||
OpStructFieldInterfacePtr OpType = 365
|
OpStructFieldOmitEmptyInterfacePtr OpType = 365
|
||||||
OpStructFieldOmitEmptyInterfacePtr OpType = 366
|
OpStructEndInterfacePtr OpType = 366
|
||||||
OpStructEndInterfacePtr OpType = 367
|
OpStructEndOmitEmptyInterfacePtr OpType = 367
|
||||||
OpStructEndOmitEmptyInterfacePtr OpType = 368
|
OpStructFieldIntPtrString OpType = 368
|
||||||
OpStructFieldIntPtrString OpType = 369
|
OpStructFieldOmitEmptyIntPtrString OpType = 369
|
||||||
OpStructFieldOmitEmptyIntPtrString OpType = 370
|
OpStructEndIntPtrString OpType = 370
|
||||||
OpStructEndIntPtrString OpType = 371
|
OpStructEndOmitEmptyIntPtrString OpType = 371
|
||||||
OpStructEndOmitEmptyIntPtrString OpType = 372
|
OpStructFieldUintPtrString OpType = 372
|
||||||
OpStructFieldUintPtrString OpType = 373
|
OpStructFieldOmitEmptyUintPtrString OpType = 373
|
||||||
OpStructFieldOmitEmptyUintPtrString OpType = 374
|
OpStructEndUintPtrString OpType = 374
|
||||||
OpStructEndUintPtrString OpType = 375
|
OpStructEndOmitEmptyUintPtrString OpType = 375
|
||||||
OpStructEndOmitEmptyUintPtrString OpType = 376
|
OpStructFieldFloat32PtrString OpType = 376
|
||||||
OpStructFieldFloat32PtrString OpType = 377
|
OpStructFieldOmitEmptyFloat32PtrString OpType = 377
|
||||||
OpStructFieldOmitEmptyFloat32PtrString OpType = 378
|
OpStructEndFloat32PtrString OpType = 378
|
||||||
OpStructEndFloat32PtrString OpType = 379
|
OpStructEndOmitEmptyFloat32PtrString OpType = 379
|
||||||
OpStructEndOmitEmptyFloat32PtrString OpType = 380
|
OpStructFieldFloat64PtrString OpType = 380
|
||||||
OpStructFieldFloat64PtrString OpType = 381
|
OpStructFieldOmitEmptyFloat64PtrString OpType = 381
|
||||||
OpStructFieldOmitEmptyFloat64PtrString OpType = 382
|
OpStructEndFloat64PtrString OpType = 382
|
||||||
OpStructEndFloat64PtrString OpType = 383
|
OpStructEndOmitEmptyFloat64PtrString OpType = 383
|
||||||
OpStructEndOmitEmptyFloat64PtrString OpType = 384
|
OpStructFieldBoolPtrString OpType = 384
|
||||||
OpStructFieldBoolPtrString OpType = 385
|
OpStructFieldOmitEmptyBoolPtrString OpType = 385
|
||||||
OpStructFieldOmitEmptyBoolPtrString OpType = 386
|
OpStructEndBoolPtrString OpType = 386
|
||||||
OpStructEndBoolPtrString OpType = 387
|
OpStructEndOmitEmptyBoolPtrString OpType = 387
|
||||||
OpStructEndOmitEmptyBoolPtrString OpType = 388
|
OpStructFieldStringPtrString OpType = 388
|
||||||
OpStructFieldStringPtrString OpType = 389
|
OpStructFieldOmitEmptyStringPtrString OpType = 389
|
||||||
OpStructFieldOmitEmptyStringPtrString OpType = 390
|
OpStructEndStringPtrString OpType = 390
|
||||||
OpStructEndStringPtrString OpType = 391
|
OpStructEndOmitEmptyStringPtrString OpType = 391
|
||||||
OpStructEndOmitEmptyStringPtrString OpType = 392
|
OpStructFieldNumberPtrString OpType = 392
|
||||||
OpStructFieldNumberPtrString OpType = 393
|
OpStructFieldOmitEmptyNumberPtrString OpType = 393
|
||||||
OpStructFieldOmitEmptyNumberPtrString OpType = 394
|
OpStructEndNumberPtrString OpType = 394
|
||||||
OpStructEndNumberPtrString OpType = 395
|
OpStructEndOmitEmptyNumberPtrString OpType = 395
|
||||||
OpStructEndOmitEmptyNumberPtrString OpType = 396
|
OpStructField OpType = 396
|
||||||
OpStructField OpType = 397
|
OpStructFieldOmitEmpty OpType = 397
|
||||||
OpStructFieldOmitEmpty OpType = 398
|
OpStructEnd OpType = 398
|
||||||
OpStructEnd OpType = 399
|
OpStructEndOmitEmpty OpType = 399
|
||||||
OpStructEndOmitEmpty OpType = 400
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (t OpType) String() string {
|
func (t OpType) String() string {
|
||||||
if int(t) >= 401 {
|
if int(t) >= 400 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return opTypeStrings[int(t)]
|
return opTypeStrings[int(t)]
|
||||||
@ -896,7 +894,7 @@ func (t OpType) HeadToOmitEmptyHead() OpType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t OpType) PtrHeadToHead() OpType {
|
func (t OpType) PtrHeadToHead() OpType {
|
||||||
idx := strings.Index(t.String(), "Ptr")
|
idx := strings.Index(t.String(), "PtrHead")
|
||||||
if idx == -1 {
|
if idx == -1 {
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
135
vendor/github.com/goccy/go-json/internal/encoder/query.go
generated
vendored
Normal file
135
vendor/github.com/goccy/go-json/internal/encoder/query.go
generated
vendored
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
package encoder
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
Marshal func(interface{}) ([]byte, error)
|
||||||
|
Unmarshal func([]byte, interface{}) error
|
||||||
|
)
|
||||||
|
|
||||||
|
type FieldQuery struct {
|
||||||
|
Name string
|
||||||
|
Fields []*FieldQuery
|
||||||
|
hash string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *FieldQuery) Hash() string {
|
||||||
|
if q.hash != "" {
|
||||||
|
return q.hash
|
||||||
|
}
|
||||||
|
b, _ := Marshal(q)
|
||||||
|
q.hash = string(b)
|
||||||
|
return q.hash
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *FieldQuery) MarshalJSON() ([]byte, error) {
|
||||||
|
if q.Name != "" {
|
||||||
|
if len(q.Fields) > 0 {
|
||||||
|
return Marshal(map[string][]*FieldQuery{q.Name: q.Fields})
|
||||||
|
}
|
||||||
|
return Marshal(q.Name)
|
||||||
|
}
|
||||||
|
return Marshal(q.Fields)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *FieldQuery) QueryString() (FieldQueryString, error) {
|
||||||
|
b, err := Marshal(q)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return FieldQueryString(b), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type FieldQueryString string
|
||||||
|
|
||||||
|
func (s FieldQueryString) Build() (*FieldQuery, error) {
|
||||||
|
var query interface{}
|
||||||
|
if err := Unmarshal([]byte(s), &query); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return s.build(reflect.ValueOf(query))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s FieldQueryString) build(v reflect.Value) (*FieldQuery, error) {
|
||||||
|
switch v.Type().Kind() {
|
||||||
|
case reflect.String:
|
||||||
|
return s.buildString(v)
|
||||||
|
case reflect.Map:
|
||||||
|
return s.buildMap(v)
|
||||||
|
case reflect.Slice:
|
||||||
|
return s.buildSlice(v)
|
||||||
|
case reflect.Interface:
|
||||||
|
return s.build(reflect.ValueOf(v.Interface()))
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("failed to build field query")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s FieldQueryString) buildString(v reflect.Value) (*FieldQuery, error) {
|
||||||
|
b := []byte(v.String())
|
||||||
|
switch b[0] {
|
||||||
|
case '[', '{':
|
||||||
|
var query interface{}
|
||||||
|
if err := Unmarshal(b, &query); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if str, ok := query.(string); ok {
|
||||||
|
return &FieldQuery{Name: str}, nil
|
||||||
|
}
|
||||||
|
return s.build(reflect.ValueOf(query))
|
||||||
|
}
|
||||||
|
return &FieldQuery{Name: string(b)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s FieldQueryString) buildSlice(v reflect.Value) (*FieldQuery, error) {
|
||||||
|
fields := make([]*FieldQuery, 0, v.Len())
|
||||||
|
for i := 0; i < v.Len(); i++ {
|
||||||
|
def, err := s.build(v.Index(i))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
fields = append(fields, def)
|
||||||
|
}
|
||||||
|
return &FieldQuery{Fields: fields}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s FieldQueryString) buildMap(v reflect.Value) (*FieldQuery, error) {
|
||||||
|
keys := v.MapKeys()
|
||||||
|
if len(keys) != 1 {
|
||||||
|
return nil, fmt.Errorf("failed to build field query object")
|
||||||
|
}
|
||||||
|
key := keys[0]
|
||||||
|
if key.Type().Kind() != reflect.String {
|
||||||
|
return nil, fmt.Errorf("failed to build field query. invalid object key type")
|
||||||
|
}
|
||||||
|
name := key.String()
|
||||||
|
def, err := s.build(v.MapIndex(key))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &FieldQuery{
|
||||||
|
Name: name,
|
||||||
|
Fields: def.Fields,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type queryKey struct{}
|
||||||
|
|
||||||
|
func FieldQueryFromContext(ctx context.Context) *FieldQuery {
|
||||||
|
query := ctx.Value(queryKey{})
|
||||||
|
if query == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
q, ok := query.(*FieldQuery)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetFieldQueryToContext(ctx context.Context, query *FieldQuery) context.Context {
|
||||||
|
return context.WithValue(ctx, queryKey{}, query)
|
||||||
|
}
|
717
vendor/github.com/goccy/go-json/internal/encoder/string.go
generated
vendored
717
vendor/github.com/goccy/go-json/internal/encoder/string.go
generated
vendored
@ -3,7 +3,6 @@ package encoder
|
|||||||
import (
|
import (
|
||||||
"math/bits"
|
"math/bits"
|
||||||
"reflect"
|
"reflect"
|
||||||
"unicode/utf8"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -12,390 +11,8 @@ const (
|
|||||||
msb = 0x8080808080808080
|
msb = 0x8080808080808080
|
||||||
)
|
)
|
||||||
|
|
||||||
var needEscapeWithHTML = [256]bool{
|
|
||||||
'"': true,
|
|
||||||
'&': true,
|
|
||||||
'<': true,
|
|
||||||
'>': true,
|
|
||||||
'\\': true,
|
|
||||||
0x00: true,
|
|
||||||
0x01: true,
|
|
||||||
0x02: true,
|
|
||||||
0x03: true,
|
|
||||||
0x04: true,
|
|
||||||
0x05: true,
|
|
||||||
0x06: true,
|
|
||||||
0x07: true,
|
|
||||||
0x08: true,
|
|
||||||
0x09: true,
|
|
||||||
0x0a: true,
|
|
||||||
0x0b: true,
|
|
||||||
0x0c: true,
|
|
||||||
0x0d: true,
|
|
||||||
0x0e: true,
|
|
||||||
0x0f: true,
|
|
||||||
0x10: true,
|
|
||||||
0x11: true,
|
|
||||||
0x12: true,
|
|
||||||
0x13: true,
|
|
||||||
0x14: true,
|
|
||||||
0x15: true,
|
|
||||||
0x16: true,
|
|
||||||
0x17: true,
|
|
||||||
0x18: true,
|
|
||||||
0x19: true,
|
|
||||||
0x1a: true,
|
|
||||||
0x1b: true,
|
|
||||||
0x1c: true,
|
|
||||||
0x1d: true,
|
|
||||||
0x1e: true,
|
|
||||||
0x1f: true,
|
|
||||||
/* 0x20 - 0x7f */
|
|
||||||
0x80: true,
|
|
||||||
0x81: true,
|
|
||||||
0x82: true,
|
|
||||||
0x83: true,
|
|
||||||
0x84: true,
|
|
||||||
0x85: true,
|
|
||||||
0x86: true,
|
|
||||||
0x87: true,
|
|
||||||
0x88: true,
|
|
||||||
0x89: true,
|
|
||||||
0x8a: true,
|
|
||||||
0x8b: true,
|
|
||||||
0x8c: true,
|
|
||||||
0x8d: true,
|
|
||||||
0x8e: true,
|
|
||||||
0x8f: true,
|
|
||||||
0x90: true,
|
|
||||||
0x91: true,
|
|
||||||
0x92: true,
|
|
||||||
0x93: true,
|
|
||||||
0x94: true,
|
|
||||||
0x95: true,
|
|
||||||
0x96: true,
|
|
||||||
0x97: true,
|
|
||||||
0x98: true,
|
|
||||||
0x99: true,
|
|
||||||
0x9a: true,
|
|
||||||
0x9b: true,
|
|
||||||
0x9c: true,
|
|
||||||
0x9d: true,
|
|
||||||
0x9e: true,
|
|
||||||
0x9f: true,
|
|
||||||
0xa0: true,
|
|
||||||
0xa1: true,
|
|
||||||
0xa2: true,
|
|
||||||
0xa3: true,
|
|
||||||
0xa4: true,
|
|
||||||
0xa5: true,
|
|
||||||
0xa6: true,
|
|
||||||
0xa7: true,
|
|
||||||
0xa8: true,
|
|
||||||
0xa9: true,
|
|
||||||
0xaa: true,
|
|
||||||
0xab: true,
|
|
||||||
0xac: true,
|
|
||||||
0xad: true,
|
|
||||||
0xae: true,
|
|
||||||
0xaf: true,
|
|
||||||
0xb0: true,
|
|
||||||
0xb1: true,
|
|
||||||
0xb2: true,
|
|
||||||
0xb3: true,
|
|
||||||
0xb4: true,
|
|
||||||
0xb5: true,
|
|
||||||
0xb6: true,
|
|
||||||
0xb7: true,
|
|
||||||
0xb8: true,
|
|
||||||
0xb9: true,
|
|
||||||
0xba: true,
|
|
||||||
0xbb: true,
|
|
||||||
0xbc: true,
|
|
||||||
0xbd: true,
|
|
||||||
0xbe: true,
|
|
||||||
0xbf: true,
|
|
||||||
0xc0: true,
|
|
||||||
0xc1: true,
|
|
||||||
0xc2: true,
|
|
||||||
0xc3: true,
|
|
||||||
0xc4: true,
|
|
||||||
0xc5: true,
|
|
||||||
0xc6: true,
|
|
||||||
0xc7: true,
|
|
||||||
0xc8: true,
|
|
||||||
0xc9: true,
|
|
||||||
0xca: true,
|
|
||||||
0xcb: true,
|
|
||||||
0xcc: true,
|
|
||||||
0xcd: true,
|
|
||||||
0xce: true,
|
|
||||||
0xcf: true,
|
|
||||||
0xd0: true,
|
|
||||||
0xd1: true,
|
|
||||||
0xd2: true,
|
|
||||||
0xd3: true,
|
|
||||||
0xd4: true,
|
|
||||||
0xd5: true,
|
|
||||||
0xd6: true,
|
|
||||||
0xd7: true,
|
|
||||||
0xd8: true,
|
|
||||||
0xd9: true,
|
|
||||||
0xda: true,
|
|
||||||
0xdb: true,
|
|
||||||
0xdc: true,
|
|
||||||
0xdd: true,
|
|
||||||
0xde: true,
|
|
||||||
0xdf: true,
|
|
||||||
0xe0: true,
|
|
||||||
0xe1: true,
|
|
||||||
0xe2: true,
|
|
||||||
0xe3: true,
|
|
||||||
0xe4: true,
|
|
||||||
0xe5: true,
|
|
||||||
0xe6: true,
|
|
||||||
0xe7: true,
|
|
||||||
0xe8: true,
|
|
||||||
0xe9: true,
|
|
||||||
0xea: true,
|
|
||||||
0xeb: true,
|
|
||||||
0xec: true,
|
|
||||||
0xed: true,
|
|
||||||
0xee: true,
|
|
||||||
0xef: true,
|
|
||||||
0xf0: true,
|
|
||||||
0xf1: true,
|
|
||||||
0xf2: true,
|
|
||||||
0xf3: true,
|
|
||||||
0xf4: true,
|
|
||||||
0xf5: true,
|
|
||||||
0xf6: true,
|
|
||||||
0xf7: true,
|
|
||||||
0xf8: true,
|
|
||||||
0xf9: true,
|
|
||||||
0xfa: true,
|
|
||||||
0xfb: true,
|
|
||||||
0xfc: true,
|
|
||||||
0xfd: true,
|
|
||||||
0xfe: true,
|
|
||||||
0xff: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
var needEscape = [256]bool{
|
|
||||||
'"': true,
|
|
||||||
'\\': true,
|
|
||||||
0x00: true,
|
|
||||||
0x01: true,
|
|
||||||
0x02: true,
|
|
||||||
0x03: true,
|
|
||||||
0x04: true,
|
|
||||||
0x05: true,
|
|
||||||
0x06: true,
|
|
||||||
0x07: true,
|
|
||||||
0x08: true,
|
|
||||||
0x09: true,
|
|
||||||
0x0a: true,
|
|
||||||
0x0b: true,
|
|
||||||
0x0c: true,
|
|
||||||
0x0d: true,
|
|
||||||
0x0e: true,
|
|
||||||
0x0f: true,
|
|
||||||
0x10: true,
|
|
||||||
0x11: true,
|
|
||||||
0x12: true,
|
|
||||||
0x13: true,
|
|
||||||
0x14: true,
|
|
||||||
0x15: true,
|
|
||||||
0x16: true,
|
|
||||||
0x17: true,
|
|
||||||
0x18: true,
|
|
||||||
0x19: true,
|
|
||||||
0x1a: true,
|
|
||||||
0x1b: true,
|
|
||||||
0x1c: true,
|
|
||||||
0x1d: true,
|
|
||||||
0x1e: true,
|
|
||||||
0x1f: true,
|
|
||||||
/* 0x20 - 0x7f */
|
|
||||||
0x80: true,
|
|
||||||
0x81: true,
|
|
||||||
0x82: true,
|
|
||||||
0x83: true,
|
|
||||||
0x84: true,
|
|
||||||
0x85: true,
|
|
||||||
0x86: true,
|
|
||||||
0x87: true,
|
|
||||||
0x88: true,
|
|
||||||
0x89: true,
|
|
||||||
0x8a: true,
|
|
||||||
0x8b: true,
|
|
||||||
0x8c: true,
|
|
||||||
0x8d: true,
|
|
||||||
0x8e: true,
|
|
||||||
0x8f: true,
|
|
||||||
0x90: true,
|
|
||||||
0x91: true,
|
|
||||||
0x92: true,
|
|
||||||
0x93: true,
|
|
||||||
0x94: true,
|
|
||||||
0x95: true,
|
|
||||||
0x96: true,
|
|
||||||
0x97: true,
|
|
||||||
0x98: true,
|
|
||||||
0x99: true,
|
|
||||||
0x9a: true,
|
|
||||||
0x9b: true,
|
|
||||||
0x9c: true,
|
|
||||||
0x9d: true,
|
|
||||||
0x9e: true,
|
|
||||||
0x9f: true,
|
|
||||||
0xa0: true,
|
|
||||||
0xa1: true,
|
|
||||||
0xa2: true,
|
|
||||||
0xa3: true,
|
|
||||||
0xa4: true,
|
|
||||||
0xa5: true,
|
|
||||||
0xa6: true,
|
|
||||||
0xa7: true,
|
|
||||||
0xa8: true,
|
|
||||||
0xa9: true,
|
|
||||||
0xaa: true,
|
|
||||||
0xab: true,
|
|
||||||
0xac: true,
|
|
||||||
0xad: true,
|
|
||||||
0xae: true,
|
|
||||||
0xaf: true,
|
|
||||||
0xb0: true,
|
|
||||||
0xb1: true,
|
|
||||||
0xb2: true,
|
|
||||||
0xb3: true,
|
|
||||||
0xb4: true,
|
|
||||||
0xb5: true,
|
|
||||||
0xb6: true,
|
|
||||||
0xb7: true,
|
|
||||||
0xb8: true,
|
|
||||||
0xb9: true,
|
|
||||||
0xba: true,
|
|
||||||
0xbb: true,
|
|
||||||
0xbc: true,
|
|
||||||
0xbd: true,
|
|
||||||
0xbe: true,
|
|
||||||
0xbf: true,
|
|
||||||
0xc0: true,
|
|
||||||
0xc1: true,
|
|
||||||
0xc2: true,
|
|
||||||
0xc3: true,
|
|
||||||
0xc4: true,
|
|
||||||
0xc5: true,
|
|
||||||
0xc6: true,
|
|
||||||
0xc7: true,
|
|
||||||
0xc8: true,
|
|
||||||
0xc9: true,
|
|
||||||
0xca: true,
|
|
||||||
0xcb: true,
|
|
||||||
0xcc: true,
|
|
||||||
0xcd: true,
|
|
||||||
0xce: true,
|
|
||||||
0xcf: true,
|
|
||||||
0xd0: true,
|
|
||||||
0xd1: true,
|
|
||||||
0xd2: true,
|
|
||||||
0xd3: true,
|
|
||||||
0xd4: true,
|
|
||||||
0xd5: true,
|
|
||||||
0xd6: true,
|
|
||||||
0xd7: true,
|
|
||||||
0xd8: true,
|
|
||||||
0xd9: true,
|
|
||||||
0xda: true,
|
|
||||||
0xdb: true,
|
|
||||||
0xdc: true,
|
|
||||||
0xdd: true,
|
|
||||||
0xde: true,
|
|
||||||
0xdf: true,
|
|
||||||
0xe0: true,
|
|
||||||
0xe1: true,
|
|
||||||
0xe2: true,
|
|
||||||
0xe3: true,
|
|
||||||
0xe4: true,
|
|
||||||
0xe5: true,
|
|
||||||
0xe6: true,
|
|
||||||
0xe7: true,
|
|
||||||
0xe8: true,
|
|
||||||
0xe9: true,
|
|
||||||
0xea: true,
|
|
||||||
0xeb: true,
|
|
||||||
0xec: true,
|
|
||||||
0xed: true,
|
|
||||||
0xee: true,
|
|
||||||
0xef: true,
|
|
||||||
0xf0: true,
|
|
||||||
0xf1: true,
|
|
||||||
0xf2: true,
|
|
||||||
0xf3: true,
|
|
||||||
0xf4: true,
|
|
||||||
0xf5: true,
|
|
||||||
0xf6: true,
|
|
||||||
0xf7: true,
|
|
||||||
0xf8: true,
|
|
||||||
0xf9: true,
|
|
||||||
0xfa: true,
|
|
||||||
0xfb: true,
|
|
||||||
0xfc: true,
|
|
||||||
0xfd: true,
|
|
||||||
0xfe: true,
|
|
||||||
0xff: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
var hex = "0123456789abcdef"
|
var hex = "0123456789abcdef"
|
||||||
|
|
||||||
// escapeIndex finds the index of the first char in `s` that requires escaping.
|
|
||||||
// A char requires escaping if it's outside of the range of [0x20, 0x7F] or if
|
|
||||||
// it includes a double quote or backslash.
|
|
||||||
// If no chars in `s` require escaping, the return value is -1.
|
|
||||||
func escapeIndex(s string) int {
|
|
||||||
chunks := stringToUint64Slice(s)
|
|
||||||
for _, n := range chunks {
|
|
||||||
// combine masks before checking for the MSB of each byte. We include
|
|
||||||
// `n` in the mask to check whether any of the *input* byte MSBs were
|
|
||||||
// set (i.e. the byte was outside the ASCII range).
|
|
||||||
mask := n | below(n, 0x20) | contains(n, '"') | contains(n, '\\')
|
|
||||||
if (mask & msb) != 0 {
|
|
||||||
return bits.TrailingZeros64(mask&msb) / 8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
valLen := len(s)
|
|
||||||
for i := len(chunks) * 8; i < valLen; i++ {
|
|
||||||
if needEscape[s[i]] {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
// below return a mask that can be used to determine if any of the bytes
|
|
||||||
// in `n` are below `b`. If a byte's MSB is set in the mask then that byte was
|
|
||||||
// below `b`. The result is only valid if `b`, and each byte in `n`, is below
|
|
||||||
// 0x80.
|
|
||||||
func below(n uint64, b byte) uint64 {
|
|
||||||
return n - expand(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// contains returns a mask that can be used to determine if any of the
|
|
||||||
// bytes in `n` are equal to `b`. If a byte's MSB is set in the mask then
|
|
||||||
// that byte is equal to `b`. The result is only valid if `b`, and each
|
|
||||||
// byte in `n`, is below 0x80.
|
|
||||||
func contains(n uint64, b byte) uint64 {
|
|
||||||
return (n ^ expand(b)) - lsb
|
|
||||||
}
|
|
||||||
|
|
||||||
// expand puts the specified byte into each of the 8 bytes of a uint64.
|
|
||||||
func expand(b byte) uint64 {
|
|
||||||
return lsb * uint64(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
//nolint:govet
|
//nolint:govet
|
||||||
func stringToUint64Slice(s string) []uint64 {
|
func stringToUint64Slice(s string) []uint64 {
|
||||||
return *(*[]uint64)(unsafe.Pointer(&reflect.SliceHeader{
|
return *(*[]uint64)(unsafe.Pointer(&reflect.SliceHeader{
|
||||||
@ -406,9 +23,19 @@ func stringToUint64Slice(s string) []uint64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func AppendString(ctx *RuntimeContext, buf []byte, s string) []byte {
|
func AppendString(ctx *RuntimeContext, buf []byte, s string) []byte {
|
||||||
if ctx.Option.Flag&HTMLEscapeOption == 0 {
|
if ctx.Option.Flag&HTMLEscapeOption != 0 {
|
||||||
|
if ctx.Option.Flag&NormalizeUTF8Option != 0 {
|
||||||
|
return appendNormalizedHTMLString(buf, s)
|
||||||
|
}
|
||||||
|
return appendHTMLString(buf, s)
|
||||||
|
}
|
||||||
|
if ctx.Option.Flag&NormalizeUTF8Option != 0 {
|
||||||
|
return appendNormalizedString(buf, s)
|
||||||
|
}
|
||||||
return appendString(buf, s)
|
return appendString(buf, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func appendNormalizedHTMLString(buf []byte, s string) []byte {
|
||||||
valLen := len(s)
|
valLen := len(s)
|
||||||
if valLen == 0 {
|
if valLen == 0 {
|
||||||
return append(buf, `""`...)
|
return append(buf, `""`...)
|
||||||
@ -435,7 +62,7 @@ func AppendString(ctx *RuntimeContext, buf []byte, s string) []byte {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := len(chunks) * 8; i < valLen; i++ {
|
for i := len(chunks) * 8; i < valLen; i++ {
|
||||||
if needEscapeWithHTML[s[i]] {
|
if needEscapeHTMLNormalizeUTF8[s[i]] {
|
||||||
j = i
|
j = i
|
||||||
goto ESCAPE_END
|
goto ESCAPE_END
|
||||||
}
|
}
|
||||||
@ -447,7 +74,7 @@ ESCAPE_END:
|
|||||||
for j < valLen {
|
for j < valLen {
|
||||||
c := s[j]
|
c := s[j]
|
||||||
|
|
||||||
if !needEscapeWithHTML[c] {
|
if !needEscapeHTMLNormalizeUTF8[c] {
|
||||||
// fast path: most of the time, printable ascii characters are used
|
// fast path: most of the time, printable ascii characters are used
|
||||||
j++
|
j++
|
||||||
continue
|
continue
|
||||||
@ -489,10 +116,220 @@ ESCAPE_END:
|
|||||||
i = j + 1
|
i = j + 1
|
||||||
j = j + 1
|
j = j + 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
case 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, // 0x00-0x0F
|
||||||
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F: // 0x10-0x1F
|
||||||
|
buf = append(buf, s[i:j]...)
|
||||||
|
buf = append(buf, `\u00`...)
|
||||||
|
buf = append(buf, hex[c>>4], hex[c&0xF])
|
||||||
|
i = j + 1
|
||||||
|
j = j + 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
state, size := decodeRuneInString(s[j:])
|
||||||
|
switch state {
|
||||||
|
case runeErrorState:
|
||||||
|
buf = append(buf, s[i:j]...)
|
||||||
|
buf = append(buf, `\ufffd`...)
|
||||||
|
i = j + 1
|
||||||
|
j = j + 1
|
||||||
|
continue
|
||||||
|
// U+2028 is LINE SEPARATOR.
|
||||||
|
// U+2029 is PARAGRAPH SEPARATOR.
|
||||||
|
// They are both technically valid characters in JSON strings,
|
||||||
|
// but don't work in JSONP, which has to be evaluated as JavaScript,
|
||||||
|
// and can lead to security holes there. It is valid JSON to
|
||||||
|
// escape them, so we do so unconditionally.
|
||||||
|
// See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
|
||||||
|
case lineSepState:
|
||||||
|
buf = append(buf, s[i:j]...)
|
||||||
|
buf = append(buf, `\u2028`...)
|
||||||
|
i = j + 3
|
||||||
|
j = j + 3
|
||||||
|
continue
|
||||||
|
case paragraphSepState:
|
||||||
|
buf = append(buf, s[i:j]...)
|
||||||
|
buf = append(buf, `\u2029`...)
|
||||||
|
i = j + 3
|
||||||
|
j = j + 3
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
j += size
|
||||||
}
|
}
|
||||||
|
|
||||||
// This encodes bytes < 0x20 except for \t, \n and \r.
|
return append(append(buf, s[i:]...), '"')
|
||||||
if c < 0x20 {
|
}
|
||||||
|
|
||||||
|
func appendHTMLString(buf []byte, s string) []byte {
|
||||||
|
valLen := len(s)
|
||||||
|
if valLen == 0 {
|
||||||
|
return append(buf, `""`...)
|
||||||
|
}
|
||||||
|
buf = append(buf, '"')
|
||||||
|
var (
|
||||||
|
i, j int
|
||||||
|
)
|
||||||
|
if valLen >= 8 {
|
||||||
|
chunks := stringToUint64Slice(s)
|
||||||
|
for _, n := range chunks {
|
||||||
|
// combine masks before checking for the MSB of each byte. We include
|
||||||
|
// `n` in the mask to check whether any of the *input* byte MSBs were
|
||||||
|
// set (i.e. the byte was outside the ASCII range).
|
||||||
|
mask := n | (n - (lsb * 0x20)) |
|
||||||
|
((n ^ (lsb * '"')) - lsb) |
|
||||||
|
((n ^ (lsb * '\\')) - lsb) |
|
||||||
|
((n ^ (lsb * '<')) - lsb) |
|
||||||
|
((n ^ (lsb * '>')) - lsb) |
|
||||||
|
((n ^ (lsb * '&')) - lsb)
|
||||||
|
if (mask & msb) != 0 {
|
||||||
|
j = bits.TrailingZeros64(mask&msb) / 8
|
||||||
|
goto ESCAPE_END
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := len(chunks) * 8; i < valLen; i++ {
|
||||||
|
if needEscapeHTML[s[i]] {
|
||||||
|
j = i
|
||||||
|
goto ESCAPE_END
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// no found any escape characters.
|
||||||
|
return append(append(buf, s...), '"')
|
||||||
|
}
|
||||||
|
ESCAPE_END:
|
||||||
|
for j < valLen {
|
||||||
|
c := s[j]
|
||||||
|
|
||||||
|
if !needEscapeHTML[c] {
|
||||||
|
// fast path: most of the time, printable ascii characters are used
|
||||||
|
j++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch c {
|
||||||
|
case '\\', '"':
|
||||||
|
buf = append(buf, s[i:j]...)
|
||||||
|
buf = append(buf, '\\', c)
|
||||||
|
i = j + 1
|
||||||
|
j = j + 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
case '\n':
|
||||||
|
buf = append(buf, s[i:j]...)
|
||||||
|
buf = append(buf, '\\', 'n')
|
||||||
|
i = j + 1
|
||||||
|
j = j + 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
case '\r':
|
||||||
|
buf = append(buf, s[i:j]...)
|
||||||
|
buf = append(buf, '\\', 'r')
|
||||||
|
i = j + 1
|
||||||
|
j = j + 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
case '\t':
|
||||||
|
buf = append(buf, s[i:j]...)
|
||||||
|
buf = append(buf, '\\', 't')
|
||||||
|
i = j + 1
|
||||||
|
j = j + 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
case '<', '>', '&':
|
||||||
|
buf = append(buf, s[i:j]...)
|
||||||
|
buf = append(buf, `\u00`...)
|
||||||
|
buf = append(buf, hex[c>>4], hex[c&0xF])
|
||||||
|
i = j + 1
|
||||||
|
j = j + 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
case 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, // 0x00-0x0F
|
||||||
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F: // 0x10-0x1F
|
||||||
|
buf = append(buf, s[i:j]...)
|
||||||
|
buf = append(buf, `\u00`...)
|
||||||
|
buf = append(buf, hex[c>>4], hex[c&0xF])
|
||||||
|
i = j + 1
|
||||||
|
j = j + 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
|
||||||
|
return append(append(buf, s[i:]...), '"')
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendNormalizedString(buf []byte, s string) []byte {
|
||||||
|
valLen := len(s)
|
||||||
|
if valLen == 0 {
|
||||||
|
return append(buf, `""`...)
|
||||||
|
}
|
||||||
|
buf = append(buf, '"')
|
||||||
|
var (
|
||||||
|
i, j int
|
||||||
|
)
|
||||||
|
if valLen >= 8 {
|
||||||
|
chunks := stringToUint64Slice(s)
|
||||||
|
for _, n := range chunks {
|
||||||
|
// combine masks before checking for the MSB of each byte. We include
|
||||||
|
// `n` in the mask to check whether any of the *input* byte MSBs were
|
||||||
|
// set (i.e. the byte was outside the ASCII range).
|
||||||
|
mask := n | (n - (lsb * 0x20)) |
|
||||||
|
((n ^ (lsb * '"')) - lsb) |
|
||||||
|
((n ^ (lsb * '\\')) - lsb)
|
||||||
|
if (mask & msb) != 0 {
|
||||||
|
j = bits.TrailingZeros64(mask&msb) / 8
|
||||||
|
goto ESCAPE_END
|
||||||
|
}
|
||||||
|
}
|
||||||
|
valLen := len(s)
|
||||||
|
for i := len(chunks) * 8; i < valLen; i++ {
|
||||||
|
if needEscapeNormalizeUTF8[s[i]] {
|
||||||
|
j = i
|
||||||
|
goto ESCAPE_END
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return append(append(buf, s...), '"')
|
||||||
|
}
|
||||||
|
ESCAPE_END:
|
||||||
|
for j < valLen {
|
||||||
|
c := s[j]
|
||||||
|
|
||||||
|
if !needEscapeNormalizeUTF8[c] {
|
||||||
|
// fast path: most of the time, printable ascii characters are used
|
||||||
|
j++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch c {
|
||||||
|
case '\\', '"':
|
||||||
|
buf = append(buf, s[i:j]...)
|
||||||
|
buf = append(buf, '\\', c)
|
||||||
|
i = j + 1
|
||||||
|
j = j + 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
case '\n':
|
||||||
|
buf = append(buf, s[i:j]...)
|
||||||
|
buf = append(buf, '\\', 'n')
|
||||||
|
i = j + 1
|
||||||
|
j = j + 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
case '\r':
|
||||||
|
buf = append(buf, s[i:j]...)
|
||||||
|
buf = append(buf, '\\', 'r')
|
||||||
|
i = j + 1
|
||||||
|
j = j + 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
case '\t':
|
||||||
|
buf = append(buf, s[i:j]...)
|
||||||
|
buf = append(buf, '\\', 't')
|
||||||
|
i = j + 1
|
||||||
|
j = j + 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
case 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, // 0x00-0x0F
|
||||||
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F: // 0x10-0x1F
|
||||||
buf = append(buf, s[i:j]...)
|
buf = append(buf, s[i:j]...)
|
||||||
buf = append(buf, `\u00`...)
|
buf = append(buf, `\u00`...)
|
||||||
buf = append(buf, hex[c>>4], hex[c&0xF])
|
buf = append(buf, hex[c>>4], hex[c&0xF])
|
||||||
@ -501,18 +338,14 @@ ESCAPE_END:
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
r, size := utf8.DecodeRuneInString(s[j:])
|
state, size := decodeRuneInString(s[j:])
|
||||||
|
switch state {
|
||||||
if r == utf8.RuneError && size == 1 {
|
case runeErrorState:
|
||||||
buf = append(buf, s[i:j]...)
|
buf = append(buf, s[i:j]...)
|
||||||
buf = append(buf, `\ufffd`...)
|
buf = append(buf, `\ufffd`...)
|
||||||
i = j + size
|
i = j + 1
|
||||||
j = j + size
|
j = j + 1
|
||||||
continue
|
continue
|
||||||
}
|
|
||||||
|
|
||||||
switch r {
|
|
||||||
case '\u2028', '\u2029':
|
|
||||||
// U+2028 is LINE SEPARATOR.
|
// U+2028 is LINE SEPARATOR.
|
||||||
// U+2029 is PARAGRAPH SEPARATOR.
|
// U+2029 is PARAGRAPH SEPARATOR.
|
||||||
// They are both technically valid characters in JSON strings,
|
// They are both technically valid characters in JSON strings,
|
||||||
@ -520,14 +353,19 @@ ESCAPE_END:
|
|||||||
// and can lead to security holes there. It is valid JSON to
|
// and can lead to security holes there. It is valid JSON to
|
||||||
// escape them, so we do so unconditionally.
|
// escape them, so we do so unconditionally.
|
||||||
// See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
|
// See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
|
||||||
|
case lineSepState:
|
||||||
buf = append(buf, s[i:j]...)
|
buf = append(buf, s[i:j]...)
|
||||||
buf = append(buf, `\u202`...)
|
buf = append(buf, `\u2028`...)
|
||||||
buf = append(buf, hex[r&0xF])
|
i = j + 3
|
||||||
i = j + size
|
j = j + 3
|
||||||
j = j + size
|
continue
|
||||||
|
case paragraphSepState:
|
||||||
|
buf = append(buf, s[i:j]...)
|
||||||
|
buf = append(buf, `\u2029`...)
|
||||||
|
i = j + 3
|
||||||
|
j = j + 3
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
j += size
|
j += size
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -540,19 +378,37 @@ func appendString(buf []byte, s string) []byte {
|
|||||||
return append(buf, `""`...)
|
return append(buf, `""`...)
|
||||||
}
|
}
|
||||||
buf = append(buf, '"')
|
buf = append(buf, '"')
|
||||||
var escapeIdx int
|
var (
|
||||||
|
i, j int
|
||||||
|
)
|
||||||
if valLen >= 8 {
|
if valLen >= 8 {
|
||||||
if escapeIdx = escapeIndex(s); escapeIdx < 0 {
|
chunks := stringToUint64Slice(s)
|
||||||
|
for _, n := range chunks {
|
||||||
|
// combine masks before checking for the MSB of each byte. We include
|
||||||
|
// `n` in the mask to check whether any of the *input* byte MSBs were
|
||||||
|
// set (i.e. the byte was outside the ASCII range).
|
||||||
|
mask := n | (n - (lsb * 0x20)) |
|
||||||
|
((n ^ (lsb * '"')) - lsb) |
|
||||||
|
((n ^ (lsb * '\\')) - lsb)
|
||||||
|
if (mask & msb) != 0 {
|
||||||
|
j = bits.TrailingZeros64(mask&msb) / 8
|
||||||
|
goto ESCAPE_END
|
||||||
|
}
|
||||||
|
}
|
||||||
|
valLen := len(s)
|
||||||
|
for i := len(chunks) * 8; i < valLen; i++ {
|
||||||
|
if needEscape[s[i]] {
|
||||||
|
j = i
|
||||||
|
goto ESCAPE_END
|
||||||
|
}
|
||||||
|
}
|
||||||
return append(append(buf, s...), '"')
|
return append(append(buf, s...), '"')
|
||||||
}
|
}
|
||||||
}
|
ESCAPE_END:
|
||||||
|
|
||||||
i := 0
|
|
||||||
j := escapeIdx
|
|
||||||
for j < valLen {
|
for j < valLen {
|
||||||
c := s[j]
|
c := s[j]
|
||||||
|
|
||||||
if c >= 0x20 && c <= 0x7f && c != '\\' && c != '"' {
|
if !needEscape[c] {
|
||||||
// fast path: most of the time, printable ascii characters are used
|
// fast path: most of the time, printable ascii characters are used
|
||||||
j++
|
j++
|
||||||
continue
|
continue
|
||||||
@ -587,7 +443,8 @@ func appendString(buf []byte, s string) []byte {
|
|||||||
j = j + 1
|
j = j + 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case '<', '>', '&':
|
case 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, // 0x00-0x0F
|
||||||
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F: // 0x10-0x1F
|
||||||
buf = append(buf, s[i:j]...)
|
buf = append(buf, s[i:j]...)
|
||||||
buf = append(buf, `\u00`...)
|
buf = append(buf, `\u00`...)
|
||||||
buf = append(buf, hex[c>>4], hex[c&0xF])
|
buf = append(buf, hex[c>>4], hex[c&0xF])
|
||||||
@ -595,45 +452,7 @@ func appendString(buf []byte, s string) []byte {
|
|||||||
j = j + 1
|
j = j + 1
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
j++
|
||||||
// This encodes bytes < 0x20 except for \t, \n and \r.
|
|
||||||
if c < 0x20 {
|
|
||||||
buf = append(buf, s[i:j]...)
|
|
||||||
buf = append(buf, `\u00`...)
|
|
||||||
buf = append(buf, hex[c>>4], hex[c&0xF])
|
|
||||||
i = j + 1
|
|
||||||
j = j + 1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
r, size := utf8.DecodeRuneInString(s[j:])
|
|
||||||
|
|
||||||
if r == utf8.RuneError && size == 1 {
|
|
||||||
buf = append(buf, s[i:j]...)
|
|
||||||
buf = append(buf, `\ufffd`...)
|
|
||||||
i = j + size
|
|
||||||
j = j + size
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch r {
|
|
||||||
case '\u2028', '\u2029':
|
|
||||||
// U+2028 is LINE SEPARATOR.
|
|
||||||
// U+2029 is PARAGRAPH SEPARATOR.
|
|
||||||
// They are both technically valid characters in JSON strings,
|
|
||||||
// but don't work in JSONP, which has to be evaluated as JavaScript,
|
|
||||||
// and can lead to security holes there. It is valid JSON to
|
|
||||||
// escape them, so we do so unconditionally.
|
|
||||||
// See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
|
|
||||||
buf = append(buf, s[i:j]...)
|
|
||||||
buf = append(buf, `\u202`...)
|
|
||||||
buf = append(buf, hex[r&0xF])
|
|
||||||
i = j + size
|
|
||||||
j = j + size
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
j += size
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return append(append(buf, s[i:]...), '"')
|
return append(append(buf, s[i:]...), '"')
|
||||||
|
415
vendor/github.com/goccy/go-json/internal/encoder/string_table.go
generated
vendored
Normal file
415
vendor/github.com/goccy/go-json/internal/encoder/string_table.go
generated
vendored
Normal file
@ -0,0 +1,415 @@
|
|||||||
|
package encoder
|
||||||
|
|
||||||
|
var needEscapeHTMLNormalizeUTF8 = [256]bool{
|
||||||
|
'"': true,
|
||||||
|
'&': true,
|
||||||
|
'<': true,
|
||||||
|
'>': true,
|
||||||
|
'\\': true,
|
||||||
|
0x00: true,
|
||||||
|
0x01: true,
|
||||||
|
0x02: true,
|
||||||
|
0x03: true,
|
||||||
|
0x04: true,
|
||||||
|
0x05: true,
|
||||||
|
0x06: true,
|
||||||
|
0x07: true,
|
||||||
|
0x08: true,
|
||||||
|
0x09: true,
|
||||||
|
0x0a: true,
|
||||||
|
0x0b: true,
|
||||||
|
0x0c: true,
|
||||||
|
0x0d: true,
|
||||||
|
0x0e: true,
|
||||||
|
0x0f: true,
|
||||||
|
0x10: true,
|
||||||
|
0x11: true,
|
||||||
|
0x12: true,
|
||||||
|
0x13: true,
|
||||||
|
0x14: true,
|
||||||
|
0x15: true,
|
||||||
|
0x16: true,
|
||||||
|
0x17: true,
|
||||||
|
0x18: true,
|
||||||
|
0x19: true,
|
||||||
|
0x1a: true,
|
||||||
|
0x1b: true,
|
||||||
|
0x1c: true,
|
||||||
|
0x1d: true,
|
||||||
|
0x1e: true,
|
||||||
|
0x1f: true,
|
||||||
|
/* 0x20 - 0x7f */
|
||||||
|
0x80: true,
|
||||||
|
0x81: true,
|
||||||
|
0x82: true,
|
||||||
|
0x83: true,
|
||||||
|
0x84: true,
|
||||||
|
0x85: true,
|
||||||
|
0x86: true,
|
||||||
|
0x87: true,
|
||||||
|
0x88: true,
|
||||||
|
0x89: true,
|
||||||
|
0x8a: true,
|
||||||
|
0x8b: true,
|
||||||
|
0x8c: true,
|
||||||
|
0x8d: true,
|
||||||
|
0x8e: true,
|
||||||
|
0x8f: true,
|
||||||
|
0x90: true,
|
||||||
|
0x91: true,
|
||||||
|
0x92: true,
|
||||||
|
0x93: true,
|
||||||
|
0x94: true,
|
||||||
|
0x95: true,
|
||||||
|
0x96: true,
|
||||||
|
0x97: true,
|
||||||
|
0x98: true,
|
||||||
|
0x99: true,
|
||||||
|
0x9a: true,
|
||||||
|
0x9b: true,
|
||||||
|
0x9c: true,
|
||||||
|
0x9d: true,
|
||||||
|
0x9e: true,
|
||||||
|
0x9f: true,
|
||||||
|
0xa0: true,
|
||||||
|
0xa1: true,
|
||||||
|
0xa2: true,
|
||||||
|
0xa3: true,
|
||||||
|
0xa4: true,
|
||||||
|
0xa5: true,
|
||||||
|
0xa6: true,
|
||||||
|
0xa7: true,
|
||||||
|
0xa8: true,
|
||||||
|
0xa9: true,
|
||||||
|
0xaa: true,
|
||||||
|
0xab: true,
|
||||||
|
0xac: true,
|
||||||
|
0xad: true,
|
||||||
|
0xae: true,
|
||||||
|
0xaf: true,
|
||||||
|
0xb0: true,
|
||||||
|
0xb1: true,
|
||||||
|
0xb2: true,
|
||||||
|
0xb3: true,
|
||||||
|
0xb4: true,
|
||||||
|
0xb5: true,
|
||||||
|
0xb6: true,
|
||||||
|
0xb7: true,
|
||||||
|
0xb8: true,
|
||||||
|
0xb9: true,
|
||||||
|
0xba: true,
|
||||||
|
0xbb: true,
|
||||||
|
0xbc: true,
|
||||||
|
0xbd: true,
|
||||||
|
0xbe: true,
|
||||||
|
0xbf: true,
|
||||||
|
0xc0: true,
|
||||||
|
0xc1: true,
|
||||||
|
0xc2: true,
|
||||||
|
0xc3: true,
|
||||||
|
0xc4: true,
|
||||||
|
0xc5: true,
|
||||||
|
0xc6: true,
|
||||||
|
0xc7: true,
|
||||||
|
0xc8: true,
|
||||||
|
0xc9: true,
|
||||||
|
0xca: true,
|
||||||
|
0xcb: true,
|
||||||
|
0xcc: true,
|
||||||
|
0xcd: true,
|
||||||
|
0xce: true,
|
||||||
|
0xcf: true,
|
||||||
|
0xd0: true,
|
||||||
|
0xd1: true,
|
||||||
|
0xd2: true,
|
||||||
|
0xd3: true,
|
||||||
|
0xd4: true,
|
||||||
|
0xd5: true,
|
||||||
|
0xd6: true,
|
||||||
|
0xd7: true,
|
||||||
|
0xd8: true,
|
||||||
|
0xd9: true,
|
||||||
|
0xda: true,
|
||||||
|
0xdb: true,
|
||||||
|
0xdc: true,
|
||||||
|
0xdd: true,
|
||||||
|
0xde: true,
|
||||||
|
0xdf: true,
|
||||||
|
0xe0: true,
|
||||||
|
0xe1: true,
|
||||||
|
0xe2: true,
|
||||||
|
0xe3: true,
|
||||||
|
0xe4: true,
|
||||||
|
0xe5: true,
|
||||||
|
0xe6: true,
|
||||||
|
0xe7: true,
|
||||||
|
0xe8: true,
|
||||||
|
0xe9: true,
|
||||||
|
0xea: true,
|
||||||
|
0xeb: true,
|
||||||
|
0xec: true,
|
||||||
|
0xed: true,
|
||||||
|
0xee: true,
|
||||||
|
0xef: true,
|
||||||
|
0xf0: true,
|
||||||
|
0xf1: true,
|
||||||
|
0xf2: true,
|
||||||
|
0xf3: true,
|
||||||
|
0xf4: true,
|
||||||
|
0xf5: true,
|
||||||
|
0xf6: true,
|
||||||
|
0xf7: true,
|
||||||
|
0xf8: true,
|
||||||
|
0xf9: true,
|
||||||
|
0xfa: true,
|
||||||
|
0xfb: true,
|
||||||
|
0xfc: true,
|
||||||
|
0xfd: true,
|
||||||
|
0xfe: true,
|
||||||
|
0xff: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
var needEscapeNormalizeUTF8 = [256]bool{
|
||||||
|
'"': true,
|
||||||
|
'\\': true,
|
||||||
|
0x00: true,
|
||||||
|
0x01: true,
|
||||||
|
0x02: true,
|
||||||
|
0x03: true,
|
||||||
|
0x04: true,
|
||||||
|
0x05: true,
|
||||||
|
0x06: true,
|
||||||
|
0x07: true,
|
||||||
|
0x08: true,
|
||||||
|
0x09: true,
|
||||||
|
0x0a: true,
|
||||||
|
0x0b: true,
|
||||||
|
0x0c: true,
|
||||||
|
0x0d: true,
|
||||||
|
0x0e: true,
|
||||||
|
0x0f: true,
|
||||||
|
0x10: true,
|
||||||
|
0x11: true,
|
||||||
|
0x12: true,
|
||||||
|
0x13: true,
|
||||||
|
0x14: true,
|
||||||
|
0x15: true,
|
||||||
|
0x16: true,
|
||||||
|
0x17: true,
|
||||||
|
0x18: true,
|
||||||
|
0x19: true,
|
||||||
|
0x1a: true,
|
||||||
|
0x1b: true,
|
||||||
|
0x1c: true,
|
||||||
|
0x1d: true,
|
||||||
|
0x1e: true,
|
||||||
|
0x1f: true,
|
||||||
|
/* 0x20 - 0x7f */
|
||||||
|
0x80: true,
|
||||||
|
0x81: true,
|
||||||
|
0x82: true,
|
||||||
|
0x83: true,
|
||||||
|
0x84: true,
|
||||||
|
0x85: true,
|
||||||
|
0x86: true,
|
||||||
|
0x87: true,
|
||||||
|
0x88: true,
|
||||||
|
0x89: true,
|
||||||
|
0x8a: true,
|
||||||
|
0x8b: true,
|
||||||
|
0x8c: true,
|
||||||
|
0x8d: true,
|
||||||
|
0x8e: true,
|
||||||
|
0x8f: true,
|
||||||
|
0x90: true,
|
||||||
|
0x91: true,
|
||||||
|
0x92: true,
|
||||||
|
0x93: true,
|
||||||
|
0x94: true,
|
||||||
|
0x95: true,
|
||||||
|
0x96: true,
|
||||||
|
0x97: true,
|
||||||
|
0x98: true,
|
||||||
|
0x99: true,
|
||||||
|
0x9a: true,
|
||||||
|
0x9b: true,
|
||||||
|
0x9c: true,
|
||||||
|
0x9d: true,
|
||||||
|
0x9e: true,
|
||||||
|
0x9f: true,
|
||||||
|
0xa0: true,
|
||||||
|
0xa1: true,
|
||||||
|
0xa2: true,
|
||||||
|
0xa3: true,
|
||||||
|
0xa4: true,
|
||||||
|
0xa5: true,
|
||||||
|
0xa6: true,
|
||||||
|
0xa7: true,
|
||||||
|
0xa8: true,
|
||||||
|
0xa9: true,
|
||||||
|
0xaa: true,
|
||||||
|
0xab: true,
|
||||||
|
0xac: true,
|
||||||
|
0xad: true,
|
||||||
|
0xae: true,
|
||||||
|
0xaf: true,
|
||||||
|
0xb0: true,
|
||||||
|
0xb1: true,
|
||||||
|
0xb2: true,
|
||||||
|
0xb3: true,
|
||||||
|
0xb4: true,
|
||||||
|
0xb5: true,
|
||||||
|
0xb6: true,
|
||||||
|
0xb7: true,
|
||||||
|
0xb8: true,
|
||||||
|
0xb9: true,
|
||||||
|
0xba: true,
|
||||||
|
0xbb: true,
|
||||||
|
0xbc: true,
|
||||||
|
0xbd: true,
|
||||||
|
0xbe: true,
|
||||||
|
0xbf: true,
|
||||||
|
0xc0: true,
|
||||||
|
0xc1: true,
|
||||||
|
0xc2: true,
|
||||||
|
0xc3: true,
|
||||||
|
0xc4: true,
|
||||||
|
0xc5: true,
|
||||||
|
0xc6: true,
|
||||||
|
0xc7: true,
|
||||||
|
0xc8: true,
|
||||||
|
0xc9: true,
|
||||||
|
0xca: true,
|
||||||
|
0xcb: true,
|
||||||
|
0xcc: true,
|
||||||
|
0xcd: true,
|
||||||
|
0xce: true,
|
||||||
|
0xcf: true,
|
||||||
|
0xd0: true,
|
||||||
|
0xd1: true,
|
||||||
|
0xd2: true,
|
||||||
|
0xd3: true,
|
||||||
|
0xd4: true,
|
||||||
|
0xd5: true,
|
||||||
|
0xd6: true,
|
||||||
|
0xd7: true,
|
||||||
|
0xd8: true,
|
||||||
|
0xd9: true,
|
||||||
|
0xda: true,
|
||||||
|
0xdb: true,
|
||||||
|
0xdc: true,
|
||||||
|
0xdd: true,
|
||||||
|
0xde: true,
|
||||||
|
0xdf: true,
|
||||||
|
0xe0: true,
|
||||||
|
0xe1: true,
|
||||||
|
0xe2: true,
|
||||||
|
0xe3: true,
|
||||||
|
0xe4: true,
|
||||||
|
0xe5: true,
|
||||||
|
0xe6: true,
|
||||||
|
0xe7: true,
|
||||||
|
0xe8: true,
|
||||||
|
0xe9: true,
|
||||||
|
0xea: true,
|
||||||
|
0xeb: true,
|
||||||
|
0xec: true,
|
||||||
|
0xed: true,
|
||||||
|
0xee: true,
|
||||||
|
0xef: true,
|
||||||
|
0xf0: true,
|
||||||
|
0xf1: true,
|
||||||
|
0xf2: true,
|
||||||
|
0xf3: true,
|
||||||
|
0xf4: true,
|
||||||
|
0xf5: true,
|
||||||
|
0xf6: true,
|
||||||
|
0xf7: true,
|
||||||
|
0xf8: true,
|
||||||
|
0xf9: true,
|
||||||
|
0xfa: true,
|
||||||
|
0xfb: true,
|
||||||
|
0xfc: true,
|
||||||
|
0xfd: true,
|
||||||
|
0xfe: true,
|
||||||
|
0xff: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
var needEscapeHTML = [256]bool{
|
||||||
|
'"': true,
|
||||||
|
'&': true,
|
||||||
|
'<': true,
|
||||||
|
'>': true,
|
||||||
|
'\\': true,
|
||||||
|
0x00: true,
|
||||||
|
0x01: true,
|
||||||
|
0x02: true,
|
||||||
|
0x03: true,
|
||||||
|
0x04: true,
|
||||||
|
0x05: true,
|
||||||
|
0x06: true,
|
||||||
|
0x07: true,
|
||||||
|
0x08: true,
|
||||||
|
0x09: true,
|
||||||
|
0x0a: true,
|
||||||
|
0x0b: true,
|
||||||
|
0x0c: true,
|
||||||
|
0x0d: true,
|
||||||
|
0x0e: true,
|
||||||
|
0x0f: true,
|
||||||
|
0x10: true,
|
||||||
|
0x11: true,
|
||||||
|
0x12: true,
|
||||||
|
0x13: true,
|
||||||
|
0x14: true,
|
||||||
|
0x15: true,
|
||||||
|
0x16: true,
|
||||||
|
0x17: true,
|
||||||
|
0x18: true,
|
||||||
|
0x19: true,
|
||||||
|
0x1a: true,
|
||||||
|
0x1b: true,
|
||||||
|
0x1c: true,
|
||||||
|
0x1d: true,
|
||||||
|
0x1e: true,
|
||||||
|
0x1f: true,
|
||||||
|
/* 0x20 - 0xff */
|
||||||
|
}
|
||||||
|
|
||||||
|
var needEscape = [256]bool{
|
||||||
|
'"': true,
|
||||||
|
'\\': true,
|
||||||
|
0x00: true,
|
||||||
|
0x01: true,
|
||||||
|
0x02: true,
|
||||||
|
0x03: true,
|
||||||
|
0x04: true,
|
||||||
|
0x05: true,
|
||||||
|
0x06: true,
|
||||||
|
0x07: true,
|
||||||
|
0x08: true,
|
||||||
|
0x09: true,
|
||||||
|
0x0a: true,
|
||||||
|
0x0b: true,
|
||||||
|
0x0c: true,
|
||||||
|
0x0d: true,
|
||||||
|
0x0e: true,
|
||||||
|
0x0f: true,
|
||||||
|
0x10: true,
|
||||||
|
0x11: true,
|
||||||
|
0x12: true,
|
||||||
|
0x13: true,
|
||||||
|
0x14: true,
|
||||||
|
0x15: true,
|
||||||
|
0x16: true,
|
||||||
|
0x17: true,
|
||||||
|
0x18: true,
|
||||||
|
0x19: true,
|
||||||
|
0x1a: true,
|
||||||
|
0x1b: true,
|
||||||
|
0x1c: true,
|
||||||
|
0x1d: true,
|
||||||
|
0x1e: true,
|
||||||
|
0x1f: true,
|
||||||
|
/* 0x20 - 0xff */
|
||||||
|
}
|
21
vendor/github.com/goccy/go-json/internal/encoder/vm/debug_vm.go
generated
vendored
21
vendor/github.com/goccy/go-json/internal/encoder/vm/debug_vm.go
generated
vendored
@ -16,16 +16,17 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
fmt.Println("=============[DEBUG]===============")
|
w := ctx.Option.DebugOut
|
||||||
fmt.Println("* [TYPE]")
|
fmt.Fprintln(w, "=============[DEBUG]===============")
|
||||||
fmt.Println(codeSet.Type)
|
fmt.Fprintln(w, "* [TYPE]")
|
||||||
fmt.Printf("\n")
|
fmt.Fprintln(w, codeSet.Type)
|
||||||
fmt.Println("* [ALL OPCODE]")
|
fmt.Fprintf(w, "\n")
|
||||||
fmt.Println(code.Dump())
|
fmt.Fprintln(w, "* [ALL OPCODE]")
|
||||||
fmt.Printf("\n")
|
fmt.Fprintln(w, code.Dump())
|
||||||
fmt.Println("* [CONTEXT]")
|
fmt.Fprintf(w, "\n")
|
||||||
fmt.Printf("%+v\n", ctx)
|
fmt.Fprintln(w, "* [CONTEXT]")
|
||||||
fmt.Println("===================================")
|
fmt.Fprintf(w, "%+v\n", ctx)
|
||||||
|
fmt.Fprintln(w, "===================================")
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
18
vendor/github.com/goccy/go-json/internal/encoder/vm/util.go
generated
vendored
18
vendor/github.com/goccy/go-json/internal/encoder/vm/util.go
generated
vendored
@ -68,7 +68,19 @@ func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
|
|||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func ptrToUint64(p uintptr) uint64 { return **(**uint64)(unsafe.Pointer(&p)) }
|
func ptrToUint64(p uintptr, bitSize uint8) uint64 {
|
||||||
|
switch bitSize {
|
||||||
|
case 8:
|
||||||
|
return (uint64)(**(**uint8)(unsafe.Pointer(&p)))
|
||||||
|
case 16:
|
||||||
|
return (uint64)(**(**uint16)(unsafe.Pointer(&p)))
|
||||||
|
case 32:
|
||||||
|
return (uint64)(**(**uint32)(unsafe.Pointer(&p)))
|
||||||
|
case 64:
|
||||||
|
return **(**uint64)(unsafe.Pointer(&p))
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) }
|
func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) }
|
||||||
func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) }
|
func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) }
|
||||||
func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) }
|
func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) }
|
||||||
@ -114,6 +126,10 @@ func appendComma(_ *encoder.RuntimeContext, b []byte) []byte {
|
|||||||
return append(b, ',')
|
return append(b, ',')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func appendNullComma(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||||
|
return append(b, "null,"...)
|
||||||
|
}
|
||||||
|
|
||||||
func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
|
func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||||
last := len(b) - 1
|
last := len(b) - 1
|
||||||
b[last] = ':'
|
b[last] = ':'
|
||||||
|
773
vendor/github.com/goccy/go-json/internal/encoder/vm/vm.go
generated
vendored
773
vendor/github.com/goccy/go-json/internal/encoder/vm/vm.go
generated
vendored
File diff suppressed because it is too large
Load Diff
21
vendor/github.com/goccy/go-json/internal/encoder/vm_color/debug_vm.go
generated
vendored
21
vendor/github.com/goccy/go-json/internal/encoder/vm_color/debug_vm.go
generated
vendored
@ -16,16 +16,17 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet)
|
|||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
fmt.Println("=============[DEBUG]===============")
|
w := ctx.Option.DebugOut
|
||||||
fmt.Println("* [TYPE]")
|
fmt.Fprintln(w, "=============[DEBUG]===============")
|
||||||
fmt.Println(codeSet.Type)
|
fmt.Fprintln(w, "* [TYPE]")
|
||||||
fmt.Printf("\n")
|
fmt.Fprintln(w, codeSet.Type)
|
||||||
fmt.Println("* [ALL OPCODE]")
|
fmt.Fprintf(w, "\n")
|
||||||
fmt.Println(code.Dump())
|
fmt.Fprintln(w, "* [ALL OPCODE]")
|
||||||
fmt.Printf("\n")
|
fmt.Fprintln(w, code.Dump())
|
||||||
fmt.Println("* [CONTEXT]")
|
fmt.Fprintf(w, "\n")
|
||||||
fmt.Printf("%+v\n", ctx)
|
fmt.Fprintln(w, "* [CONTEXT]")
|
||||||
fmt.Println("===================================")
|
fmt.Fprintf(w, "%+v\n", ctx)
|
||||||
|
fmt.Fprintln(w, "===================================")
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
29
vendor/github.com/goccy/go-json/internal/encoder/vm_color/util.go
generated
vendored
29
vendor/github.com/goccy/go-json/internal/encoder/vm_color/util.go
generated
vendored
@ -61,7 +61,19 @@ func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
|
|||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func ptrToUint64(p uintptr) uint64 { return **(**uint64)(unsafe.Pointer(&p)) }
|
func ptrToUint64(p uintptr, bitSize uint8) uint64 {
|
||||||
|
switch bitSize {
|
||||||
|
case 8:
|
||||||
|
return (uint64)(**(**uint8)(unsafe.Pointer(&p)))
|
||||||
|
case 16:
|
||||||
|
return (uint64)(**(**uint16)(unsafe.Pointer(&p)))
|
||||||
|
case 32:
|
||||||
|
return (uint64)(**(**uint32)(unsafe.Pointer(&p)))
|
||||||
|
case 64:
|
||||||
|
return **(**uint64)(unsafe.Pointer(&p))
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) }
|
func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) }
|
||||||
func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) }
|
func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) }
|
||||||
func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) }
|
func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) }
|
||||||
@ -92,17 +104,17 @@ func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendInt(ctx *encoder.RuntimeContext, b []byte, v uint64, code *encoder.Opcode) []byte {
|
func appendInt(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte {
|
||||||
format := ctx.Option.ColorScheme.Int
|
format := ctx.Option.ColorScheme.Int
|
||||||
b = append(b, format.Header...)
|
b = append(b, format.Header...)
|
||||||
b = encoder.AppendInt(ctx, b, v, code)
|
b = encoder.AppendInt(ctx, b, p, code)
|
||||||
return append(b, format.Footer...)
|
return append(b, format.Footer...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendUint(ctx *encoder.RuntimeContext, b []byte, v uint64, code *encoder.Opcode) []byte {
|
func appendUint(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte {
|
||||||
format := ctx.Option.ColorScheme.Uint
|
format := ctx.Option.ColorScheme.Uint
|
||||||
b = append(b, format.Header...)
|
b = append(b, format.Header...)
|
||||||
b = encoder.AppendUint(ctx, b, v, code)
|
b = encoder.AppendUint(ctx, b, p, code)
|
||||||
return append(b, format.Footer...)
|
return append(b, format.Footer...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,6 +178,13 @@ func appendComma(_ *encoder.RuntimeContext, b []byte) []byte {
|
|||||||
return append(b, ',')
|
return append(b, ',')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func appendNullComma(ctx *encoder.RuntimeContext, b []byte) []byte {
|
||||||
|
format := ctx.Option.ColorScheme.Null
|
||||||
|
b = append(b, format.Header...)
|
||||||
|
b = append(b, "null"...)
|
||||||
|
return append(append(b, format.Footer...), ',')
|
||||||
|
}
|
||||||
|
|
||||||
func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
|
func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||||
last := len(b) - 1
|
last := len(b) - 1
|
||||||
b[last] = ':'
|
b[last] = ':'
|
||||||
|
773
vendor/github.com/goccy/go-json/internal/encoder/vm_color/vm.go
generated
vendored
773
vendor/github.com/goccy/go-json/internal/encoder/vm_color/vm.go
generated
vendored
File diff suppressed because it is too large
Load Diff
21
vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/debug_vm.go
generated
vendored
21
vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/debug_vm.go
generated
vendored
@ -16,16 +16,17 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet)
|
|||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
fmt.Println("=============[DEBUG]===============")
|
w := ctx.Option.DebugOut
|
||||||
fmt.Println("* [TYPE]")
|
fmt.Fprintln(w, "=============[DEBUG]===============")
|
||||||
fmt.Println(codeSet.Type)
|
fmt.Fprintln(w, "* [TYPE]")
|
||||||
fmt.Printf("\n")
|
fmt.Fprintln(w, codeSet.Type)
|
||||||
fmt.Println("* [ALL OPCODE]")
|
fmt.Fprintf(w, "\n")
|
||||||
fmt.Println(code.Dump())
|
fmt.Fprintln(w, "* [ALL OPCODE]")
|
||||||
fmt.Printf("\n")
|
fmt.Fprintln(w, code.Dump())
|
||||||
fmt.Println("* [CONTEXT]")
|
fmt.Fprintf(w, "\n")
|
||||||
fmt.Printf("%+v\n", ctx)
|
fmt.Fprintln(w, "* [CONTEXT]")
|
||||||
fmt.Println("===================================")
|
fmt.Fprintf(w, "%+v\n", ctx)
|
||||||
|
fmt.Fprintln(w, "===================================")
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
30
vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/util.go
generated
vendored
30
vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/util.go
generated
vendored
@ -63,7 +63,20 @@ func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
|
|||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func ptrToUint64(p uintptr) uint64 { return **(**uint64)(unsafe.Pointer(&p)) }
|
func ptrToUint64(p uintptr, bitSize uint8) uint64 {
|
||||||
|
switch bitSize {
|
||||||
|
case 8:
|
||||||
|
return (uint64)(**(**uint8)(unsafe.Pointer(&p)))
|
||||||
|
case 16:
|
||||||
|
return (uint64)(**(**uint16)(unsafe.Pointer(&p)))
|
||||||
|
case 32:
|
||||||
|
return (uint64)(**(**uint32)(unsafe.Pointer(&p)))
|
||||||
|
case 64:
|
||||||
|
return **(**uint64)(unsafe.Pointer(&p))
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) }
|
func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) }
|
||||||
func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) }
|
func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) }
|
||||||
func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) }
|
func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) }
|
||||||
@ -94,17 +107,17 @@ func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendInt(ctx *encoder.RuntimeContext, b []byte, v uint64, code *encoder.Opcode) []byte {
|
func appendInt(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte {
|
||||||
format := ctx.Option.ColorScheme.Int
|
format := ctx.Option.ColorScheme.Int
|
||||||
b = append(b, format.Header...)
|
b = append(b, format.Header...)
|
||||||
b = encoder.AppendInt(ctx, b, v, code)
|
b = encoder.AppendInt(ctx, b, p, code)
|
||||||
return append(b, format.Footer...)
|
return append(b, format.Footer...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendUint(ctx *encoder.RuntimeContext, b []byte, v uint64, code *encoder.Opcode) []byte {
|
func appendUint(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte {
|
||||||
format := ctx.Option.ColorScheme.Uint
|
format := ctx.Option.ColorScheme.Uint
|
||||||
b = append(b, format.Header...)
|
b = append(b, format.Header...)
|
||||||
b = encoder.AppendUint(ctx, b, v, code)
|
b = encoder.AppendUint(ctx, b, p, code)
|
||||||
return append(b, format.Footer...)
|
return append(b, format.Footer...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,6 +181,13 @@ func appendComma(_ *encoder.RuntimeContext, b []byte) []byte {
|
|||||||
return append(b, ',', '\n')
|
return append(b, ',', '\n')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func appendNullComma(ctx *encoder.RuntimeContext, b []byte) []byte {
|
||||||
|
format := ctx.Option.ColorScheme.Null
|
||||||
|
b = append(b, format.Header...)
|
||||||
|
b = append(b, "null"...)
|
||||||
|
return append(append(b, format.Footer...), ',', '\n')
|
||||||
|
}
|
||||||
|
|
||||||
func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
|
func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||||
return append(b, ':', ' ')
|
return append(b, ':', ' ')
|
||||||
}
|
}
|
||||||
|
773
vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/vm.go
generated
vendored
773
vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/vm.go
generated
vendored
File diff suppressed because it is too large
Load Diff
21
vendor/github.com/goccy/go-json/internal/encoder/vm_indent/debug_vm.go
generated
vendored
21
vendor/github.com/goccy/go-json/internal/encoder/vm_indent/debug_vm.go
generated
vendored
@ -16,16 +16,17 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet)
|
|||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
fmt.Println("=============[DEBUG]===============")
|
w := ctx.Option.DebugOut
|
||||||
fmt.Println("* [TYPE]")
|
fmt.Fprintln(w, "=============[DEBUG]===============")
|
||||||
fmt.Println(codeSet.Type)
|
fmt.Fprintln(w, "* [TYPE]")
|
||||||
fmt.Printf("\n")
|
fmt.Fprintln(w, codeSet.Type)
|
||||||
fmt.Println("* [ALL OPCODE]")
|
fmt.Fprintf(w, "\n")
|
||||||
fmt.Println(code.Dump())
|
fmt.Fprintln(w, "* [ALL OPCODE]")
|
||||||
fmt.Printf("\n")
|
fmt.Fprintln(w, code.Dump())
|
||||||
fmt.Println("* [CONTEXT]")
|
fmt.Fprintf(w, "\n")
|
||||||
fmt.Printf("%+v\n", ctx)
|
fmt.Fprintln(w, "* [CONTEXT]")
|
||||||
fmt.Println("===================================")
|
fmt.Fprintf(w, "%+v\n", ctx)
|
||||||
|
fmt.Fprintln(w, "===================================")
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
18
vendor/github.com/goccy/go-json/internal/encoder/vm_indent/util.go
generated
vendored
18
vendor/github.com/goccy/go-json/internal/encoder/vm_indent/util.go
generated
vendored
@ -70,7 +70,19 @@ func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
|
|||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func ptrToUint64(p uintptr) uint64 { return **(**uint64)(unsafe.Pointer(&p)) }
|
func ptrToUint64(p uintptr, bitSize uint8) uint64 {
|
||||||
|
switch bitSize {
|
||||||
|
case 8:
|
||||||
|
return (uint64)(**(**uint8)(unsafe.Pointer(&p)))
|
||||||
|
case 16:
|
||||||
|
return (uint64)(**(**uint16)(unsafe.Pointer(&p)))
|
||||||
|
case 32:
|
||||||
|
return (uint64)(**(**uint32)(unsafe.Pointer(&p)))
|
||||||
|
case 64:
|
||||||
|
return **(**uint64)(unsafe.Pointer(&p))
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) }
|
func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) }
|
||||||
func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) }
|
func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) }
|
||||||
func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) }
|
func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) }
|
||||||
@ -116,6 +128,10 @@ func appendComma(_ *encoder.RuntimeContext, b []byte) []byte {
|
|||||||
return append(b, ',', '\n')
|
return append(b, ',', '\n')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func appendNullComma(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||||
|
return append(b, "null,\n"...)
|
||||||
|
}
|
||||||
|
|
||||||
func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
|
func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||||
return append(b, ':', ' ')
|
return append(b, ':', ' ')
|
||||||
}
|
}
|
||||||
|
773
vendor/github.com/goccy/go-json/internal/encoder/vm_indent/vm.go
generated
vendored
773
vendor/github.com/goccy/go-json/internal/encoder/vm_indent/vm.go
generated
vendored
File diff suppressed because it is too large
Load Diff
6
vendor/github.com/goccy/go-json/internal/runtime/struct_field.go
generated
vendored
6
vendor/github.com/goccy/go-json/internal/runtime/struct_field.go
generated
vendored
@ -13,7 +13,11 @@ func getTag(field reflect.StructField) string {
|
|||||||
func IsIgnoredStructField(field reflect.StructField) bool {
|
func IsIgnoredStructField(field reflect.StructField) bool {
|
||||||
if field.PkgPath != "" {
|
if field.PkgPath != "" {
|
||||||
if field.Anonymous {
|
if field.Anonymous {
|
||||||
if !(field.Type.Kind() == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct) && field.Type.Kind() != reflect.Struct {
|
t := field.Type
|
||||||
|
if t.Kind() == reflect.Ptr {
|
||||||
|
t = t.Elem()
|
||||||
|
}
|
||||||
|
if t.Kind() != reflect.Struct {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
5
vendor/github.com/goccy/go-json/json.go
generated
vendored
5
vendor/github.com/goccy/go-json/json.go
generated
vendored
@ -364,3 +364,8 @@ func Valid(data []byte) bool {
|
|||||||
}
|
}
|
||||||
return decoder.InputOffset() >= int64(len(data))
|
return decoder.InputOffset() >= int64(len(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
encoder.Marshal = Marshal
|
||||||
|
encoder.Unmarshal = Unmarshal
|
||||||
|
}
|
||||||
|
26
vendor/github.com/goccy/go-json/option.go
generated
vendored
26
vendor/github.com/goccy/go-json/option.go
generated
vendored
@ -1,6 +1,8 @@
|
|||||||
package json
|
package json
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/goccy/go-json/internal/decoder"
|
"github.com/goccy/go-json/internal/decoder"
|
||||||
"github.com/goccy/go-json/internal/encoder"
|
"github.com/goccy/go-json/internal/encoder"
|
||||||
)
|
)
|
||||||
@ -15,6 +17,23 @@ func UnorderedMap() EncodeOptionFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DisableHTMLEscape disables escaping of HTML characters ( '&', '<', '>' ) when encoding string.
|
||||||
|
func DisableHTMLEscape() EncodeOptionFunc {
|
||||||
|
return func(opt *EncodeOption) {
|
||||||
|
opt.Flag &= ^encoder.HTMLEscapeOption
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisableNormalizeUTF8
|
||||||
|
// By default, when encoding string, UTF8 characters in the range of 0x80 - 0xFF are processed by applying \ufffd for invalid code and escaping for \u2028 and \u2029.
|
||||||
|
// This option disables this behaviour. You can expect faster speeds by applying this option, but be careful.
|
||||||
|
// encoding/json implements here: https://github.com/golang/go/blob/6178d25fc0b28724b1b5aec2b1b74fc06d9294c7/src/encoding/json/encode.go#L1067-L1093.
|
||||||
|
func DisableNormalizeUTF8() EncodeOptionFunc {
|
||||||
|
return func(opt *EncodeOption) {
|
||||||
|
opt.Flag &= ^encoder.NormalizeUTF8Option
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Debug outputs debug information when panic occurs during encoding.
|
// Debug outputs debug information when panic occurs during encoding.
|
||||||
func Debug() EncodeOptionFunc {
|
func Debug() EncodeOptionFunc {
|
||||||
return func(opt *EncodeOption) {
|
return func(opt *EncodeOption) {
|
||||||
@ -22,6 +41,13 @@ func Debug() EncodeOptionFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DebugWith sets the destination to write debug messages.
|
||||||
|
func DebugWith(w io.Writer) EncodeOptionFunc {
|
||||||
|
return func(opt *EncodeOption) {
|
||||||
|
opt.DebugOut = w
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Colorize add an identifier for coloring to the string of the encoded result.
|
// Colorize add an identifier for coloring to the string of the encoded result.
|
||||||
func Colorize(scheme *ColorScheme) EncodeOptionFunc {
|
func Colorize(scheme *ColorScheme) EncodeOptionFunc {
|
||||||
return func(opt *EncodeOption) {
|
return func(opt *EncodeOption) {
|
||||||
|
47
vendor/github.com/goccy/go-json/query.go
generated
vendored
Normal file
47
vendor/github.com/goccy/go-json/query.go
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package json
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goccy/go-json/internal/encoder"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// FieldQuery you can dynamically filter the fields in the structure by creating a FieldQuery,
|
||||||
|
// adding it to context.Context using SetFieldQueryToContext and then passing it to MarshalContext.
|
||||||
|
// This is a type-safe operation, so it is faster than filtering using map[string]interface{}.
|
||||||
|
FieldQuery = encoder.FieldQuery
|
||||||
|
FieldQueryString = encoder.FieldQueryString
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// FieldQueryFromContext get current FieldQuery from context.Context.
|
||||||
|
FieldQueryFromContext = encoder.FieldQueryFromContext
|
||||||
|
// SetFieldQueryToContext set current FieldQuery to context.Context.
|
||||||
|
SetFieldQueryToContext = encoder.SetFieldQueryToContext
|
||||||
|
)
|
||||||
|
|
||||||
|
// BuildFieldQuery builds FieldQuery by fieldName or sub field query.
|
||||||
|
// First, specify the field name that you want to keep in structure type.
|
||||||
|
// If the field you want to keep is a structure type, by creating a sub field query using BuildSubFieldQuery,
|
||||||
|
// you can select the fields you want to keep in the structure.
|
||||||
|
// This description can be written recursively.
|
||||||
|
func BuildFieldQuery(fields ...FieldQueryString) (*FieldQuery, error) {
|
||||||
|
query, err := Marshal(fields)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return FieldQueryString(query).Build()
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildSubFieldQuery builds sub field query.
|
||||||
|
func BuildSubFieldQuery(name string) *SubFieldQuery {
|
||||||
|
return &SubFieldQuery{name: name}
|
||||||
|
}
|
||||||
|
|
||||||
|
type SubFieldQuery struct {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *SubFieldQuery) Fields(fields ...FieldQueryString) FieldQueryString {
|
||||||
|
query, _ := Marshal(map[string][]FieldQueryString{q.name: fields})
|
||||||
|
return FieldQueryString(query)
|
||||||
|
}
|
2
vendor/github.com/json-iterator/go/README.md
generated
vendored
2
vendor/github.com/json-iterator/go/README.md
generated
vendored
@ -8,8 +8,6 @@
|
|||||||
|
|
||||||
A high-performance 100% compatible drop-in replacement of "encoding/json"
|
A high-performance 100% compatible drop-in replacement of "encoding/json"
|
||||||
|
|
||||||
You can also use thrift like JSON using [thrift-iterator](https://github.com/thrift-iterator/go)
|
|
||||||
|
|
||||||
# Benchmark
|
# Benchmark
|
||||||
|
|
||||||
![benchmark](http://jsoniter.com/benchmarks/go-benchmark.png)
|
![benchmark](http://jsoniter.com/benchmarks/go-benchmark.png)
|
||||||
|
148
vendor/github.com/labstack/echo/v4/CHANGELOG.md
generated
vendored
148
vendor/github.com/labstack/echo/v4/CHANGELOG.md
generated
vendored
@ -1,5 +1,153 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v4.9.1 - 2022-10-12
|
||||||
|
|
||||||
|
**Fixes**
|
||||||
|
|
||||||
|
* Fix logger panicing (when template is set to empty) by bumping dependency version [#2295](https://github.com/labstack/echo/issues/2295)
|
||||||
|
|
||||||
|
**Enhancements**
|
||||||
|
|
||||||
|
* Improve CORS documentation [#2272](https://github.com/labstack/echo/pull/2272)
|
||||||
|
* Update readme about supported Go versions [#2291](https://github.com/labstack/echo/pull/2291)
|
||||||
|
* Tests: improve error handling on closing body [#2254](https://github.com/labstack/echo/pull/2254)
|
||||||
|
* Tests: refactor some of the assertions in tests [#2275](https://github.com/labstack/echo/pull/2275)
|
||||||
|
* Tests: refactor assertions [#2301](https://github.com/labstack/echo/pull/2301)
|
||||||
|
|
||||||
|
## v4.9.0 - 2022-09-04
|
||||||
|
|
||||||
|
**Security**
|
||||||
|
|
||||||
|
* Fix open redirect vulnerability in handlers serving static directories (e.Static, e.StaticFs, echo.StaticDirectoryHandler) [#2260](https://github.com/labstack/echo/pull/2260)
|
||||||
|
|
||||||
|
**Enhancements**
|
||||||
|
|
||||||
|
* Allow configuring ErrorHandler in CSRF middleware [#2257](https://github.com/labstack/echo/pull/2257)
|
||||||
|
* Replace HTTP method constants in tests with stdlib constants [#2247](https://github.com/labstack/echo/pull/2247)
|
||||||
|
|
||||||
|
|
||||||
|
## v4.8.0 - 2022-08-10
|
||||||
|
|
||||||
|
**Most notable things**
|
||||||
|
|
||||||
|
You can now add any arbitrary HTTP method type as a route [#2237](https://github.com/labstack/echo/pull/2237)
|
||||||
|
```go
|
||||||
|
e.Add("COPY", "/*", func(c echo.Context) error
|
||||||
|
return c.String(http.StatusOK, "OK COPY")
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
You can add custom 404 handler for specific paths [#2217](https://github.com/labstack/echo/pull/2217)
|
||||||
|
```go
|
||||||
|
e.RouteNotFound("/*", func(c echo.Context) error { return c.NoContent(http.StatusNotFound) })
|
||||||
|
|
||||||
|
g := e.Group("/images")
|
||||||
|
g.RouteNotFound("/*", func(c echo.Context) error { return c.NoContent(http.StatusNotFound) })
|
||||||
|
```
|
||||||
|
|
||||||
|
**Enhancements**
|
||||||
|
|
||||||
|
* Add new value binding methods (UnixTimeMilli,TextUnmarshaler,JSONUnmarshaler) to Valuebinder [#2127](https://github.com/labstack/echo/pull/2127)
|
||||||
|
* Refactor: body_limit middleware unit test [#2145](https://github.com/labstack/echo/pull/2145)
|
||||||
|
* Refactor: Timeout mw: rework how test waits for timeout. [#2187](https://github.com/labstack/echo/pull/2187)
|
||||||
|
* BasicAuth middleware returns 500 InternalServerError on invalid base64 strings but should return 400 [#2191](https://github.com/labstack/echo/pull/2191)
|
||||||
|
* Refactor: duplicated findStaticChild process at findChildWithLabel [#2176](https://github.com/labstack/echo/pull/2176)
|
||||||
|
* Allow different param names in different methods with same path scheme [#2209](https://github.com/labstack/echo/pull/2209)
|
||||||
|
* Add support for registering handlers for different 404 routes [#2217](https://github.com/labstack/echo/pull/2217)
|
||||||
|
* Middlewares should use errors.As() instead of type assertion on HTTPError [#2227](https://github.com/labstack/echo/pull/2227)
|
||||||
|
* Allow arbitrary HTTP method types to be added as routes [#2237](https://github.com/labstack/echo/pull/2237)
|
||||||
|
|
||||||
|
## v4.7.2 - 2022-03-16
|
||||||
|
|
||||||
|
**Fixes**
|
||||||
|
|
||||||
|
* Fix nil pointer exception when calling Start again after address binding error [#2131](https://github.com/labstack/echo/pull/2131)
|
||||||
|
* Fix CSRF middleware not being able to extract token from multipart/form-data form [#2136](https://github.com/labstack/echo/pull/2136)
|
||||||
|
* Fix Timeout middleware write race [#2126](https://github.com/labstack/echo/pull/2126)
|
||||||
|
|
||||||
|
**Enhancements**
|
||||||
|
|
||||||
|
* Recover middleware should not log panic for aborted handler [#2134](https://github.com/labstack/echo/pull/2134)
|
||||||
|
|
||||||
|
|
||||||
|
## v4.7.1 - 2022-03-13
|
||||||
|
|
||||||
|
**Fixes**
|
||||||
|
|
||||||
|
* Fix `e.Static`, `.File()`, `c.Attachment()` being picky with paths starting with `./`, `../` and `/` after 4.7.0 introduced echo.Filesystem support (Go1.16+) [#2123](https://github.com/labstack/echo/pull/2123)
|
||||||
|
|
||||||
|
**Enhancements**
|
||||||
|
|
||||||
|
* Remove some unused code [#2116](https://github.com/labstack/echo/pull/2116)
|
||||||
|
|
||||||
|
|
||||||
|
## v4.7.0 - 2022-03-01
|
||||||
|
|
||||||
|
**Enhancements**
|
||||||
|
|
||||||
|
* Add JWT, KeyAuth, CSRF multivalue extractors [#2060](https://github.com/labstack/echo/pull/2060)
|
||||||
|
* Add LogErrorFunc to recover middleware [#2072](https://github.com/labstack/echo/pull/2072)
|
||||||
|
* Add support for HEAD method query params binding [#2027](https://github.com/labstack/echo/pull/2027)
|
||||||
|
* Improve filesystem support with echo.FileFS, echo.StaticFS, group.FileFS, group.StaticFS [#2064](https://github.com/labstack/echo/pull/2064)
|
||||||
|
|
||||||
|
**Fixes**
|
||||||
|
|
||||||
|
* Fix X-Real-IP bug, improve tests [#2007](https://github.com/labstack/echo/pull/2007)
|
||||||
|
* Minor syntax fixes [#1994](https://github.com/labstack/echo/pull/1994), [#2102](https://github.com/labstack/echo/pull/2102), [#2102](https://github.com/labstack/echo/pull/2102)
|
||||||
|
|
||||||
|
**General**
|
||||||
|
|
||||||
|
* Add cache-control and connection headers [#2103](https://github.com/labstack/echo/pull/2103)
|
||||||
|
* Add Retry-After header constant [#2078](https://github.com/labstack/echo/pull/2078)
|
||||||
|
* Upgrade `go` directive in `go.mod` to 1.17 [#2049](https://github.com/labstack/echo/pull/2049)
|
||||||
|
* Add Pagoda [#2077](https://github.com/labstack/echo/pull/2077) and Souin [#2069](https://github.com/labstack/echo/pull/2069) to 3rd-party middlewares in README
|
||||||
|
|
||||||
|
## v4.6.3 - 2022-01-10
|
||||||
|
|
||||||
|
**Fixes**
|
||||||
|
|
||||||
|
* Fixed Echo version number in greeting message which was not incremented to `4.6.2` [#2066](https://github.com/labstack/echo/issues/2066)
|
||||||
|
|
||||||
|
|
||||||
|
## v4.6.2 - 2022-01-08
|
||||||
|
|
||||||
|
**Fixes**
|
||||||
|
|
||||||
|
* Fixed route containing escaped colon should be matchable but is not matched to request path [#2047](https://github.com/labstack/echo/pull/2047)
|
||||||
|
* Fixed a problem that returned wrong content-encoding when the gzip compressed content was empty. [#1921](https://github.com/labstack/echo/pull/1921)
|
||||||
|
* Update (test) dependencies [#2021](https://github.com/labstack/echo/pull/2021)
|
||||||
|
|
||||||
|
|
||||||
|
**Enhancements**
|
||||||
|
|
||||||
|
* Add support for configurable target header for the request_id middleware [#2040](https://github.com/labstack/echo/pull/2040)
|
||||||
|
* Change decompress middleware to use stream decompression instead of buffering [#2018](https://github.com/labstack/echo/pull/2018)
|
||||||
|
* Documentation updates
|
||||||
|
|
||||||
|
|
||||||
|
## v4.6.1 - 2021-09-26
|
||||||
|
|
||||||
|
**Enhancements**
|
||||||
|
|
||||||
|
* Add start time to request logger middleware values [#1991](https://github.com/labstack/echo/pull/1991)
|
||||||
|
|
||||||
|
## v4.6.0 - 2021-09-20
|
||||||
|
|
||||||
|
Introduced a new [request logger](https://github.com/labstack/echo/blob/master/middleware/request_logger.go) middleware
|
||||||
|
to help with cases when you want to use some other logging library in your application.
|
||||||
|
|
||||||
|
**Fixes**
|
||||||
|
|
||||||
|
* fix timeout middleware warning: superfluous response.WriteHeader [#1905](https://github.com/labstack/echo/issues/1905)
|
||||||
|
|
||||||
|
**Enhancements**
|
||||||
|
|
||||||
|
* Add Cookie to KeyAuth middleware's KeyLookup [#1929](https://github.com/labstack/echo/pull/1929)
|
||||||
|
* JWT middleware should ignore case of auth scheme in request header [#1951](https://github.com/labstack/echo/pull/1951)
|
||||||
|
* Refactor default error handler to return first if response is already committed [#1956](https://github.com/labstack/echo/pull/1956)
|
||||||
|
* Added request logger middleware which helps to use custom logger library for logging requests. [#1980](https://github.com/labstack/echo/pull/1980)
|
||||||
|
* Allow escaping of colon in route path so Google Cloud API "custom methods" could be implemented [#1988](https://github.com/labstack/echo/pull/1988)
|
||||||
|
|
||||||
## v4.5.0 - 2021-08-01
|
## v4.5.0 - 2021-08-01
|
||||||
|
|
||||||
**Important notes**
|
**Important notes**
|
||||||
|
6
vendor/github.com/labstack/echo/v4/Makefile
generated
vendored
6
vendor/github.com/labstack/echo/v4/Makefile
generated
vendored
@ -9,7 +9,7 @@ tag:
|
|||||||
check: lint vet race ## Check project
|
check: lint vet race ## Check project
|
||||||
|
|
||||||
init:
|
init:
|
||||||
@go get -u golang.org/x/lint/golint
|
@go install golang.org/x/lint/golint@latest
|
||||||
|
|
||||||
lint: ## Lint the files
|
lint: ## Lint the files
|
||||||
@golint -set_exit_status ${PKG_LIST}
|
@golint -set_exit_status ${PKG_LIST}
|
||||||
@ -29,6 +29,6 @@ benchmark: ## Run benchmarks
|
|||||||
help: ## Display this help screen
|
help: ## Display this help screen
|
||||||
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||||
|
|
||||||
goversion ?= "1.15"
|
goversion ?= "1.16"
|
||||||
test_version: ## Run tests inside Docker with given version (defaults to 1.15 oldest supported). Example: make test_version goversion=1.15
|
test_version: ## Run tests inside Docker with given version (defaults to 1.15 oldest supported). Example: make test_version goversion=1.16
|
||||||
@docker run --rm -it -v $(shell pwd):/project golang:$(goversion) /bin/sh -c "cd /project && make init check"
|
@docker run --rm -it -v $(shell pwd):/project golang:$(goversion) /bin/sh -c "cd /project && make init check"
|
||||||
|
31
vendor/github.com/labstack/echo/v4/README.md
generated
vendored
31
vendor/github.com/labstack/echo/v4/README.md
generated
vendored
@ -5,19 +5,17 @@
|
|||||||
[![Go Report Card](https://goreportcard.com/badge/github.com/labstack/echo?style=flat-square)](https://goreportcard.com/report/github.com/labstack/echo)
|
[![Go Report Card](https://goreportcard.com/badge/github.com/labstack/echo?style=flat-square)](https://goreportcard.com/report/github.com/labstack/echo)
|
||||||
[![Build Status](http://img.shields.io/travis/labstack/echo.svg?style=flat-square)](https://travis-ci.org/labstack/echo)
|
[![Build Status](http://img.shields.io/travis/labstack/echo.svg?style=flat-square)](https://travis-ci.org/labstack/echo)
|
||||||
[![Codecov](https://img.shields.io/codecov/c/github/labstack/echo.svg?style=flat-square)](https://codecov.io/gh/labstack/echo)
|
[![Codecov](https://img.shields.io/codecov/c/github/labstack/echo.svg?style=flat-square)](https://codecov.io/gh/labstack/echo)
|
||||||
[![Join the chat at https://gitter.im/labstack/echo](https://img.shields.io/badge/gitter-join%20chat-brightgreen.svg?style=flat-square)](https://gitter.im/labstack/echo)
|
|
||||||
[![Forum](https://img.shields.io/badge/community-forum-00afd1.svg?style=flat-square)](https://github.com/labstack/echo/discussions)
|
[![Forum](https://img.shields.io/badge/community-forum-00afd1.svg?style=flat-square)](https://github.com/labstack/echo/discussions)
|
||||||
[![Twitter](https://img.shields.io/badge/twitter-@labstack-55acee.svg?style=flat-square)](https://twitter.com/labstack)
|
[![Twitter](https://img.shields.io/badge/twitter-@labstack-55acee.svg?style=flat-square)](https://twitter.com/labstack)
|
||||||
[![License](http://img.shields.io/badge/license-mit-blue.svg?style=flat-square)](https://raw.githubusercontent.com/labstack/echo/master/LICENSE)
|
[![License](http://img.shields.io/badge/license-mit-blue.svg?style=flat-square)](https://raw.githubusercontent.com/labstack/echo/master/LICENSE)
|
||||||
|
|
||||||
## Supported Go versions
|
## Supported Go versions
|
||||||
|
|
||||||
|
Latest version of Echo supports last four Go major [releases](https://go.dev/doc/devel/release) and might work with older versions.
|
||||||
|
|
||||||
As of version 4.0.0, Echo is available as a [Go module](https://github.com/golang/go/wiki/Modules).
|
As of version 4.0.0, Echo is available as a [Go module](https://github.com/golang/go/wiki/Modules).
|
||||||
Therefore a Go version capable of understanding /vN suffixed imports is required:
|
Therefore a Go version capable of understanding /vN suffixed imports is required:
|
||||||
|
|
||||||
- 1.9.7+
|
|
||||||
- 1.10.3+
|
|
||||||
- 1.14+
|
|
||||||
|
|
||||||
Any of these versions will allow you to import Echo as `github.com/labstack/echo/v4` which is the recommended
|
Any of these versions will allow you to import Echo as `github.com/labstack/echo/v4` which is the recommended
|
||||||
way of using Echo going forward.
|
way of using Echo going forward.
|
||||||
@ -66,9 +64,9 @@ go get github.com/labstack/echo/v4
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/labstack/echo/v4/middleware"
|
"github.com/labstack/echo/v4/middleware"
|
||||||
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -92,10 +90,24 @@ func hello(c echo.Context) error {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
# Third-party middlewares
|
||||||
|
|
||||||
|
| Repository | Description |
|
||||||
|
|------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| [github.com/labstack/echo-contrib](https://github.com/labstack/echo-contrib) | (by Echo team) [casbin](https://github.com/casbin/casbin), [gorilla/sessions](https://github.com/gorilla/sessions), [jaegertracing](github.com/uber/jaeger-client-go), [prometheus](https://github.com/prometheus/client_golang/), [pprof](https://pkg.go.dev/net/http/pprof), [zipkin](https://github.com/openzipkin/zipkin-go) middlewares |
|
||||||
|
| [deepmap/oapi-codegen](https://github.com/deepmap/oapi-codegen) | Automatically generate RESTful API documentation with [OpenAPI](https://swagger.io/specification/) Client and Server Code Generator |
|
||||||
|
| [github.com/swaggo/echo-swagger](https://github.com/swaggo/echo-swagger) | Automatically generate RESTful API documentation with [Swagger](https://swagger.io/) 2.0. |
|
||||||
|
| [github.com/ziflex/lecho](https://github.com/ziflex/lecho) | [Zerolog](https://github.com/rs/zerolog) logging library wrapper for Echo logger interface. |
|
||||||
|
| [github.com/brpaz/echozap](https://github.com/brpaz/echozap) | Uber´s [Zap](https://github.com/uber-go/zap) logging library wrapper for Echo logger interface. |
|
||||||
|
| [github.com/darkweak/souin/plugins/echo](https://github.com/darkweak/souin/tree/master/plugins/echo) | HTTP cache system based on [Souin](https://github.com/darkweak/souin) to automatically get your endpoints cached. It supports some distributed and non-distributed storage systems depending your needs. |
|
||||||
|
| [github.com/mikestefanello/pagoda](https://github.com/mikestefanello/pagoda) | Rapid, easy full-stack web development starter kit built with Echo. |
|
||||||
|
| [github.com/go-woo/protoc-gen-echo](https://github.com/go-woo/protoc-gen-echo) | ProtoBuf generate Echo server side code |
|
||||||
|
|
||||||
|
Please send a PR to add your own library here.
|
||||||
|
|
||||||
## Help
|
## Help
|
||||||
|
|
||||||
- [Forum](https://github.com/labstack/echo/discussions)
|
- [Forum](https://github.com/labstack/echo/discussions)
|
||||||
- [Chat](https://gitter.im/labstack/echo)
|
|
||||||
|
|
||||||
## Contribute
|
## Contribute
|
||||||
|
|
||||||
@ -114,8 +126,11 @@ func hello(c echo.Context) error {
|
|||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
- [Vishal Rana](https://github.com/vishr) - Author
|
- [Vishal Rana](https://github.com/vishr) (Author)
|
||||||
- [Nitin Rana](https://github.com/nr17) - Consultant
|
- [Nitin Rana](https://github.com/nr17) (Consultant)
|
||||||
|
- [Roland Lammel](https://github.com/lammel) (Maintainer)
|
||||||
|
- [Martti T.](https://github.com/aldas) (Maintainer)
|
||||||
|
- [Pablo Andres Fuente](https://github.com/pafuent) (Maintainer)
|
||||||
- [Contributors](https://github.com/labstack/echo/graphs/contributors)
|
- [Contributors](https://github.com/labstack/echo/graphs/contributors)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
10
vendor/github.com/labstack/echo/v4/bind.go
generated
vendored
10
vendor/github.com/labstack/echo/v4/bind.go
generated
vendored
@ -111,11 +111,11 @@ func (b *DefaultBinder) Bind(i interface{}, c Context) (err error) {
|
|||||||
if err := b.BindPathParams(c, i); err != nil {
|
if err := b.BindPathParams(c, i); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Issue #1670 - Query params are binded only for GET/DELETE and NOT for usual request with body (POST/PUT/PATCH)
|
// Only bind query parameters for GET/DELETE/HEAD to avoid unexpected behavior with destination struct binding from body.
|
||||||
// Reasoning here is that parameters in query and bind destination struct could have UNEXPECTED matches and results due that.
|
// For example a request URL `&id=1&lang=en` with body `{"id":100,"lang":"de"}` would lead to precedence issues.
|
||||||
// i.e. is `&id=1&lang=en` from URL same as `{"id":100,"lang":"de"}` request body and which one should have priority when binding.
|
// The HTTP method check restores pre-v4.1.11 behavior to avoid these problems (see issue #1670)
|
||||||
// This HTTP method check restores pre v4.1.11 behavior and avoids different problems when query is mixed with body
|
method := c.Request().Method
|
||||||
if c.Request().Method == http.MethodGet || c.Request().Method == http.MethodDelete {
|
if method == http.MethodGet || method == http.MethodDelete || method == http.MethodHead {
|
||||||
if err = b.BindQueryParams(c, i); err != nil {
|
if err = b.BindQueryParams(c, i); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
195
vendor/github.com/labstack/echo/v4/binder.go
generated
vendored
195
vendor/github.com/labstack/echo/v4/binder.go
generated
vendored
@ -1,6 +1,8 @@
|
|||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -52,7 +54,10 @@ import (
|
|||||||
* time
|
* time
|
||||||
* duration
|
* duration
|
||||||
* BindUnmarshaler() interface
|
* BindUnmarshaler() interface
|
||||||
|
* TextUnmarshaler() interface
|
||||||
|
* JSONUnmarshaler() interface
|
||||||
* UnixTime() - converts unix time (integer) to time.Time
|
* UnixTime() - converts unix time (integer) to time.Time
|
||||||
|
* UnixTimeMilli() - converts unix time with millisecond precision (integer) to time.Time
|
||||||
* UnixTimeNano() - converts unix time with nanosecond precision (integer) to time.Time
|
* UnixTimeNano() - converts unix time with nanosecond precision (integer) to time.Time
|
||||||
* CustomFunc() - callback function for your custom conversion logic. Signature `func(values []string) []error`
|
* CustomFunc() - callback function for your custom conversion logic. Signature `func(values []string) []error`
|
||||||
*/
|
*/
|
||||||
@ -204,7 +209,7 @@ func (b *ValueBinder) CustomFunc(sourceParam string, customFunc func(values []st
|
|||||||
return b.customFunc(sourceParam, customFunc, false)
|
return b.customFunc(sourceParam, customFunc, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustCustomFunc requires parameter values to exist to be bind with Func. Returns error when value does not exist.
|
// MustCustomFunc requires parameter values to exist to bind with Func. Returns error when value does not exist.
|
||||||
func (b *ValueBinder) MustCustomFunc(sourceParam string, customFunc func(values []string) []error) *ValueBinder {
|
func (b *ValueBinder) MustCustomFunc(sourceParam string, customFunc func(values []string) []error) *ValueBinder {
|
||||||
return b.customFunc(sourceParam, customFunc, true)
|
return b.customFunc(sourceParam, customFunc, true)
|
||||||
}
|
}
|
||||||
@ -241,7 +246,7 @@ func (b *ValueBinder) String(sourceParam string, dest *string) *ValueBinder {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustString requires parameter value to exist to be bind to string variable. Returns error when value does not exist
|
// MustString requires parameter value to exist to bind to string variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustString(sourceParam string, dest *string) *ValueBinder {
|
func (b *ValueBinder) MustString(sourceParam string, dest *string) *ValueBinder {
|
||||||
if b.failFast && b.errors != nil {
|
if b.failFast && b.errors != nil {
|
||||||
return b
|
return b
|
||||||
@ -270,7 +275,7 @@ func (b *ValueBinder) Strings(sourceParam string, dest *[]string) *ValueBinder {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustStrings requires parameter values to exist to be bind to slice of string variables. Returns error when value does not exist
|
// MustStrings requires parameter values to exist to bind to slice of string variables. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustStrings(sourceParam string, dest *[]string) *ValueBinder {
|
func (b *ValueBinder) MustStrings(sourceParam string, dest *[]string) *ValueBinder {
|
||||||
if b.failFast && b.errors != nil {
|
if b.failFast && b.errors != nil {
|
||||||
return b
|
return b
|
||||||
@ -302,7 +307,7 @@ func (b *ValueBinder) BindUnmarshaler(sourceParam string, dest BindUnmarshaler)
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustBindUnmarshaler requires parameter value to exist to be bind to destination implementing BindUnmarshaler interface.
|
// MustBindUnmarshaler requires parameter value to exist to bind to destination implementing BindUnmarshaler interface.
|
||||||
// Returns error when value does not exist
|
// Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustBindUnmarshaler(sourceParam string, dest BindUnmarshaler) *ValueBinder {
|
func (b *ValueBinder) MustBindUnmarshaler(sourceParam string, dest BindUnmarshaler) *ValueBinder {
|
||||||
if b.failFast && b.errors != nil {
|
if b.failFast && b.errors != nil {
|
||||||
@ -321,13 +326,85 @@ func (b *ValueBinder) MustBindUnmarshaler(sourceParam string, dest BindUnmarshal
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JSONUnmarshaler binds parameter to destination implementing json.Unmarshaler interface
|
||||||
|
func (b *ValueBinder) JSONUnmarshaler(sourceParam string, dest json.Unmarshaler) *ValueBinder {
|
||||||
|
if b.failFast && b.errors != nil {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp := b.ValueFunc(sourceParam)
|
||||||
|
if tmp == "" {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := dest.UnmarshalJSON([]byte(tmp)); err != nil {
|
||||||
|
b.setError(b.ErrorFunc(sourceParam, []string{tmp}, "failed to bind field value to json.Unmarshaler interface", err))
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustJSONUnmarshaler requires parameter value to exist to bind to destination implementing json.Unmarshaler interface.
|
||||||
|
// Returns error when value does not exist
|
||||||
|
func (b *ValueBinder) MustJSONUnmarshaler(sourceParam string, dest json.Unmarshaler) *ValueBinder {
|
||||||
|
if b.failFast && b.errors != nil {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp := b.ValueFunc(sourceParam)
|
||||||
|
if tmp == "" {
|
||||||
|
b.setError(b.ErrorFunc(sourceParam, []string{tmp}, "required field value is empty", nil))
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := dest.UnmarshalJSON([]byte(tmp)); err != nil {
|
||||||
|
b.setError(b.ErrorFunc(sourceParam, []string{tmp}, "failed to bind field value to json.Unmarshaler interface", err))
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// TextUnmarshaler binds parameter to destination implementing encoding.TextUnmarshaler interface
|
||||||
|
func (b *ValueBinder) TextUnmarshaler(sourceParam string, dest encoding.TextUnmarshaler) *ValueBinder {
|
||||||
|
if b.failFast && b.errors != nil {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp := b.ValueFunc(sourceParam)
|
||||||
|
if tmp == "" {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := dest.UnmarshalText([]byte(tmp)); err != nil {
|
||||||
|
b.setError(b.ErrorFunc(sourceParam, []string{tmp}, "failed to bind field value to encoding.TextUnmarshaler interface", err))
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustTextUnmarshaler requires parameter value to exist to bind to destination implementing encoding.TextUnmarshaler interface.
|
||||||
|
// Returns error when value does not exist
|
||||||
|
func (b *ValueBinder) MustTextUnmarshaler(sourceParam string, dest encoding.TextUnmarshaler) *ValueBinder {
|
||||||
|
if b.failFast && b.errors != nil {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp := b.ValueFunc(sourceParam)
|
||||||
|
if tmp == "" {
|
||||||
|
b.setError(b.ErrorFunc(sourceParam, []string{tmp}, "required field value is empty", nil))
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := dest.UnmarshalText([]byte(tmp)); err != nil {
|
||||||
|
b.setError(b.ErrorFunc(sourceParam, []string{tmp}, "failed to bind field value to encoding.TextUnmarshaler interface", err))
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
// BindWithDelimiter binds parameter to destination by suitable conversion function.
|
// BindWithDelimiter binds parameter to destination by suitable conversion function.
|
||||||
// Delimiter is used before conversion to split parameter value to separate values
|
// Delimiter is used before conversion to split parameter value to separate values
|
||||||
func (b *ValueBinder) BindWithDelimiter(sourceParam string, dest interface{}, delimiter string) *ValueBinder {
|
func (b *ValueBinder) BindWithDelimiter(sourceParam string, dest interface{}, delimiter string) *ValueBinder {
|
||||||
return b.bindWithDelimiter(sourceParam, dest, delimiter, false)
|
return b.bindWithDelimiter(sourceParam, dest, delimiter, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustBindWithDelimiter requires parameter value to exist to be bind destination by suitable conversion function.
|
// MustBindWithDelimiter requires parameter value to exist to bind destination by suitable conversion function.
|
||||||
// Delimiter is used before conversion to split parameter value to separate values
|
// Delimiter is used before conversion to split parameter value to separate values
|
||||||
func (b *ValueBinder) MustBindWithDelimiter(sourceParam string, dest interface{}, delimiter string) *ValueBinder {
|
func (b *ValueBinder) MustBindWithDelimiter(sourceParam string, dest interface{}, delimiter string) *ValueBinder {
|
||||||
return b.bindWithDelimiter(sourceParam, dest, delimiter, true)
|
return b.bindWithDelimiter(sourceParam, dest, delimiter, true)
|
||||||
@ -376,7 +453,7 @@ func (b *ValueBinder) Int64(sourceParam string, dest *int64) *ValueBinder {
|
|||||||
return b.intValue(sourceParam, dest, 64, false)
|
return b.intValue(sourceParam, dest, 64, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustInt64 requires parameter value to exist to be bind to int64 variable. Returns error when value does not exist
|
// MustInt64 requires parameter value to exist to bind to int64 variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustInt64(sourceParam string, dest *int64) *ValueBinder {
|
func (b *ValueBinder) MustInt64(sourceParam string, dest *int64) *ValueBinder {
|
||||||
return b.intValue(sourceParam, dest, 64, true)
|
return b.intValue(sourceParam, dest, 64, true)
|
||||||
}
|
}
|
||||||
@ -386,7 +463,7 @@ func (b *ValueBinder) Int32(sourceParam string, dest *int32) *ValueBinder {
|
|||||||
return b.intValue(sourceParam, dest, 32, false)
|
return b.intValue(sourceParam, dest, 32, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustInt32 requires parameter value to exist to be bind to int32 variable. Returns error when value does not exist
|
// MustInt32 requires parameter value to exist to bind to int32 variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustInt32(sourceParam string, dest *int32) *ValueBinder {
|
func (b *ValueBinder) MustInt32(sourceParam string, dest *int32) *ValueBinder {
|
||||||
return b.intValue(sourceParam, dest, 32, true)
|
return b.intValue(sourceParam, dest, 32, true)
|
||||||
}
|
}
|
||||||
@ -396,7 +473,7 @@ func (b *ValueBinder) Int16(sourceParam string, dest *int16) *ValueBinder {
|
|||||||
return b.intValue(sourceParam, dest, 16, false)
|
return b.intValue(sourceParam, dest, 16, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustInt16 requires parameter value to exist to be bind to int16 variable. Returns error when value does not exist
|
// MustInt16 requires parameter value to exist to bind to int16 variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustInt16(sourceParam string, dest *int16) *ValueBinder {
|
func (b *ValueBinder) MustInt16(sourceParam string, dest *int16) *ValueBinder {
|
||||||
return b.intValue(sourceParam, dest, 16, true)
|
return b.intValue(sourceParam, dest, 16, true)
|
||||||
}
|
}
|
||||||
@ -406,7 +483,7 @@ func (b *ValueBinder) Int8(sourceParam string, dest *int8) *ValueBinder {
|
|||||||
return b.intValue(sourceParam, dest, 8, false)
|
return b.intValue(sourceParam, dest, 8, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustInt8 requires parameter value to exist to be bind to int8 variable. Returns error when value does not exist
|
// MustInt8 requires parameter value to exist to bind to int8 variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustInt8(sourceParam string, dest *int8) *ValueBinder {
|
func (b *ValueBinder) MustInt8(sourceParam string, dest *int8) *ValueBinder {
|
||||||
return b.intValue(sourceParam, dest, 8, true)
|
return b.intValue(sourceParam, dest, 8, true)
|
||||||
}
|
}
|
||||||
@ -416,7 +493,7 @@ func (b *ValueBinder) Int(sourceParam string, dest *int) *ValueBinder {
|
|||||||
return b.intValue(sourceParam, dest, 0, false)
|
return b.intValue(sourceParam, dest, 0, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustInt requires parameter value to exist to be bind to int variable. Returns error when value does not exist
|
// MustInt requires parameter value to exist to bind to int variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustInt(sourceParam string, dest *int) *ValueBinder {
|
func (b *ValueBinder) MustInt(sourceParam string, dest *int) *ValueBinder {
|
||||||
return b.intValue(sourceParam, dest, 0, true)
|
return b.intValue(sourceParam, dest, 0, true)
|
||||||
}
|
}
|
||||||
@ -544,7 +621,7 @@ func (b *ValueBinder) Int64s(sourceParam string, dest *[]int64) *ValueBinder {
|
|||||||
return b.intsValue(sourceParam, dest, false)
|
return b.intsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustInt64s requires parameter value to exist to be bind to int64 slice variable. Returns error when value does not exist
|
// MustInt64s requires parameter value to exist to bind to int64 slice variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustInt64s(sourceParam string, dest *[]int64) *ValueBinder {
|
func (b *ValueBinder) MustInt64s(sourceParam string, dest *[]int64) *ValueBinder {
|
||||||
return b.intsValue(sourceParam, dest, true)
|
return b.intsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -554,7 +631,7 @@ func (b *ValueBinder) Int32s(sourceParam string, dest *[]int32) *ValueBinder {
|
|||||||
return b.intsValue(sourceParam, dest, false)
|
return b.intsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustInt32s requires parameter value to exist to be bind to int32 slice variable. Returns error when value does not exist
|
// MustInt32s requires parameter value to exist to bind to int32 slice variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustInt32s(sourceParam string, dest *[]int32) *ValueBinder {
|
func (b *ValueBinder) MustInt32s(sourceParam string, dest *[]int32) *ValueBinder {
|
||||||
return b.intsValue(sourceParam, dest, true)
|
return b.intsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -564,7 +641,7 @@ func (b *ValueBinder) Int16s(sourceParam string, dest *[]int16) *ValueBinder {
|
|||||||
return b.intsValue(sourceParam, dest, false)
|
return b.intsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustInt16s requires parameter value to exist to be bind to int16 slice variable. Returns error when value does not exist
|
// MustInt16s requires parameter value to exist to bind to int16 slice variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustInt16s(sourceParam string, dest *[]int16) *ValueBinder {
|
func (b *ValueBinder) MustInt16s(sourceParam string, dest *[]int16) *ValueBinder {
|
||||||
return b.intsValue(sourceParam, dest, true)
|
return b.intsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -574,7 +651,7 @@ func (b *ValueBinder) Int8s(sourceParam string, dest *[]int8) *ValueBinder {
|
|||||||
return b.intsValue(sourceParam, dest, false)
|
return b.intsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustInt8s requires parameter value to exist to be bind to int8 slice variable. Returns error when value does not exist
|
// MustInt8s requires parameter value to exist to bind to int8 slice variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustInt8s(sourceParam string, dest *[]int8) *ValueBinder {
|
func (b *ValueBinder) MustInt8s(sourceParam string, dest *[]int8) *ValueBinder {
|
||||||
return b.intsValue(sourceParam, dest, true)
|
return b.intsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -584,7 +661,7 @@ func (b *ValueBinder) Ints(sourceParam string, dest *[]int) *ValueBinder {
|
|||||||
return b.intsValue(sourceParam, dest, false)
|
return b.intsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustInts requires parameter value to exist to be bind to int slice variable. Returns error when value does not exist
|
// MustInts requires parameter value to exist to bind to int slice variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustInts(sourceParam string, dest *[]int) *ValueBinder {
|
func (b *ValueBinder) MustInts(sourceParam string, dest *[]int) *ValueBinder {
|
||||||
return b.intsValue(sourceParam, dest, true)
|
return b.intsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -594,7 +671,7 @@ func (b *ValueBinder) Uint64(sourceParam string, dest *uint64) *ValueBinder {
|
|||||||
return b.uintValue(sourceParam, dest, 64, false)
|
return b.uintValue(sourceParam, dest, 64, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUint64 requires parameter value to exist to be bind to uint64 variable. Returns error when value does not exist
|
// MustUint64 requires parameter value to exist to bind to uint64 variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustUint64(sourceParam string, dest *uint64) *ValueBinder {
|
func (b *ValueBinder) MustUint64(sourceParam string, dest *uint64) *ValueBinder {
|
||||||
return b.uintValue(sourceParam, dest, 64, true)
|
return b.uintValue(sourceParam, dest, 64, true)
|
||||||
}
|
}
|
||||||
@ -604,7 +681,7 @@ func (b *ValueBinder) Uint32(sourceParam string, dest *uint32) *ValueBinder {
|
|||||||
return b.uintValue(sourceParam, dest, 32, false)
|
return b.uintValue(sourceParam, dest, 32, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUint32 requires parameter value to exist to be bind to uint32 variable. Returns error when value does not exist
|
// MustUint32 requires parameter value to exist to bind to uint32 variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustUint32(sourceParam string, dest *uint32) *ValueBinder {
|
func (b *ValueBinder) MustUint32(sourceParam string, dest *uint32) *ValueBinder {
|
||||||
return b.uintValue(sourceParam, dest, 32, true)
|
return b.uintValue(sourceParam, dest, 32, true)
|
||||||
}
|
}
|
||||||
@ -614,7 +691,7 @@ func (b *ValueBinder) Uint16(sourceParam string, dest *uint16) *ValueBinder {
|
|||||||
return b.uintValue(sourceParam, dest, 16, false)
|
return b.uintValue(sourceParam, dest, 16, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUint16 requires parameter value to exist to be bind to uint16 variable. Returns error when value does not exist
|
// MustUint16 requires parameter value to exist to bind to uint16 variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustUint16(sourceParam string, dest *uint16) *ValueBinder {
|
func (b *ValueBinder) MustUint16(sourceParam string, dest *uint16) *ValueBinder {
|
||||||
return b.uintValue(sourceParam, dest, 16, true)
|
return b.uintValue(sourceParam, dest, 16, true)
|
||||||
}
|
}
|
||||||
@ -624,7 +701,7 @@ func (b *ValueBinder) Uint8(sourceParam string, dest *uint8) *ValueBinder {
|
|||||||
return b.uintValue(sourceParam, dest, 8, false)
|
return b.uintValue(sourceParam, dest, 8, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUint8 requires parameter value to exist to be bind to uint8 variable. Returns error when value does not exist
|
// MustUint8 requires parameter value to exist to bind to uint8 variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustUint8(sourceParam string, dest *uint8) *ValueBinder {
|
func (b *ValueBinder) MustUint8(sourceParam string, dest *uint8) *ValueBinder {
|
||||||
return b.uintValue(sourceParam, dest, 8, true)
|
return b.uintValue(sourceParam, dest, 8, true)
|
||||||
}
|
}
|
||||||
@ -634,7 +711,7 @@ func (b *ValueBinder) Byte(sourceParam string, dest *byte) *ValueBinder {
|
|||||||
return b.uintValue(sourceParam, dest, 8, false)
|
return b.uintValue(sourceParam, dest, 8, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustByte requires parameter value to exist to be bind to byte variable. Returns error when value does not exist
|
// MustByte requires parameter value to exist to bind to byte variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustByte(sourceParam string, dest *byte) *ValueBinder {
|
func (b *ValueBinder) MustByte(sourceParam string, dest *byte) *ValueBinder {
|
||||||
return b.uintValue(sourceParam, dest, 8, true)
|
return b.uintValue(sourceParam, dest, 8, true)
|
||||||
}
|
}
|
||||||
@ -644,7 +721,7 @@ func (b *ValueBinder) Uint(sourceParam string, dest *uint) *ValueBinder {
|
|||||||
return b.uintValue(sourceParam, dest, 0, false)
|
return b.uintValue(sourceParam, dest, 0, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUint requires parameter value to exist to be bind to uint variable. Returns error when value does not exist
|
// MustUint requires parameter value to exist to bind to uint variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustUint(sourceParam string, dest *uint) *ValueBinder {
|
func (b *ValueBinder) MustUint(sourceParam string, dest *uint) *ValueBinder {
|
||||||
return b.uintValue(sourceParam, dest, 0, true)
|
return b.uintValue(sourceParam, dest, 0, true)
|
||||||
}
|
}
|
||||||
@ -772,7 +849,7 @@ func (b *ValueBinder) Uint64s(sourceParam string, dest *[]uint64) *ValueBinder {
|
|||||||
return b.uintsValue(sourceParam, dest, false)
|
return b.uintsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUint64s requires parameter value to exist to be bind to uint64 slice variable. Returns error when value does not exist
|
// MustUint64s requires parameter value to exist to bind to uint64 slice variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustUint64s(sourceParam string, dest *[]uint64) *ValueBinder {
|
func (b *ValueBinder) MustUint64s(sourceParam string, dest *[]uint64) *ValueBinder {
|
||||||
return b.uintsValue(sourceParam, dest, true)
|
return b.uintsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -782,7 +859,7 @@ func (b *ValueBinder) Uint32s(sourceParam string, dest *[]uint32) *ValueBinder {
|
|||||||
return b.uintsValue(sourceParam, dest, false)
|
return b.uintsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUint32s requires parameter value to exist to be bind to uint32 slice variable. Returns error when value does not exist
|
// MustUint32s requires parameter value to exist to bind to uint32 slice variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustUint32s(sourceParam string, dest *[]uint32) *ValueBinder {
|
func (b *ValueBinder) MustUint32s(sourceParam string, dest *[]uint32) *ValueBinder {
|
||||||
return b.uintsValue(sourceParam, dest, true)
|
return b.uintsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -792,7 +869,7 @@ func (b *ValueBinder) Uint16s(sourceParam string, dest *[]uint16) *ValueBinder {
|
|||||||
return b.uintsValue(sourceParam, dest, false)
|
return b.uintsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUint16s requires parameter value to exist to be bind to uint16 slice variable. Returns error when value does not exist
|
// MustUint16s requires parameter value to exist to bind to uint16 slice variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustUint16s(sourceParam string, dest *[]uint16) *ValueBinder {
|
func (b *ValueBinder) MustUint16s(sourceParam string, dest *[]uint16) *ValueBinder {
|
||||||
return b.uintsValue(sourceParam, dest, true)
|
return b.uintsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -802,7 +879,7 @@ func (b *ValueBinder) Uint8s(sourceParam string, dest *[]uint8) *ValueBinder {
|
|||||||
return b.uintsValue(sourceParam, dest, false)
|
return b.uintsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUint8s requires parameter value to exist to be bind to uint8 slice variable. Returns error when value does not exist
|
// MustUint8s requires parameter value to exist to bind to uint8 slice variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustUint8s(sourceParam string, dest *[]uint8) *ValueBinder {
|
func (b *ValueBinder) MustUint8s(sourceParam string, dest *[]uint8) *ValueBinder {
|
||||||
return b.uintsValue(sourceParam, dest, true)
|
return b.uintsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -812,7 +889,7 @@ func (b *ValueBinder) Uints(sourceParam string, dest *[]uint) *ValueBinder {
|
|||||||
return b.uintsValue(sourceParam, dest, false)
|
return b.uintsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUints requires parameter value to exist to be bind to uint slice variable. Returns error when value does not exist
|
// MustUints requires parameter value to exist to bind to uint slice variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustUints(sourceParam string, dest *[]uint) *ValueBinder {
|
func (b *ValueBinder) MustUints(sourceParam string, dest *[]uint) *ValueBinder {
|
||||||
return b.uintsValue(sourceParam, dest, true)
|
return b.uintsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -822,7 +899,7 @@ func (b *ValueBinder) Bool(sourceParam string, dest *bool) *ValueBinder {
|
|||||||
return b.boolValue(sourceParam, dest, false)
|
return b.boolValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustBool requires parameter value to exist to be bind to bool variable. Returns error when value does not exist
|
// MustBool requires parameter value to exist to bind to bool variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustBool(sourceParam string, dest *bool) *ValueBinder {
|
func (b *ValueBinder) MustBool(sourceParam string, dest *bool) *ValueBinder {
|
||||||
return b.boolValue(sourceParam, dest, true)
|
return b.boolValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -887,7 +964,7 @@ func (b *ValueBinder) Bools(sourceParam string, dest *[]bool) *ValueBinder {
|
|||||||
return b.boolsValue(sourceParam, dest, false)
|
return b.boolsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustBools requires parameter values to exist to be bind to slice of bool variables. Returns error when values does not exist
|
// MustBools requires parameter values to exist to bind to slice of bool variables. Returns error when values does not exist
|
||||||
func (b *ValueBinder) MustBools(sourceParam string, dest *[]bool) *ValueBinder {
|
func (b *ValueBinder) MustBools(sourceParam string, dest *[]bool) *ValueBinder {
|
||||||
return b.boolsValue(sourceParam, dest, true)
|
return b.boolsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -897,7 +974,7 @@ func (b *ValueBinder) Float64(sourceParam string, dest *float64) *ValueBinder {
|
|||||||
return b.floatValue(sourceParam, dest, 64, false)
|
return b.floatValue(sourceParam, dest, 64, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustFloat64 requires parameter value to exist to be bind to float64 variable. Returns error when value does not exist
|
// MustFloat64 requires parameter value to exist to bind to float64 variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustFloat64(sourceParam string, dest *float64) *ValueBinder {
|
func (b *ValueBinder) MustFloat64(sourceParam string, dest *float64) *ValueBinder {
|
||||||
return b.floatValue(sourceParam, dest, 64, true)
|
return b.floatValue(sourceParam, dest, 64, true)
|
||||||
}
|
}
|
||||||
@ -907,7 +984,7 @@ func (b *ValueBinder) Float32(sourceParam string, dest *float32) *ValueBinder {
|
|||||||
return b.floatValue(sourceParam, dest, 32, false)
|
return b.floatValue(sourceParam, dest, 32, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustFloat32 requires parameter value to exist to be bind to float32 variable. Returns error when value does not exist
|
// MustFloat32 requires parameter value to exist to bind to float32 variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustFloat32(sourceParam string, dest *float32) *ValueBinder {
|
func (b *ValueBinder) MustFloat32(sourceParam string, dest *float32) *ValueBinder {
|
||||||
return b.floatValue(sourceParam, dest, 32, true)
|
return b.floatValue(sourceParam, dest, 32, true)
|
||||||
}
|
}
|
||||||
@ -992,7 +1069,7 @@ func (b *ValueBinder) Float64s(sourceParam string, dest *[]float64) *ValueBinder
|
|||||||
return b.floatsValue(sourceParam, dest, false)
|
return b.floatsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustFloat64s requires parameter values to exist to be bind to slice of float64 variables. Returns error when values does not exist
|
// MustFloat64s requires parameter values to exist to bind to slice of float64 variables. Returns error when values does not exist
|
||||||
func (b *ValueBinder) MustFloat64s(sourceParam string, dest *[]float64) *ValueBinder {
|
func (b *ValueBinder) MustFloat64s(sourceParam string, dest *[]float64) *ValueBinder {
|
||||||
return b.floatsValue(sourceParam, dest, true)
|
return b.floatsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -1002,7 +1079,7 @@ func (b *ValueBinder) Float32s(sourceParam string, dest *[]float32) *ValueBinder
|
|||||||
return b.floatsValue(sourceParam, dest, false)
|
return b.floatsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustFloat32s requires parameter values to exist to be bind to slice of float32 variables. Returns error when values does not exist
|
// MustFloat32s requires parameter values to exist to bind to slice of float32 variables. Returns error when values does not exist
|
||||||
func (b *ValueBinder) MustFloat32s(sourceParam string, dest *[]float32) *ValueBinder {
|
func (b *ValueBinder) MustFloat32s(sourceParam string, dest *[]float32) *ValueBinder {
|
||||||
return b.floatsValue(sourceParam, dest, true)
|
return b.floatsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -1012,7 +1089,7 @@ func (b *ValueBinder) Time(sourceParam string, dest *time.Time, layout string) *
|
|||||||
return b.time(sourceParam, dest, layout, false)
|
return b.time(sourceParam, dest, layout, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustTime requires parameter value to exist to be bind to time.Time variable. Returns error when value does not exist
|
// MustTime requires parameter value to exist to bind to time.Time variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustTime(sourceParam string, dest *time.Time, layout string) *ValueBinder {
|
func (b *ValueBinder) MustTime(sourceParam string, dest *time.Time, layout string) *ValueBinder {
|
||||||
return b.time(sourceParam, dest, layout, true)
|
return b.time(sourceParam, dest, layout, true)
|
||||||
}
|
}
|
||||||
@ -1043,7 +1120,7 @@ func (b *ValueBinder) Times(sourceParam string, dest *[]time.Time, layout string
|
|||||||
return b.times(sourceParam, dest, layout, false)
|
return b.times(sourceParam, dest, layout, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustTimes requires parameter values to exist to be bind to slice of time.Time variables. Returns error when values does not exist
|
// MustTimes requires parameter values to exist to bind to slice of time.Time variables. Returns error when values does not exist
|
||||||
func (b *ValueBinder) MustTimes(sourceParam string, dest *[]time.Time, layout string) *ValueBinder {
|
func (b *ValueBinder) MustTimes(sourceParam string, dest *[]time.Time, layout string) *ValueBinder {
|
||||||
return b.times(sourceParam, dest, layout, true)
|
return b.times(sourceParam, dest, layout, true)
|
||||||
}
|
}
|
||||||
@ -1084,7 +1161,7 @@ func (b *ValueBinder) Duration(sourceParam string, dest *time.Duration) *ValueBi
|
|||||||
return b.duration(sourceParam, dest, false)
|
return b.duration(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustDuration requires parameter value to exist to be bind to time.Duration variable. Returns error when value does not exist
|
// MustDuration requires parameter value to exist to bind to time.Duration variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustDuration(sourceParam string, dest *time.Duration) *ValueBinder {
|
func (b *ValueBinder) MustDuration(sourceParam string, dest *time.Duration) *ValueBinder {
|
||||||
return b.duration(sourceParam, dest, true)
|
return b.duration(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -1115,7 +1192,7 @@ func (b *ValueBinder) Durations(sourceParam string, dest *[]time.Duration) *Valu
|
|||||||
return b.durationsValue(sourceParam, dest, false)
|
return b.durationsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustDurations requires parameter values to exist to be bind to slice of time.Duration variables. Returns error when values does not exist
|
// MustDurations requires parameter values to exist to bind to slice of time.Duration variables. Returns error when values does not exist
|
||||||
func (b *ValueBinder) MustDurations(sourceParam string, dest *[]time.Duration) *ValueBinder {
|
func (b *ValueBinder) MustDurations(sourceParam string, dest *[]time.Duration) *ValueBinder {
|
||||||
return b.durationsValue(sourceParam, dest, true)
|
return b.durationsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -1161,10 +1238,10 @@ func (b *ValueBinder) durations(sourceParam string, values []string, dest *[]tim
|
|||||||
// Note:
|
// Note:
|
||||||
// * time.Time{} (param is empty) and time.Unix(0,0) (param = "0") are not equal
|
// * time.Time{} (param is empty) and time.Unix(0,0) (param = "0") are not equal
|
||||||
func (b *ValueBinder) UnixTime(sourceParam string, dest *time.Time) *ValueBinder {
|
func (b *ValueBinder) UnixTime(sourceParam string, dest *time.Time) *ValueBinder {
|
||||||
return b.unixTime(sourceParam, dest, false, false)
|
return b.unixTime(sourceParam, dest, false, time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUnixTime requires parameter value to exist to be bind to time.Duration variable (in local Time corresponding
|
// MustUnixTime requires parameter value to exist to bind to time.Duration variable (in local time corresponding
|
||||||
// to the given Unix time). Returns error when value does not exist.
|
// to the given Unix time). Returns error when value does not exist.
|
||||||
//
|
//
|
||||||
// Example: 1609180603 bind to 2020-12-28T18:36:43.000000000+00:00
|
// Example: 1609180603 bind to 2020-12-28T18:36:43.000000000+00:00
|
||||||
@ -1172,10 +1249,31 @@ func (b *ValueBinder) UnixTime(sourceParam string, dest *time.Time) *ValueBinder
|
|||||||
// Note:
|
// Note:
|
||||||
// * time.Time{} (param is empty) and time.Unix(0,0) (param = "0") are not equal
|
// * time.Time{} (param is empty) and time.Unix(0,0) (param = "0") are not equal
|
||||||
func (b *ValueBinder) MustUnixTime(sourceParam string, dest *time.Time) *ValueBinder {
|
func (b *ValueBinder) MustUnixTime(sourceParam string, dest *time.Time) *ValueBinder {
|
||||||
return b.unixTime(sourceParam, dest, true, false)
|
return b.unixTime(sourceParam, dest, true, time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnixTimeNano binds parameter to time.Time variable (in local Time corresponding to the given Unix time in nano second precision).
|
// UnixTimeMilli binds parameter to time.Time variable (in local time corresponding to the given Unix time in millisecond precision).
|
||||||
|
//
|
||||||
|
// Example: 1647184410140 bind to 2022-03-13T15:13:30.140000000+00:00
|
||||||
|
//
|
||||||
|
// Note:
|
||||||
|
// * time.Time{} (param is empty) and time.Unix(0,0) (param = "0") are not equal
|
||||||
|
func (b *ValueBinder) UnixTimeMilli(sourceParam string, dest *time.Time) *ValueBinder {
|
||||||
|
return b.unixTime(sourceParam, dest, false, time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustUnixTimeMilli requires parameter value to exist to bind to time.Duration variable (in local time corresponding
|
||||||
|
// to the given Unix time in millisecond precision). Returns error when value does not exist.
|
||||||
|
//
|
||||||
|
// Example: 1647184410140 bind to 2022-03-13T15:13:30.140000000+00:00
|
||||||
|
//
|
||||||
|
// Note:
|
||||||
|
// * time.Time{} (param is empty) and time.Unix(0,0) (param = "0") are not equal
|
||||||
|
func (b *ValueBinder) MustUnixTimeMilli(sourceParam string, dest *time.Time) *ValueBinder {
|
||||||
|
return b.unixTime(sourceParam, dest, true, time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnixTimeNano binds parameter to time.Time variable (in local time corresponding to the given Unix time in nanosecond precision).
|
||||||
//
|
//
|
||||||
// Example: 1609180603123456789 binds to 2020-12-28T18:36:43.123456789+00:00
|
// Example: 1609180603123456789 binds to 2020-12-28T18:36:43.123456789+00:00
|
||||||
// Example: 1000000000 binds to 1970-01-01T00:00:01.000000000+00:00
|
// Example: 1000000000 binds to 1970-01-01T00:00:01.000000000+00:00
|
||||||
@ -1185,10 +1283,10 @@ func (b *ValueBinder) MustUnixTime(sourceParam string, dest *time.Time) *ValueBi
|
|||||||
// * time.Time{} (param is empty) and time.Unix(0,0) (param = "0") are not equal
|
// * time.Time{} (param is empty) and time.Unix(0,0) (param = "0") are not equal
|
||||||
// * Javascript's Number type only has about 53 bits of precision (Number.MAX_SAFE_INTEGER = 9007199254740991). Compare it to 1609180603123456789 in example.
|
// * Javascript's Number type only has about 53 bits of precision (Number.MAX_SAFE_INTEGER = 9007199254740991). Compare it to 1609180603123456789 in example.
|
||||||
func (b *ValueBinder) UnixTimeNano(sourceParam string, dest *time.Time) *ValueBinder {
|
func (b *ValueBinder) UnixTimeNano(sourceParam string, dest *time.Time) *ValueBinder {
|
||||||
return b.unixTime(sourceParam, dest, false, true)
|
return b.unixTime(sourceParam, dest, false, time.Nanosecond)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUnixTimeNano requires parameter value to exist to be bind to time.Duration variable (in local Time corresponding
|
// MustUnixTimeNano requires parameter value to exist to bind to time.Duration variable (in local Time corresponding
|
||||||
// to the given Unix time value in nano second precision). Returns error when value does not exist.
|
// to the given Unix time value in nano second precision). Returns error when value does not exist.
|
||||||
//
|
//
|
||||||
// Example: 1609180603123456789 binds to 2020-12-28T18:36:43.123456789+00:00
|
// Example: 1609180603123456789 binds to 2020-12-28T18:36:43.123456789+00:00
|
||||||
@ -1199,10 +1297,10 @@ func (b *ValueBinder) UnixTimeNano(sourceParam string, dest *time.Time) *ValueBi
|
|||||||
// * time.Time{} (param is empty) and time.Unix(0,0) (param = "0") are not equal
|
// * time.Time{} (param is empty) and time.Unix(0,0) (param = "0") are not equal
|
||||||
// * Javascript's Number type only has about 53 bits of precision (Number.MAX_SAFE_INTEGER = 9007199254740991). Compare it to 1609180603123456789 in example.
|
// * Javascript's Number type only has about 53 bits of precision (Number.MAX_SAFE_INTEGER = 9007199254740991). Compare it to 1609180603123456789 in example.
|
||||||
func (b *ValueBinder) MustUnixTimeNano(sourceParam string, dest *time.Time) *ValueBinder {
|
func (b *ValueBinder) MustUnixTimeNano(sourceParam string, dest *time.Time) *ValueBinder {
|
||||||
return b.unixTime(sourceParam, dest, true, true)
|
return b.unixTime(sourceParam, dest, true, time.Nanosecond)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *ValueBinder) unixTime(sourceParam string, dest *time.Time, valueMustExist bool, isNano bool) *ValueBinder {
|
func (b *ValueBinder) unixTime(sourceParam string, dest *time.Time, valueMustExist bool, precision time.Duration) *ValueBinder {
|
||||||
if b.failFast && b.errors != nil {
|
if b.failFast && b.errors != nil {
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
@ -1221,10 +1319,13 @@ func (b *ValueBinder) unixTime(sourceParam string, dest *time.Time, valueMustExi
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
if isNano {
|
switch precision {
|
||||||
*dest = time.Unix(0, n)
|
case time.Second:
|
||||||
} else {
|
|
||||||
*dest = time.Unix(n, 0)
|
*dest = time.Unix(n, 0)
|
||||||
|
case time.Millisecond:
|
||||||
|
*dest = time.Unix(n/1e3, (n%1e3)*1e6) // TODO: time.UnixMilli(n) exists since Go1.17 switch to that when min version allows
|
||||||
|
case time.Nanosecond:
|
||||||
|
*dest = time.Unix(0, n)
|
||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
34
vendor/github.com/labstack/echo/v4/context.go
generated
vendored
34
vendor/github.com/labstack/echo/v4/context.go
generated
vendored
@ -9,8 +9,6 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
@ -183,7 +181,7 @@ type (
|
|||||||
// Logger returns the `Logger` instance.
|
// Logger returns the `Logger` instance.
|
||||||
Logger() Logger
|
Logger() Logger
|
||||||
|
|
||||||
// Set the logger
|
// SetLogger Set the logger
|
||||||
SetLogger(l Logger)
|
SetLogger(l Logger)
|
||||||
|
|
||||||
// Echo returns the `Echo` instance.
|
// Echo returns the `Echo` instance.
|
||||||
@ -210,6 +208,13 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ContextKeyHeaderAllow is set by Router for getting value for `Allow` header in later stages of handler call chain.
|
||||||
|
// Allow header is mandatory for status 405 (method not found) and useful for OPTIONS method requests.
|
||||||
|
// It is added to context only when Router does not find matching method handler for request.
|
||||||
|
ContextKeyHeaderAllow = "echo_header_allow"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultMemory = 32 << 20 // 32 MB
|
defaultMemory = 32 << 20 // 32 MB
|
||||||
indexPage = "index.html"
|
indexPage = "index.html"
|
||||||
@ -562,29 +567,6 @@ func (c *context) Stream(code int, contentType string, r io.Reader) (err error)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) File(file string) (err error) {
|
|
||||||
f, err := os.Open(file)
|
|
||||||
if err != nil {
|
|
||||||
return NotFoundHandler(c)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
fi, _ := f.Stat()
|
|
||||||
if fi.IsDir() {
|
|
||||||
file = filepath.Join(file, indexPage)
|
|
||||||
f, err = os.Open(file)
|
|
||||||
if err != nil {
|
|
||||||
return NotFoundHandler(c)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
if fi, err = f.Stat(); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
http.ServeContent(c.Response(), c.Request(), fi.Name(), fi.ModTime(), f)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *context) Attachment(file, name string) error {
|
func (c *context) Attachment(file, name string) error {
|
||||||
return c.contentDisposition(file, name, "attachment")
|
return c.contentDisposition(file, name, "attachment")
|
||||||
}
|
}
|
||||||
|
49
vendor/github.com/labstack/echo/v4/context_fs.go
generated
vendored
Normal file
49
vendor/github.com/labstack/echo/v4/context_fs.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package echo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"io/fs"
|
||||||
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *context) File(file string) error {
|
||||||
|
return fsFile(c, file, c.echo.Filesystem)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileFS serves file from given file system.
|
||||||
|
//
|
||||||
|
// When dealing with `embed.FS` use `fs := echo.MustSubFS(fs, "rootDirectory") to create sub fs which uses necessary
|
||||||
|
// prefix for directory path. This is necessary as `//go:embed assets/images` embeds files with paths
|
||||||
|
// including `assets/images` as their prefix.
|
||||||
|
func (c *context) FileFS(file string, filesystem fs.FS) error {
|
||||||
|
return fsFile(c, file, filesystem)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fsFile(c Context, file string, filesystem fs.FS) error {
|
||||||
|
f, err := filesystem.Open(file)
|
||||||
|
if err != nil {
|
||||||
|
return ErrNotFound
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
fi, _ := f.Stat()
|
||||||
|
if fi.IsDir() {
|
||||||
|
file = filepath.ToSlash(filepath.Join(file, indexPage)) // ToSlash is necessary for Windows. fs.Open and os.Open are different in that aspect.
|
||||||
|
f, err = filesystem.Open(file)
|
||||||
|
if err != nil {
|
||||||
|
return ErrNotFound
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
if fi, err = f.Stat(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ff, ok := f.(io.ReadSeeker)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("file does not implement io.ReadSeeker")
|
||||||
|
}
|
||||||
|
http.ServeContent(c.Response(), c.Request(), fi.Name(), fi.ModTime(), ff)
|
||||||
|
return nil
|
||||||
|
}
|
116
vendor/github.com/labstack/echo/v4/echo.go
generated
vendored
116
vendor/github.com/labstack/echo/v4/echo.go
generated
vendored
@ -47,9 +47,6 @@ import (
|
|||||||
stdLog "log"
|
stdLog "log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
@ -66,6 +63,7 @@ import (
|
|||||||
type (
|
type (
|
||||||
// Echo is the top-level framework instance.
|
// Echo is the top-level framework instance.
|
||||||
Echo struct {
|
Echo struct {
|
||||||
|
filesystem
|
||||||
common
|
common
|
||||||
// startupMutex is mutex to lock Echo instance access during server configuration and startup. Useful for to get
|
// startupMutex is mutex to lock Echo instance access during server configuration and startup. Useful for to get
|
||||||
// listener address info (on which interface/port was listener binded) without having data races.
|
// listener address info (on which interface/port was listener binded) without having data races.
|
||||||
@ -77,7 +75,6 @@ type (
|
|||||||
maxParam *int
|
maxParam *int
|
||||||
router *Router
|
router *Router
|
||||||
routers map[string]*Router
|
routers map[string]*Router
|
||||||
notFoundHandler HandlerFunc
|
|
||||||
pool sync.Pool
|
pool sync.Pool
|
||||||
Server *http.Server
|
Server *http.Server
|
||||||
TLSServer *http.Server
|
TLSServer *http.Server
|
||||||
@ -113,10 +110,10 @@ type (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MiddlewareFunc defines a function to process middleware.
|
// MiddlewareFunc defines a function to process middleware.
|
||||||
MiddlewareFunc func(HandlerFunc) HandlerFunc
|
MiddlewareFunc func(next HandlerFunc) HandlerFunc
|
||||||
|
|
||||||
// HandlerFunc defines a function to serve HTTP requests.
|
// HandlerFunc defines a function to serve HTTP requests.
|
||||||
HandlerFunc func(Context) error
|
HandlerFunc func(c Context) error
|
||||||
|
|
||||||
// HTTPErrorHandler is a centralized HTTP error handler.
|
// HTTPErrorHandler is a centralized HTTP error handler.
|
||||||
HTTPErrorHandler func(error, Context)
|
HTTPErrorHandler func(error, Context)
|
||||||
@ -186,12 +183,18 @@ const (
|
|||||||
PROPFIND = "PROPFIND"
|
PROPFIND = "PROPFIND"
|
||||||
// REPORT Method can be used to get information about a resource, see rfc 3253
|
// REPORT Method can be used to get information about a resource, see rfc 3253
|
||||||
REPORT = "REPORT"
|
REPORT = "REPORT"
|
||||||
|
// RouteNotFound is special method type for routes handling "route not found" (404) cases
|
||||||
|
RouteNotFound = "echo_route_not_found"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Headers
|
// Headers
|
||||||
const (
|
const (
|
||||||
HeaderAccept = "Accept"
|
HeaderAccept = "Accept"
|
||||||
HeaderAcceptEncoding = "Accept-Encoding"
|
HeaderAcceptEncoding = "Accept-Encoding"
|
||||||
|
// HeaderAllow is the name of the "Allow" header field used to list the set of methods
|
||||||
|
// advertised as supported by the target resource. Returning an Allow header is mandatory
|
||||||
|
// for status 405 (method not found) and useful for the OPTIONS method in responses.
|
||||||
|
// See RFC 7231: https://datatracker.ietf.org/doc/html/rfc7231#section-7.4.1
|
||||||
HeaderAllow = "Allow"
|
HeaderAllow = "Allow"
|
||||||
HeaderAuthorization = "Authorization"
|
HeaderAuthorization = "Authorization"
|
||||||
HeaderContentDisposition = "Content-Disposition"
|
HeaderContentDisposition = "Content-Disposition"
|
||||||
@ -203,6 +206,7 @@ const (
|
|||||||
HeaderIfModifiedSince = "If-Modified-Since"
|
HeaderIfModifiedSince = "If-Modified-Since"
|
||||||
HeaderLastModified = "Last-Modified"
|
HeaderLastModified = "Last-Modified"
|
||||||
HeaderLocation = "Location"
|
HeaderLocation = "Location"
|
||||||
|
HeaderRetryAfter = "Retry-After"
|
||||||
HeaderUpgrade = "Upgrade"
|
HeaderUpgrade = "Upgrade"
|
||||||
HeaderVary = "Vary"
|
HeaderVary = "Vary"
|
||||||
HeaderWWWAuthenticate = "WWW-Authenticate"
|
HeaderWWWAuthenticate = "WWW-Authenticate"
|
||||||
@ -212,11 +216,14 @@ const (
|
|||||||
HeaderXForwardedSsl = "X-Forwarded-Ssl"
|
HeaderXForwardedSsl = "X-Forwarded-Ssl"
|
||||||
HeaderXUrlScheme = "X-Url-Scheme"
|
HeaderXUrlScheme = "X-Url-Scheme"
|
||||||
HeaderXHTTPMethodOverride = "X-HTTP-Method-Override"
|
HeaderXHTTPMethodOverride = "X-HTTP-Method-Override"
|
||||||
HeaderXRealIP = "X-Real-IP"
|
HeaderXRealIP = "X-Real-Ip"
|
||||||
HeaderXRequestID = "X-Request-ID"
|
HeaderXRequestID = "X-Request-Id"
|
||||||
|
HeaderXCorrelationID = "X-Correlation-Id"
|
||||||
HeaderXRequestedWith = "X-Requested-With"
|
HeaderXRequestedWith = "X-Requested-With"
|
||||||
HeaderServer = "Server"
|
HeaderServer = "Server"
|
||||||
HeaderOrigin = "Origin"
|
HeaderOrigin = "Origin"
|
||||||
|
HeaderCacheControl = "Cache-Control"
|
||||||
|
HeaderConnection = "Connection"
|
||||||
|
|
||||||
// Access control
|
// Access control
|
||||||
HeaderAccessControlRequestMethod = "Access-Control-Request-Method"
|
HeaderAccessControlRequestMethod = "Access-Control-Request-Method"
|
||||||
@ -241,7 +248,7 @@ const (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// Version of Echo
|
// Version of Echo
|
||||||
Version = "4.5.0"
|
Version = "4.9.0"
|
||||||
website = "https://echo.labstack.com"
|
website = "https://echo.labstack.com"
|
||||||
// http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo
|
// http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo
|
||||||
banner = `
|
banner = `
|
||||||
@ -301,6 +308,12 @@ var (
|
|||||||
}
|
}
|
||||||
|
|
||||||
MethodNotAllowedHandler = func(c Context) error {
|
MethodNotAllowedHandler = func(c Context) error {
|
||||||
|
// See RFC 7231 section 7.4.1: An origin server MUST generate an Allow field in a 405 (Method Not Allowed)
|
||||||
|
// response and MAY do so in any other response. For disabled resources an empty Allow header may be returned
|
||||||
|
routerAllowMethods, ok := c.Get(ContextKeyHeaderAllow).(string)
|
||||||
|
if ok && routerAllowMethods != "" {
|
||||||
|
c.Response().Header().Set(HeaderAllow, routerAllowMethods)
|
||||||
|
}
|
||||||
return ErrMethodNotAllowed
|
return ErrMethodNotAllowed
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -308,6 +321,7 @@ var (
|
|||||||
// New creates an instance of Echo.
|
// New creates an instance of Echo.
|
||||||
func New() (e *Echo) {
|
func New() (e *Echo) {
|
||||||
e = &Echo{
|
e = &Echo{
|
||||||
|
filesystem: createFilesystem(),
|
||||||
Server: new(http.Server),
|
Server: new(http.Server),
|
||||||
TLSServer: new(http.Server),
|
TLSServer: new(http.Server),
|
||||||
AutoTLSManager: autocert.Manager{
|
AutoTLSManager: autocert.Manager{
|
||||||
@ -357,7 +371,17 @@ func (e *Echo) Routers() map[string]*Router {
|
|||||||
|
|
||||||
// DefaultHTTPErrorHandler is the default HTTP error handler. It sends a JSON response
|
// DefaultHTTPErrorHandler is the default HTTP error handler. It sends a JSON response
|
||||||
// with status code.
|
// with status code.
|
||||||
|
//
|
||||||
|
// NOTE: In case errors happens in middleware call-chain that is returning from handler (which did not return an error).
|
||||||
|
// When handler has already sent response (ala c.JSON()) and there is error in middleware that is returning from
|
||||||
|
// handler. Then the error that global error handler received will be ignored because we have already "commited" the
|
||||||
|
// response and status code header has been sent to the client.
|
||||||
func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) {
|
func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) {
|
||||||
|
|
||||||
|
if c.Response().Committed {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
he, ok := err.(*HTTPError)
|
he, ok := err.(*HTTPError)
|
||||||
if ok {
|
if ok {
|
||||||
if he.Internal != nil {
|
if he.Internal != nil {
|
||||||
@ -384,7 +408,6 @@ func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send response
|
// Send response
|
||||||
if !c.Response().Committed {
|
|
||||||
if c.Request().Method == http.MethodHead { // Issue #608
|
if c.Request().Method == http.MethodHead { // Issue #608
|
||||||
err = c.NoContent(he.Code)
|
err = c.NoContent(he.Code)
|
||||||
} else {
|
} else {
|
||||||
@ -394,7 +417,6 @@ func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) {
|
|||||||
e.Logger.Error(err)
|
e.Logger.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Pre adds middleware to the chain which is run before router.
|
// Pre adds middleware to the chain which is run before router.
|
||||||
func (e *Echo) Pre(middleware ...MiddlewareFunc) {
|
func (e *Echo) Pre(middleware ...MiddlewareFunc) {
|
||||||
@ -460,8 +482,21 @@ func (e *Echo) TRACE(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
|
|||||||
return e.Add(http.MethodTrace, path, h, m...)
|
return e.Add(http.MethodTrace, path, h, m...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Any registers a new route for all HTTP methods and path with matching handler
|
// RouteNotFound registers a special-case route which is executed when no other route is found (i.e. HTTP 404 cases)
|
||||||
|
// for current request URL.
|
||||||
|
// Path supports static and named/any parameters just like other http method is defined. Generally path is ended with
|
||||||
|
// wildcard/match-any character (`/*`, `/download/*` etc).
|
||||||
|
//
|
||||||
|
// Example: `e.RouteNotFound("/*", func(c echo.Context) error { return c.NoContent(http.StatusNotFound) })`
|
||||||
|
func (e *Echo) RouteNotFound(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
|
||||||
|
return e.Add(RouteNotFound, path, h, m...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any registers a new route for all HTTP methods (supported by Echo) and path with matching handler
|
||||||
// in the router with optional route-level middleware.
|
// in the router with optional route-level middleware.
|
||||||
|
//
|
||||||
|
// Note: this method only adds specific set of supported HTTP methods as handler and is not true
|
||||||
|
// "catch-any-arbitrary-method" way of matching requests.
|
||||||
func (e *Echo) Any(path string, handler HandlerFunc, middleware ...MiddlewareFunc) []*Route {
|
func (e *Echo) Any(path string, handler HandlerFunc, middleware ...MiddlewareFunc) []*Route {
|
||||||
routes := make([]*Route, len(methods))
|
routes := make([]*Route, len(methods))
|
||||||
for i, m := range methods {
|
for i, m := range methods {
|
||||||
@ -480,50 +515,6 @@ func (e *Echo) Match(methods []string, path string, handler HandlerFunc, middlew
|
|||||||
return routes
|
return routes
|
||||||
}
|
}
|
||||||
|
|
||||||
// Static registers a new route with path prefix to serve static files from the
|
|
||||||
// provided root directory.
|
|
||||||
func (e *Echo) Static(prefix, root string) *Route {
|
|
||||||
if root == "" {
|
|
||||||
root = "." // For security we want to restrict to CWD.
|
|
||||||
}
|
|
||||||
return e.static(prefix, root, e.GET)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (common) static(prefix, root string, get func(string, HandlerFunc, ...MiddlewareFunc) *Route) *Route {
|
|
||||||
h := func(c Context) error {
|
|
||||||
p, err := url.PathUnescape(c.Param("*"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
name := filepath.Join(root, filepath.Clean("/"+p)) // "/"+ for security
|
|
||||||
fi, err := os.Stat(name)
|
|
||||||
if err != nil {
|
|
||||||
// The access path does not exist
|
|
||||||
return NotFoundHandler(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the request is for a directory and does not end with "/"
|
|
||||||
p = c.Request().URL.Path // path must not be empty.
|
|
||||||
if fi.IsDir() && p[len(p)-1] != '/' {
|
|
||||||
// Redirect to ends with "/"
|
|
||||||
return c.Redirect(http.StatusMovedPermanently, p+"/")
|
|
||||||
}
|
|
||||||
return c.File(name)
|
|
||||||
}
|
|
||||||
// Handle added routes based on trailing slash:
|
|
||||||
// /prefix => exact route "/prefix" + any route "/prefix/*"
|
|
||||||
// /prefix/ => only any route "/prefix/*"
|
|
||||||
if prefix != "" {
|
|
||||||
if prefix[len(prefix)-1] == '/' {
|
|
||||||
// Only add any route for intentional trailing slash
|
|
||||||
return get(prefix+"*", h)
|
|
||||||
}
|
|
||||||
get(prefix, h)
|
|
||||||
}
|
|
||||||
return get(prefix+"/*", h)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (common) file(path, file string, get func(string, HandlerFunc, ...MiddlewareFunc) *Route,
|
func (common) file(path, file string, get func(string, HandlerFunc, ...MiddlewareFunc) *Route,
|
||||||
m ...MiddlewareFunc) *Route {
|
m ...MiddlewareFunc) *Route {
|
||||||
return get(path, func(c Context) error {
|
return get(path, func(c Context) error {
|
||||||
@ -539,6 +530,7 @@ func (e *Echo) File(path, file string, m ...MiddlewareFunc) *Route {
|
|||||||
func (e *Echo) add(host, method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route {
|
func (e *Echo) add(host, method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route {
|
||||||
name := handlerName(handler)
|
name := handlerName(handler)
|
||||||
router := e.findRouter(host)
|
router := e.findRouter(host)
|
||||||
|
// FIXME: when handler+middleware are both nil ... make it behave like handler removal
|
||||||
router.Add(method, path, func(c Context) error {
|
router.Add(method, path, func(c Context) error {
|
||||||
h := applyMiddleware(handler, middleware...)
|
h := applyMiddleware(handler, middleware...)
|
||||||
return h(c)
|
return h(c)
|
||||||
@ -634,7 +626,7 @@ func (e *Echo) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
// Acquire context
|
// Acquire context
|
||||||
c := e.pool.Get().(*context)
|
c := e.pool.Get().(*context)
|
||||||
c.Reset(r, w)
|
c.Reset(r, w)
|
||||||
h := NotFoundHandler
|
var h func(Context) error
|
||||||
|
|
||||||
if e.premiddleware == nil {
|
if e.premiddleware == nil {
|
||||||
e.findRouter(r.Host).Find(r.Method, GetPath(r), c)
|
e.findRouter(r.Host).Find(r.Method, GetPath(r), c)
|
||||||
@ -756,7 +748,7 @@ func (e *Echo) StartServer(s *http.Server) (err error) {
|
|||||||
return s.Serve(e.Listener)
|
return s.Serve(e.Listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Echo) configureServer(s *http.Server) (err error) {
|
func (e *Echo) configureServer(s *http.Server) error {
|
||||||
// Setup
|
// Setup
|
||||||
e.colorer.SetOutput(e.Logger.Output())
|
e.colorer.SetOutput(e.Logger.Output())
|
||||||
s.ErrorLog = e.StdLogger
|
s.ErrorLog = e.StdLogger
|
||||||
@ -771,10 +763,11 @@ func (e *Echo) configureServer(s *http.Server) (err error) {
|
|||||||
|
|
||||||
if s.TLSConfig == nil {
|
if s.TLSConfig == nil {
|
||||||
if e.Listener == nil {
|
if e.Listener == nil {
|
||||||
e.Listener, err = newListener(s.Addr, e.ListenerNetwork)
|
l, err := newListener(s.Addr, e.ListenerNetwork)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
e.Listener = l
|
||||||
}
|
}
|
||||||
if !e.HidePort {
|
if !e.HidePort {
|
||||||
e.colorer.Printf("⇨ http server started on %s\n", e.colorer.Green(e.Listener.Addr()))
|
e.colorer.Printf("⇨ http server started on %s\n", e.colorer.Green(e.Listener.Addr()))
|
||||||
@ -815,7 +808,7 @@ func (e *Echo) TLSListenerAddr() net.Addr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// StartH2CServer starts a custom http/2 server with h2c (HTTP/2 Cleartext).
|
// StartH2CServer starts a custom http/2 server with h2c (HTTP/2 Cleartext).
|
||||||
func (e *Echo) StartH2CServer(address string, h2s *http2.Server) (err error) {
|
func (e *Echo) StartH2CServer(address string, h2s *http2.Server) error {
|
||||||
e.startupMutex.Lock()
|
e.startupMutex.Lock()
|
||||||
// Setup
|
// Setup
|
||||||
s := e.Server
|
s := e.Server
|
||||||
@ -832,11 +825,12 @@ func (e *Echo) StartH2CServer(address string, h2s *http2.Server) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if e.Listener == nil {
|
if e.Listener == nil {
|
||||||
e.Listener, err = newListener(s.Addr, e.ListenerNetwork)
|
l, err := newListener(s.Addr, e.ListenerNetwork)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e.startupMutex.Unlock()
|
e.startupMutex.Unlock()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
e.Listener = l
|
||||||
}
|
}
|
||||||
if !e.HidePort {
|
if !e.HidePort {
|
||||||
e.colorer.Printf("⇨ http server started on %s\n", e.colorer.Green(e.Listener.Addr()))
|
e.colorer.Printf("⇨ http server started on %s\n", e.colorer.Green(e.Listener.Addr()))
|
||||||
|
175
vendor/github.com/labstack/echo/v4/echo_fs.go
generated
vendored
Normal file
175
vendor/github.com/labstack/echo/v4/echo_fs.go
generated
vendored
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
package echo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type filesystem struct {
|
||||||
|
// Filesystem is file system used by Static and File handlers to access files.
|
||||||
|
// Defaults to os.DirFS(".")
|
||||||
|
//
|
||||||
|
// When dealing with `embed.FS` use `fs := echo.MustSubFS(fs, "rootDirectory") to create sub fs which uses necessary
|
||||||
|
// prefix for directory path. This is necessary as `//go:embed assets/images` embeds files with paths
|
||||||
|
// including `assets/images` as their prefix.
|
||||||
|
Filesystem fs.FS
|
||||||
|
}
|
||||||
|
|
||||||
|
func createFilesystem() filesystem {
|
||||||
|
return filesystem{
|
||||||
|
Filesystem: newDefaultFS(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Static registers a new route with path prefix to serve static files from the provided root directory.
|
||||||
|
func (e *Echo) Static(pathPrefix, fsRoot string) *Route {
|
||||||
|
subFs := MustSubFS(e.Filesystem, fsRoot)
|
||||||
|
return e.Add(
|
||||||
|
http.MethodGet,
|
||||||
|
pathPrefix+"*",
|
||||||
|
StaticDirectoryHandler(subFs, false),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StaticFS registers a new route with path prefix to serve static files from the provided file system.
|
||||||
|
//
|
||||||
|
// When dealing with `embed.FS` use `fs := echo.MustSubFS(fs, "rootDirectory") to create sub fs which uses necessary
|
||||||
|
// prefix for directory path. This is necessary as `//go:embed assets/images` embeds files with paths
|
||||||
|
// including `assets/images` as their prefix.
|
||||||
|
func (e *Echo) StaticFS(pathPrefix string, filesystem fs.FS) *Route {
|
||||||
|
return e.Add(
|
||||||
|
http.MethodGet,
|
||||||
|
pathPrefix+"*",
|
||||||
|
StaticDirectoryHandler(filesystem, false),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StaticDirectoryHandler creates handler function to serve files from provided file system
|
||||||
|
// When disablePathUnescaping is set then file name from path is not unescaped and is served as is.
|
||||||
|
func StaticDirectoryHandler(fileSystem fs.FS, disablePathUnescaping bool) HandlerFunc {
|
||||||
|
return func(c Context) error {
|
||||||
|
p := c.Param("*")
|
||||||
|
if !disablePathUnescaping { // when router is already unescaping we do not want to do is twice
|
||||||
|
tmpPath, err := url.PathUnescape(p)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to unescape path variable: %w", err)
|
||||||
|
}
|
||||||
|
p = tmpPath
|
||||||
|
}
|
||||||
|
|
||||||
|
// fs.FS.Open() already assumes that file names are relative to FS root path and considers name with prefix `/` as invalid
|
||||||
|
name := filepath.ToSlash(filepath.Clean(strings.TrimPrefix(p, "/")))
|
||||||
|
fi, err := fs.Stat(fileSystem, name)
|
||||||
|
if err != nil {
|
||||||
|
return ErrNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the request is for a directory and does not end with "/"
|
||||||
|
p = c.Request().URL.Path // path must not be empty.
|
||||||
|
if fi.IsDir() && len(p) > 0 && p[len(p)-1] != '/' {
|
||||||
|
// Redirect to ends with "/"
|
||||||
|
return c.Redirect(http.StatusMovedPermanently, sanitizeURI(p+"/"))
|
||||||
|
}
|
||||||
|
return fsFile(c, name, fileSystem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileFS registers a new route with path to serve file from the provided file system.
|
||||||
|
func (e *Echo) FileFS(path, file string, filesystem fs.FS, m ...MiddlewareFunc) *Route {
|
||||||
|
return e.GET(path, StaticFileHandler(file, filesystem), m...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StaticFileHandler creates handler function to serve file from provided file system
|
||||||
|
func StaticFileHandler(file string, filesystem fs.FS) HandlerFunc {
|
||||||
|
return func(c Context) error {
|
||||||
|
return fsFile(c, file, filesystem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// defaultFS exists to preserve pre v4.7.0 behaviour where files were open by `os.Open`.
|
||||||
|
// v4.7 introduced `echo.Filesystem` field which is Go1.16+ `fs.Fs` interface.
|
||||||
|
// Difference between `os.Open` and `fs.Open` is that FS does not allow opening path that start with `.`, `..` or `/`
|
||||||
|
// etc. For example previously you could have `../images` in your application but `fs := os.DirFS("./")` would not
|
||||||
|
// allow you to use `fs.Open("../images")` and this would break all old applications that rely on being able to
|
||||||
|
// traverse up from current executable run path.
|
||||||
|
// NB: private because you really should use fs.FS implementation instances
|
||||||
|
type defaultFS struct {
|
||||||
|
prefix string
|
||||||
|
fs fs.FS
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDefaultFS() *defaultFS {
|
||||||
|
dir, _ := os.Getwd()
|
||||||
|
return &defaultFS{
|
||||||
|
prefix: dir,
|
||||||
|
fs: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs defaultFS) Open(name string) (fs.File, error) {
|
||||||
|
if fs.fs == nil {
|
||||||
|
return os.Open(name)
|
||||||
|
}
|
||||||
|
return fs.fs.Open(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func subFS(currentFs fs.FS, root string) (fs.FS, error) {
|
||||||
|
root = filepath.ToSlash(filepath.Clean(root)) // note: fs.FS operates only with slashes. `ToSlash` is necessary for Windows
|
||||||
|
if dFS, ok := currentFs.(*defaultFS); ok {
|
||||||
|
// we need to make exception for `defaultFS` instances as it interprets root prefix differently from fs.FS.
|
||||||
|
// fs.Fs.Open does not like relative paths ("./", "../") and absolute paths at all but prior echo.Filesystem we
|
||||||
|
// were able to use paths like `./myfile.log`, `/etc/hosts` and these would work fine with `os.Open` but not with fs.Fs
|
||||||
|
if isRelativePath(root) {
|
||||||
|
root = filepath.Join(dFS.prefix, root)
|
||||||
|
}
|
||||||
|
return &defaultFS{
|
||||||
|
prefix: root,
|
||||||
|
fs: os.DirFS(root),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
return fs.Sub(currentFs, root)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isRelativePath(path string) bool {
|
||||||
|
if path == "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if path[0] == '/' {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if runtime.GOOS == "windows" && strings.IndexByte(path, ':') != -1 {
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file?redirectedfrom=MSDN#file_and_directory_names
|
||||||
|
// https://docs.microsoft.com/en-us/dotnet/standard/io/file-path-formats
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustSubFS creates sub FS from current filesystem or panic on failure.
|
||||||
|
// Panic happens when `fsRoot` contains invalid path according to `fs.ValidPath` rules.
|
||||||
|
//
|
||||||
|
// MustSubFS is helpful when dealing with `embed.FS` because for example `//go:embed assets/images` embeds files with
|
||||||
|
// paths including `assets/images` as their prefix. In that case use `fs := echo.MustSubFS(fs, "rootDirectory") to
|
||||||
|
// create sub fs which uses necessary prefix for directory path.
|
||||||
|
func MustSubFS(currentFs fs.FS, fsRoot string) fs.FS {
|
||||||
|
subFs, err := subFS(currentFs, fsRoot)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("can not create sub FS, invalid root given, err: %w", err))
|
||||||
|
}
|
||||||
|
return subFs
|
||||||
|
}
|
||||||
|
|
||||||
|
func sanitizeURI(uri string) string {
|
||||||
|
// double slash `\\`, `//` or even `\/` is absolute uri for browsers and by redirecting request to that uri
|
||||||
|
// we are vulnerable to open redirect attack. so replace all slashes from the beginning with single slash
|
||||||
|
if len(uri) > 1 && (uri[0] == '\\' || uri[0] == '/') && (uri[1] == '\\' || uri[1] == '/') {
|
||||||
|
uri = "/" + strings.TrimLeft(uri, `/\`)
|
||||||
|
}
|
||||||
|
return uri
|
||||||
|
}
|
12
vendor/github.com/labstack/echo/v4/group.go
generated
vendored
12
vendor/github.com/labstack/echo/v4/group.go
generated
vendored
@ -102,16 +102,18 @@ func (g *Group) Group(prefix string, middleware ...MiddlewareFunc) (sg *Group) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Static implements `Echo#Static()` for sub-routes within the Group.
|
|
||||||
func (g *Group) Static(prefix, root string) {
|
|
||||||
g.static(prefix, root, g.GET)
|
|
||||||
}
|
|
||||||
|
|
||||||
// File implements `Echo#File()` for sub-routes within the Group.
|
// File implements `Echo#File()` for sub-routes within the Group.
|
||||||
func (g *Group) File(path, file string) {
|
func (g *Group) File(path, file string) {
|
||||||
g.file(path, file, g.GET)
|
g.file(path, file, g.GET)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RouteNotFound implements `Echo#RouteNotFound()` for sub-routes within the Group.
|
||||||
|
//
|
||||||
|
// Example: `g.RouteNotFound("/*", func(c echo.Context) error { return c.NoContent(http.StatusNotFound) })`
|
||||||
|
func (g *Group) RouteNotFound(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
|
||||||
|
return g.Add(RouteNotFound, path, h, m...)
|
||||||
|
}
|
||||||
|
|
||||||
// Add implements `Echo#Add()` for sub-routes within the Group.
|
// Add implements `Echo#Add()` for sub-routes within the Group.
|
||||||
func (g *Group) Add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route {
|
func (g *Group) Add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route {
|
||||||
// Combine into a new slice to avoid accidentally passing the same slice for
|
// Combine into a new slice to avoid accidentally passing the same slice for
|
||||||
|
30
vendor/github.com/labstack/echo/v4/group_fs.go
generated
vendored
Normal file
30
vendor/github.com/labstack/echo/v4/group_fs.go
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package echo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/fs"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Static implements `Echo#Static()` for sub-routes within the Group.
|
||||||
|
func (g *Group) Static(pathPrefix, fsRoot string) {
|
||||||
|
subFs := MustSubFS(g.echo.Filesystem, fsRoot)
|
||||||
|
g.StaticFS(pathPrefix, subFs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StaticFS implements `Echo#StaticFS()` for sub-routes within the Group.
|
||||||
|
//
|
||||||
|
// When dealing with `embed.FS` use `fs := echo.MustSubFS(fs, "rootDirectory") to create sub fs which uses necessary
|
||||||
|
// prefix for directory path. This is necessary as `//go:embed assets/images` embeds files with paths
|
||||||
|
// including `assets/images` as their prefix.
|
||||||
|
func (g *Group) StaticFS(pathPrefix string, filesystem fs.FS) {
|
||||||
|
g.Add(
|
||||||
|
http.MethodGet,
|
||||||
|
pathPrefix+"*",
|
||||||
|
StaticDirectoryHandler(filesystem, false),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileFS implements `Echo#FileFS()` for sub-routes within the Group.
|
||||||
|
func (g *Group) FileFS(path, file string, filesystem fs.FS, m ...MiddlewareFunc) *Route {
|
||||||
|
return g.GET(path, StaticFileHandler(file, filesystem), m...)
|
||||||
|
}
|
138
vendor/github.com/labstack/echo/v4/ip.go
generated
vendored
138
vendor/github.com/labstack/echo/v4/ip.go
generated
vendored
@ -6,6 +6,130 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
By: https://github.com/tmshn (See: https://github.com/labstack/echo/pull/1478 , https://github.com/labstack/echox/pull/134 )
|
||||||
|
Source: https://echo.labstack.com/guide/ip-address/
|
||||||
|
|
||||||
|
IP address plays fundamental role in HTTP; it's used for access control, auditing, geo-based access analysis and more.
|
||||||
|
Echo provides handy method [`Context#RealIP()`](https://godoc.org/github.com/labstack/echo#Context) for that.
|
||||||
|
|
||||||
|
However, it is not trivial to retrieve the _real_ IP address from requests especially when you put L7 proxies before the application.
|
||||||
|
In such situation, _real_ IP needs to be relayed on HTTP layer from proxies to your app, but you must not trust HTTP headers unconditionally.
|
||||||
|
Otherwise, you might give someone a chance of deceiving you. **A security risk!**
|
||||||
|
|
||||||
|
To retrieve IP address reliably/securely, you must let your application be aware of the entire architecture of your infrastructure.
|
||||||
|
In Echo, this can be done by configuring `Echo#IPExtractor` appropriately.
|
||||||
|
This guides show you why and how.
|
||||||
|
|
||||||
|
> Note: if you dont' set `Echo#IPExtractor` explicitly, Echo fallback to legacy behavior, which is not a good choice.
|
||||||
|
|
||||||
|
Let's start from two questions to know the right direction:
|
||||||
|
|
||||||
|
1. Do you put any HTTP (L7) proxy in front of the application?
|
||||||
|
- It includes both cloud solutions (such as AWS ALB or GCP HTTP LB) and OSS ones (such as Nginx, Envoy or Istio ingress gateway).
|
||||||
|
2. If yes, what HTTP header do your proxies use to pass client IP to the application?
|
||||||
|
|
||||||
|
## Case 1. With no proxy
|
||||||
|
|
||||||
|
If you put no proxy (e.g.: directory facing to the internet), all you need to (and have to) see is IP address from network layer.
|
||||||
|
Any HTTP header is untrustable because the clients have full control what headers to be set.
|
||||||
|
|
||||||
|
In this case, use `echo.ExtractIPDirect()`.
|
||||||
|
|
||||||
|
```go
|
||||||
|
e.IPExtractor = echo.ExtractIPDirect()
|
||||||
|
```
|
||||||
|
|
||||||
|
## Case 2. With proxies using `X-Forwarded-For` header
|
||||||
|
|
||||||
|
[`X-Forwared-For` (XFF)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) is the popular header
|
||||||
|
to relay clients' IP addresses.
|
||||||
|
At each hop on the proxies, they append the request IP address at the end of the header.
|
||||||
|
|
||||||
|
Following example diagram illustrates this behavior.
|
||||||
|
|
||||||
|
```text
|
||||||
|
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
|
||||||
|
│ "Origin" │───────────>│ Proxy 1 │───────────>│ Proxy 2 │───────────>│ Your app │
|
||||||
|
│ (IP: a) │ │ (IP: b) │ │ (IP: c) │ │ │
|
||||||
|
└──────────┘ └──────────┘ └──────────┘ └──────────┘
|
||||||
|
|
||||||
|
Case 1.
|
||||||
|
XFF: "" "a" "a, b"
|
||||||
|
~~~~~~
|
||||||
|
Case 2.
|
||||||
|
XFF: "x" "x, a" "x, a, b"
|
||||||
|
~~~~~~~~~
|
||||||
|
↑ What your app will see
|
||||||
|
```
|
||||||
|
|
||||||
|
In this case, use **first _untrustable_ IP reading from right**. Never use first one reading from left, as it is
|
||||||
|
configurable by client. Here "trustable" means "you are sure the IP address belongs to your infrastructre".
|
||||||
|
In above example, if `b` and `c` are trustable, the IP address of the client is `a` for both cases, never be `x`.
|
||||||
|
|
||||||
|
In Echo, use `ExtractIPFromXFFHeader(...TrustOption)`.
|
||||||
|
|
||||||
|
```go
|
||||||
|
e.IPExtractor = echo.ExtractIPFromXFFHeader()
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, it trusts internal IP addresses (loopback, link-local unicast, private-use and unique local address
|
||||||
|
from [RFC6890](https://tools.ietf.org/html/rfc6890), [RFC4291](https://tools.ietf.org/html/rfc4291) and
|
||||||
|
[RFC4193](https://tools.ietf.org/html/rfc4193)).
|
||||||
|
To control this behavior, use [`TrustOption`](https://godoc.org/github.com/labstack/echo#TrustOption)s.
|
||||||
|
|
||||||
|
E.g.:
|
||||||
|
|
||||||
|
```go
|
||||||
|
e.IPExtractor = echo.ExtractIPFromXFFHeader(
|
||||||
|
TrustLinkLocal(false),
|
||||||
|
TrustIPRanges(lbIPRange),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
- Ref: https://godoc.org/github.com/labstack/echo#TrustOption
|
||||||
|
|
||||||
|
## Case 3. With proxies using `X-Real-IP` header
|
||||||
|
|
||||||
|
`X-Real-IP` is another HTTP header to relay clients' IP addresses, but it carries only one address unlike XFF.
|
||||||
|
|
||||||
|
If your proxies set this header, use `ExtractIPFromRealIPHeader(...TrustOption)`.
|
||||||
|
|
||||||
|
```go
|
||||||
|
e.IPExtractor = echo.ExtractIPFromRealIPHeader()
|
||||||
|
```
|
||||||
|
|
||||||
|
Again, it trusts internal IP addresses by default (loopback, link-local unicast, private-use and unique local address
|
||||||
|
from [RFC6890](https://tools.ietf.org/html/rfc6890), [RFC4291](https://tools.ietf.org/html/rfc4291) and
|
||||||
|
[RFC4193](https://tools.ietf.org/html/rfc4193)).
|
||||||
|
To control this behavior, use [`TrustOption`](https://godoc.org/github.com/labstack/echo#TrustOption)s.
|
||||||
|
|
||||||
|
- Ref: https://godoc.org/github.com/labstack/echo#TrustOption
|
||||||
|
|
||||||
|
> **Never forget** to configure the outermost proxy (i.e.; at the edge of your infrastructure) **not to pass through incoming headers**.
|
||||||
|
> Otherwise there is a chance of fraud, as it is what clients can control.
|
||||||
|
|
||||||
|
## About default behavior
|
||||||
|
|
||||||
|
In default behavior, Echo sees all of first XFF header, X-Real-IP header and IP from network layer.
|
||||||
|
|
||||||
|
As you might already notice, after reading this article, this is not good.
|
||||||
|
Sole reason this is default is just backward compatibility.
|
||||||
|
|
||||||
|
## Private IP ranges
|
||||||
|
|
||||||
|
See: https://en.wikipedia.org/wiki/Private_network
|
||||||
|
|
||||||
|
Private IPv4 address ranges (RFC 1918):
|
||||||
|
* 10.0.0.0 – 10.255.255.255 (24-bit block)
|
||||||
|
* 172.16.0.0 – 172.31.255.255 (20-bit block)
|
||||||
|
* 192.168.0.0 – 192.168.255.255 (16-bit block)
|
||||||
|
|
||||||
|
Private IPv6 address ranges:
|
||||||
|
* fc00::/7 address block = RFC 4193 Unique Local Addresses (ULA)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
type ipChecker struct {
|
type ipChecker struct {
|
||||||
trustLoopback bool
|
trustLoopback bool
|
||||||
trustLinkLocal bool
|
trustLinkLocal bool
|
||||||
@ -52,6 +176,7 @@ func newIPChecker(configs []TrustOption) *ipChecker {
|
|||||||
return checker
|
return checker
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Go1.16+ added `ip.IsPrivate()` but until that use this implementation
|
||||||
func isPrivateIPRange(ip net.IP) bool {
|
func isPrivateIPRange(ip net.IP) bool {
|
||||||
if ip4 := ip.To4(); ip4 != nil {
|
if ip4 := ip.To4(); ip4 != nil {
|
||||||
return ip4[0] == 10 ||
|
return ip4[0] == 10 ||
|
||||||
@ -87,25 +212,26 @@ type IPExtractor func(*http.Request) string
|
|||||||
// ExtractIPDirect extracts IP address using actual IP address.
|
// ExtractIPDirect extracts IP address using actual IP address.
|
||||||
// Use this if your server faces to internet directory (i.e.: uses no proxy).
|
// Use this if your server faces to internet directory (i.e.: uses no proxy).
|
||||||
func ExtractIPDirect() IPExtractor {
|
func ExtractIPDirect() IPExtractor {
|
||||||
return func(req *http.Request) string {
|
return extractIP
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractIP(req *http.Request) string {
|
||||||
ra, _, _ := net.SplitHostPort(req.RemoteAddr)
|
ra, _, _ := net.SplitHostPort(req.RemoteAddr)
|
||||||
return ra
|
return ra
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractIPFromRealIPHeader extracts IP address using x-real-ip header.
|
// ExtractIPFromRealIPHeader extracts IP address using x-real-ip header.
|
||||||
// Use this if you put proxy which uses this header.
|
// Use this if you put proxy which uses this header.
|
||||||
func ExtractIPFromRealIPHeader(options ...TrustOption) IPExtractor {
|
func ExtractIPFromRealIPHeader(options ...TrustOption) IPExtractor {
|
||||||
checker := newIPChecker(options)
|
checker := newIPChecker(options)
|
||||||
return func(req *http.Request) string {
|
return func(req *http.Request) string {
|
||||||
directIP := ExtractIPDirect()(req)
|
|
||||||
realIP := req.Header.Get(HeaderXRealIP)
|
realIP := req.Header.Get(HeaderXRealIP)
|
||||||
if realIP != "" {
|
if realIP != "" {
|
||||||
if ip := net.ParseIP(directIP); ip != nil && checker.trust(ip) {
|
if ip := net.ParseIP(realIP); ip != nil && checker.trust(ip) {
|
||||||
return realIP
|
return realIP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return directIP
|
return extractIP(req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +241,7 @@ func ExtractIPFromRealIPHeader(options ...TrustOption) IPExtractor {
|
|||||||
func ExtractIPFromXFFHeader(options ...TrustOption) IPExtractor {
|
func ExtractIPFromXFFHeader(options ...TrustOption) IPExtractor {
|
||||||
checker := newIPChecker(options)
|
checker := newIPChecker(options)
|
||||||
return func(req *http.Request) string {
|
return func(req *http.Request) string {
|
||||||
directIP := ExtractIPDirect()(req)
|
directIP := extractIP(req)
|
||||||
xffs := req.Header[HeaderXForwardedFor]
|
xffs := req.Header[HeaderXForwardedFor]
|
||||||
if len(xffs) == 0 {
|
if len(xffs) == 0 {
|
||||||
return directIP
|
return directIP
|
||||||
|
6
vendor/github.com/labstack/echo/v4/middleware/basic_auth.go
generated
vendored
6
vendor/github.com/labstack/echo/v4/middleware/basic_auth.go
generated
vendored
@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
@ -74,10 +75,13 @@ func BasicAuthWithConfig(config BasicAuthConfig) echo.MiddlewareFunc {
|
|||||||
l := len(basic)
|
l := len(basic)
|
||||||
|
|
||||||
if len(auth) > l+1 && strings.EqualFold(auth[:l], basic) {
|
if len(auth) > l+1 && strings.EqualFold(auth[:l], basic) {
|
||||||
|
// Invalid base64 shouldn't be treated as error
|
||||||
|
// instead should be treated as invalid client input
|
||||||
b, err := base64.StdEncoding.DecodeString(auth[l+1:])
|
b, err := base64.StdEncoding.DecodeString(auth[l+1:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return echo.NewHTTPError(http.StatusBadRequest).SetInternal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cred := string(b)
|
cred := string(b)
|
||||||
for i := 0; i < len(cred); i++ {
|
for i := 0; i < len(cred); i++ {
|
||||||
if cred[i] == ':' {
|
if cred[i] == ':' {
|
||||||
|
9
vendor/github.com/labstack/echo/v4/middleware/compress.go
generated
vendored
9
vendor/github.com/labstack/echo/v4/middleware/compress.go
generated
vendored
@ -27,6 +27,7 @@ type (
|
|||||||
gzipResponseWriter struct {
|
gzipResponseWriter struct {
|
||||||
io.Writer
|
io.Writer
|
||||||
http.ResponseWriter
|
http.ResponseWriter
|
||||||
|
wroteBody bool
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -78,8 +79,9 @@ func GzipWithConfig(config GzipConfig) echo.MiddlewareFunc {
|
|||||||
}
|
}
|
||||||
rw := res.Writer
|
rw := res.Writer
|
||||||
w.Reset(rw)
|
w.Reset(rw)
|
||||||
|
grw := &gzipResponseWriter{Writer: w, ResponseWriter: rw}
|
||||||
defer func() {
|
defer func() {
|
||||||
if res.Size == 0 {
|
if !grw.wroteBody {
|
||||||
if res.Header().Get(echo.HeaderContentEncoding) == gzipScheme {
|
if res.Header().Get(echo.HeaderContentEncoding) == gzipScheme {
|
||||||
res.Header().Del(echo.HeaderContentEncoding)
|
res.Header().Del(echo.HeaderContentEncoding)
|
||||||
}
|
}
|
||||||
@ -92,7 +94,6 @@ func GzipWithConfig(config GzipConfig) echo.MiddlewareFunc {
|
|||||||
w.Close()
|
w.Close()
|
||||||
pool.Put(w)
|
pool.Put(w)
|
||||||
}()
|
}()
|
||||||
grw := &gzipResponseWriter{Writer: w, ResponseWriter: rw}
|
|
||||||
res.Writer = grw
|
res.Writer = grw
|
||||||
}
|
}
|
||||||
return next(c)
|
return next(c)
|
||||||
@ -101,9 +102,6 @@ func GzipWithConfig(config GzipConfig) echo.MiddlewareFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *gzipResponseWriter) WriteHeader(code int) {
|
func (w *gzipResponseWriter) WriteHeader(code int) {
|
||||||
if code == http.StatusNoContent { // Issue #489
|
|
||||||
w.ResponseWriter.Header().Del(echo.HeaderContentEncoding)
|
|
||||||
}
|
|
||||||
w.Header().Del(echo.HeaderContentLength) // Issue #444
|
w.Header().Del(echo.HeaderContentLength) // Issue #444
|
||||||
w.ResponseWriter.WriteHeader(code)
|
w.ResponseWriter.WriteHeader(code)
|
||||||
}
|
}
|
||||||
@ -112,6 +110,7 @@ func (w *gzipResponseWriter) Write(b []byte) (int, error) {
|
|||||||
if w.Header().Get(echo.HeaderContentType) == "" {
|
if w.Header().Get(echo.HeaderContentType) == "" {
|
||||||
w.Header().Set(echo.HeaderContentType, http.DetectContentType(b))
|
w.Header().Set(echo.HeaderContentType, http.DetectContentType(b))
|
||||||
}
|
}
|
||||||
|
w.wroteBody = true
|
||||||
return w.Writer.Write(b)
|
return w.Writer.Write(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
141
vendor/github.com/labstack/echo/v4/middleware/cors.go
generated
vendored
141
vendor/github.com/labstack/echo/v4/middleware/cors.go
generated
vendored
@ -15,42 +15,85 @@ type (
|
|||||||
// Skipper defines a function to skip middleware.
|
// Skipper defines a function to skip middleware.
|
||||||
Skipper Skipper
|
Skipper Skipper
|
||||||
|
|
||||||
// AllowOrigin defines a list of origins that may access the resource.
|
// AllowOrigins determines the value of the Access-Control-Allow-Origin
|
||||||
|
// response header. This header defines a list of origins that may access the
|
||||||
|
// resource. The wildcard characters '*' and '?' are supported and are
|
||||||
|
// converted to regex fragments '.*' and '.' accordingly.
|
||||||
|
//
|
||||||
|
// Security: use extreme caution when handling the origin, and carefully
|
||||||
|
// validate any logic. Remember that attackers may register hostile domain names.
|
||||||
|
// See https://blog.portswigger.net/2016/10/exploiting-cors-misconfigurations-for.html
|
||||||
|
//
|
||||||
// Optional. Default value []string{"*"}.
|
// Optional. Default value []string{"*"}.
|
||||||
|
//
|
||||||
|
// See also: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
|
||||||
AllowOrigins []string `yaml:"allow_origins"`
|
AllowOrigins []string `yaml:"allow_origins"`
|
||||||
|
|
||||||
// AllowOriginFunc is a custom function to validate the origin. It takes the
|
// AllowOriginFunc is a custom function to validate the origin. It takes the
|
||||||
// origin as an argument and returns true if allowed or false otherwise. If
|
// origin as an argument and returns true if allowed or false otherwise. If
|
||||||
// an error is returned, it is returned by the handler. If this option is
|
// an error is returned, it is returned by the handler. If this option is
|
||||||
// set, AllowOrigins is ignored.
|
// set, AllowOrigins is ignored.
|
||||||
|
//
|
||||||
|
// Security: use extreme caution when handling the origin, and carefully
|
||||||
|
// validate any logic. Remember that attackers may register hostile domain names.
|
||||||
|
// See https://blog.portswigger.net/2016/10/exploiting-cors-misconfigurations-for.html
|
||||||
|
//
|
||||||
// Optional.
|
// Optional.
|
||||||
AllowOriginFunc func(origin string) (bool, error) `yaml:"allow_origin_func"`
|
AllowOriginFunc func(origin string) (bool, error) `yaml:"allow_origin_func"`
|
||||||
|
|
||||||
// AllowMethods defines a list methods allowed when accessing the resource.
|
// AllowMethods determines the value of the Access-Control-Allow-Methods
|
||||||
// This is used in response to a preflight request.
|
// response header. This header specified the list of methods allowed when
|
||||||
|
// accessing the resource. This is used in response to a preflight request.
|
||||||
|
//
|
||||||
// Optional. Default value DefaultCORSConfig.AllowMethods.
|
// Optional. Default value DefaultCORSConfig.AllowMethods.
|
||||||
|
// If `allowMethods` is left empty, this middleware will fill for preflight
|
||||||
|
// request `Access-Control-Allow-Methods` header value
|
||||||
|
// from `Allow` header that echo.Router set into context.
|
||||||
|
//
|
||||||
|
// See also: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods
|
||||||
AllowMethods []string `yaml:"allow_methods"`
|
AllowMethods []string `yaml:"allow_methods"`
|
||||||
|
|
||||||
// AllowHeaders defines a list of request headers that can be used when
|
// AllowHeaders determines the value of the Access-Control-Allow-Headers
|
||||||
// making the actual request. This is in response to a preflight request.
|
// response header. This header is used in response to a preflight request to
|
||||||
|
// indicate which HTTP headers can be used when making the actual request.
|
||||||
|
//
|
||||||
// Optional. Default value []string{}.
|
// Optional. Default value []string{}.
|
||||||
|
//
|
||||||
|
// See also: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers
|
||||||
AllowHeaders []string `yaml:"allow_headers"`
|
AllowHeaders []string `yaml:"allow_headers"`
|
||||||
|
|
||||||
// AllowCredentials indicates whether or not the response to the request
|
// AllowCredentials determines the value of the
|
||||||
// can be exposed when the credentials flag is true. When used as part of
|
// Access-Control-Allow-Credentials response header. This header indicates
|
||||||
// a response to a preflight request, this indicates whether or not the
|
// whether or not the response to the request can be exposed when the
|
||||||
// actual request can be made using credentials.
|
// credentials mode (Request.credentials) is true. When used as part of a
|
||||||
// Optional. Default value false.
|
// response to a preflight request, this indicates whether or not the actual
|
||||||
|
// request can be made using credentials. See also
|
||||||
|
// [MDN: Access-Control-Allow-Credentials].
|
||||||
|
//
|
||||||
|
// Optional. Default value false, in which case the header is not set.
|
||||||
|
//
|
||||||
|
// Security: avoid using `AllowCredentials = true` with `AllowOrigins = *`.
|
||||||
|
// See "Exploiting CORS misconfigurations for Bitcoins and bounties",
|
||||||
|
// https://blog.portswigger.net/2016/10/exploiting-cors-misconfigurations-for.html
|
||||||
|
//
|
||||||
|
// See also: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials
|
||||||
AllowCredentials bool `yaml:"allow_credentials"`
|
AllowCredentials bool `yaml:"allow_credentials"`
|
||||||
|
|
||||||
// ExposeHeaders defines a whitelist headers that clients are allowed to
|
// ExposeHeaders determines the value of Access-Control-Expose-Headers, which
|
||||||
// access.
|
// defines a list of headers that clients are allowed to access.
|
||||||
// Optional. Default value []string{}.
|
//
|
||||||
|
// Optional. Default value []string{}, in which case the header is not set.
|
||||||
|
//
|
||||||
|
// See also: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Header
|
||||||
ExposeHeaders []string `yaml:"expose_headers"`
|
ExposeHeaders []string `yaml:"expose_headers"`
|
||||||
|
|
||||||
// MaxAge indicates how long (in seconds) the results of a preflight request
|
// MaxAge determines the value of the Access-Control-Max-Age response header.
|
||||||
// can be cached.
|
// This header indicates how long (in seconds) the results of a preflight
|
||||||
// Optional. Default value 0.
|
// request can be cached.
|
||||||
|
//
|
||||||
|
// Optional. Default value 0. The header is set only if MaxAge > 0.
|
||||||
|
//
|
||||||
|
// See also: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age
|
||||||
MaxAge int `yaml:"max_age"`
|
MaxAge int `yaml:"max_age"`
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -65,13 +108,22 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// CORS returns a Cross-Origin Resource Sharing (CORS) middleware.
|
// CORS returns a Cross-Origin Resource Sharing (CORS) middleware.
|
||||||
// See: https://developer.mozilla.org/en/docs/Web/HTTP/Access_control_CORS
|
// See also [MDN: Cross-Origin Resource Sharing (CORS)].
|
||||||
|
//
|
||||||
|
// Security: Poorly configured CORS can compromise security because it allows
|
||||||
|
// relaxation of the browser's Same-Origin policy. See [Exploiting CORS
|
||||||
|
// misconfigurations for Bitcoins and bounties] and [Portswigger: Cross-origin
|
||||||
|
// resource sharing (CORS)] for more details.
|
||||||
|
//
|
||||||
|
// [MDN: Cross-Origin Resource Sharing (CORS)]: https://developer.mozilla.org/en/docs/Web/HTTP/Access_control_CORS
|
||||||
|
// [Exploiting CORS misconfigurations for Bitcoins and bounties]: https://blog.portswigger.net/2016/10/exploiting-cors-misconfigurations-for.html
|
||||||
|
// [Portswigger: Cross-origin resource sharing (CORS)]: https://portswigger.net/web-security/cors
|
||||||
func CORS() echo.MiddlewareFunc {
|
func CORS() echo.MiddlewareFunc {
|
||||||
return CORSWithConfig(DefaultCORSConfig)
|
return CORSWithConfig(DefaultCORSConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CORSWithConfig returns a CORS middleware with config.
|
// CORSWithConfig returns a CORS middleware with config.
|
||||||
// See: `CORS()`.
|
// See: [CORS].
|
||||||
func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {
|
func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {
|
||||||
// Defaults
|
// Defaults
|
||||||
if config.Skipper == nil {
|
if config.Skipper == nil {
|
||||||
@ -80,7 +132,9 @@ func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {
|
|||||||
if len(config.AllowOrigins) == 0 {
|
if len(config.AllowOrigins) == 0 {
|
||||||
config.AllowOrigins = DefaultCORSConfig.AllowOrigins
|
config.AllowOrigins = DefaultCORSConfig.AllowOrigins
|
||||||
}
|
}
|
||||||
|
hasCustomAllowMethods := true
|
||||||
if len(config.AllowMethods) == 0 {
|
if len(config.AllowMethods) == 0 {
|
||||||
|
hasCustomAllowMethods = false
|
||||||
config.AllowMethods = DefaultCORSConfig.AllowMethods
|
config.AllowMethods = DefaultCORSConfig.AllowMethods
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,10 +163,28 @@ func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {
|
|||||||
origin := req.Header.Get(echo.HeaderOrigin)
|
origin := req.Header.Get(echo.HeaderOrigin)
|
||||||
allowOrigin := ""
|
allowOrigin := ""
|
||||||
|
|
||||||
preflight := req.Method == http.MethodOptions
|
|
||||||
res.Header().Add(echo.HeaderVary, echo.HeaderOrigin)
|
res.Header().Add(echo.HeaderVary, echo.HeaderOrigin)
|
||||||
|
|
||||||
// No Origin provided
|
// Preflight request is an OPTIONS request, using three HTTP request headers: Access-Control-Request-Method,
|
||||||
|
// Access-Control-Request-Headers, and the Origin header. See: https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request
|
||||||
|
// For simplicity we just consider method type and later `Origin` header.
|
||||||
|
preflight := req.Method == http.MethodOptions
|
||||||
|
|
||||||
|
// Although router adds special handler in case of OPTIONS method we avoid calling next for OPTIONS in this middleware
|
||||||
|
// as CORS requests do not have cookies / authentication headers by default, so we could get stuck in auth
|
||||||
|
// middlewares by calling next(c).
|
||||||
|
// But we still want to send `Allow` header as response in case of Non-CORS OPTIONS request as router default
|
||||||
|
// handler does.
|
||||||
|
routerAllowMethods := ""
|
||||||
|
if preflight {
|
||||||
|
tmpAllowMethods, ok := c.Get(echo.ContextKeyHeaderAllow).(string)
|
||||||
|
if ok && tmpAllowMethods != "" {
|
||||||
|
routerAllowMethods = tmpAllowMethods
|
||||||
|
c.Response().Header().Set(echo.HeaderAllow, routerAllowMethods)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No Origin provided. This is (probably) not request from actual browser - proceed executing middleware chain
|
||||||
if origin == "" {
|
if origin == "" {
|
||||||
if !preflight {
|
if !preflight {
|
||||||
return next(c)
|
return next(c)
|
||||||
@ -145,19 +217,15 @@ func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check allowed origin patterns
|
checkPatterns := false
|
||||||
for _, re := range allowOriginPatterns {
|
|
||||||
if allowOrigin == "" {
|
if allowOrigin == "" {
|
||||||
didx := strings.Index(origin, "://")
|
// to avoid regex cost by invalid (long) domains (253 is domain name max limit)
|
||||||
if didx == -1 {
|
if len(origin) <= (253+3+5) && strings.Contains(origin, "://") {
|
||||||
continue
|
checkPatterns = true
|
||||||
}
|
}
|
||||||
domAuth := origin[didx+3:]
|
|
||||||
// to avoid regex cost by invalid long domain
|
|
||||||
if len(domAuth) > 253 {
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
if checkPatterns {
|
||||||
|
for _, re := range allowOriginPatterns {
|
||||||
if match, _ := regexp.MatchString(re, origin); match {
|
if match, _ := regexp.MatchString(re, origin); match {
|
||||||
allowOrigin = origin
|
allowOrigin = origin
|
||||||
break
|
break
|
||||||
@ -174,12 +242,13 @@ func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {
|
|||||||
return c.NoContent(http.StatusNoContent)
|
return c.NoContent(http.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simple request
|
|
||||||
if !preflight {
|
|
||||||
res.Header().Set(echo.HeaderAccessControlAllowOrigin, allowOrigin)
|
res.Header().Set(echo.HeaderAccessControlAllowOrigin, allowOrigin)
|
||||||
if config.AllowCredentials {
|
if config.AllowCredentials {
|
||||||
res.Header().Set(echo.HeaderAccessControlAllowCredentials, "true")
|
res.Header().Set(echo.HeaderAccessControlAllowCredentials, "true")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Simple request
|
||||||
|
if !preflight {
|
||||||
if exposeHeaders != "" {
|
if exposeHeaders != "" {
|
||||||
res.Header().Set(echo.HeaderAccessControlExposeHeaders, exposeHeaders)
|
res.Header().Set(echo.HeaderAccessControlExposeHeaders, exposeHeaders)
|
||||||
}
|
}
|
||||||
@ -189,11 +258,13 @@ func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {
|
|||||||
// Preflight request
|
// Preflight request
|
||||||
res.Header().Add(echo.HeaderVary, echo.HeaderAccessControlRequestMethod)
|
res.Header().Add(echo.HeaderVary, echo.HeaderAccessControlRequestMethod)
|
||||||
res.Header().Add(echo.HeaderVary, echo.HeaderAccessControlRequestHeaders)
|
res.Header().Add(echo.HeaderVary, echo.HeaderAccessControlRequestHeaders)
|
||||||
res.Header().Set(echo.HeaderAccessControlAllowOrigin, allowOrigin)
|
|
||||||
|
if !hasCustomAllowMethods && routerAllowMethods != "" {
|
||||||
|
res.Header().Set(echo.HeaderAccessControlAllowMethods, routerAllowMethods)
|
||||||
|
} else {
|
||||||
res.Header().Set(echo.HeaderAccessControlAllowMethods, allowMethods)
|
res.Header().Set(echo.HeaderAccessControlAllowMethods, allowMethods)
|
||||||
if config.AllowCredentials {
|
|
||||||
res.Header().Set(echo.HeaderAccessControlAllowCredentials, "true")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if allowHeaders != "" {
|
if allowHeaders != "" {
|
||||||
res.Header().Set(echo.HeaderAccessControlAllowHeaders, allowHeaders)
|
res.Header().Set(echo.HeaderAccessControlAllowHeaders, allowHeaders)
|
||||||
} else {
|
} else {
|
||||||
|
120
vendor/github.com/labstack/echo/v4/middleware/csrf.go
generated
vendored
120
vendor/github.com/labstack/echo/v4/middleware/csrf.go
generated
vendored
@ -2,9 +2,7 @@ package middleware
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
@ -21,13 +19,15 @@ type (
|
|||||||
TokenLength uint8 `yaml:"token_length"`
|
TokenLength uint8 `yaml:"token_length"`
|
||||||
// Optional. Default value 32.
|
// Optional. Default value 32.
|
||||||
|
|
||||||
// TokenLookup is a string in the form of "<source>:<key>" that is used
|
// TokenLookup is a string in the form of "<source>:<name>" or "<source>:<name>,<source>:<name>" that is used
|
||||||
// to extract token from the request.
|
// to extract token from the request.
|
||||||
// Optional. Default value "header:X-CSRF-Token".
|
// Optional. Default value "header:X-CSRF-Token".
|
||||||
// Possible values:
|
// Possible values:
|
||||||
// - "header:<name>"
|
// - "header:<name>" or "header:<name>:<cut-prefix>"
|
||||||
// - "form:<name>"
|
|
||||||
// - "query:<name>"
|
// - "query:<name>"
|
||||||
|
// - "form:<name>"
|
||||||
|
// Multiple sources example:
|
||||||
|
// - "header:X-CSRF-Token,query:csrf"
|
||||||
TokenLookup string `yaml:"token_lookup"`
|
TokenLookup string `yaml:"token_lookup"`
|
||||||
|
|
||||||
// Context key to store generated CSRF token into context.
|
// Context key to store generated CSRF token into context.
|
||||||
@ -61,13 +61,18 @@ type (
|
|||||||
// Indicates SameSite mode of the CSRF cookie.
|
// Indicates SameSite mode of the CSRF cookie.
|
||||||
// Optional. Default value SameSiteDefaultMode.
|
// Optional. Default value SameSiteDefaultMode.
|
||||||
CookieSameSite http.SameSite `yaml:"cookie_same_site"`
|
CookieSameSite http.SameSite `yaml:"cookie_same_site"`
|
||||||
|
|
||||||
|
// ErrorHandler defines a function which is executed for returning custom errors.
|
||||||
|
ErrorHandler CSRFErrorHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
// csrfTokenExtractor defines a function that takes `echo.Context` and returns
|
// CSRFErrorHandler is a function which is executed for creating custom errors.
|
||||||
// either a token or an error.
|
CSRFErrorHandler func(err error, c echo.Context) error
|
||||||
csrfTokenExtractor func(echo.Context) (string, error)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ErrCSRFInvalid is returned when CSRF check fails
|
||||||
|
var ErrCSRFInvalid = echo.NewHTTPError(http.StatusForbidden, "invalid csrf token")
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// DefaultCSRFConfig is the default CSRF middleware config.
|
// DefaultCSRFConfig is the default CSRF middleware config.
|
||||||
DefaultCSRFConfig = CSRFConfig{
|
DefaultCSRFConfig = CSRFConfig{
|
||||||
@ -114,14 +119,9 @@ func CSRFWithConfig(config CSRFConfig) echo.MiddlewareFunc {
|
|||||||
config.CookieSecure = true
|
config.CookieSecure = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize
|
extractors, err := createExtractors(config.TokenLookup, "")
|
||||||
parts := strings.Split(config.TokenLookup, ":")
|
if err != nil {
|
||||||
extractor := csrfTokenFromHeader(parts[1])
|
panic(err)
|
||||||
switch parts[0] {
|
|
||||||
case "form":
|
|
||||||
extractor = csrfTokenFromForm(parts[1])
|
|
||||||
case "query":
|
|
||||||
extractor = csrfTokenFromQuery(parts[1])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
@ -130,28 +130,58 @@ func CSRFWithConfig(config CSRFConfig) echo.MiddlewareFunc {
|
|||||||
return next(c)
|
return next(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
req := c.Request()
|
|
||||||
k, err := c.Cookie(config.CookieName)
|
|
||||||
token := ""
|
token := ""
|
||||||
|
if k, err := c.Cookie(config.CookieName); err != nil {
|
||||||
// Generate token
|
token = random.String(config.TokenLength) // Generate token
|
||||||
if err != nil {
|
|
||||||
token = random.String(config.TokenLength)
|
|
||||||
} else {
|
} else {
|
||||||
// Reuse token
|
token = k.Value // Reuse token
|
||||||
token = k.Value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch req.Method {
|
switch c.Request().Method {
|
||||||
case http.MethodGet, http.MethodHead, http.MethodOptions, http.MethodTrace:
|
case http.MethodGet, http.MethodHead, http.MethodOptions, http.MethodTrace:
|
||||||
default:
|
default:
|
||||||
// Validate token only for requests which are not defined as 'safe' by RFC7231
|
// Validate token only for requests which are not defined as 'safe' by RFC7231
|
||||||
clientToken, err := extractor(c)
|
var lastExtractorErr error
|
||||||
|
var lastTokenErr error
|
||||||
|
outer:
|
||||||
|
for _, extractor := range extractors {
|
||||||
|
clientTokens, err := extractor(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
|
lastExtractorErr = err
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
if !validateCSRFToken(token, clientToken) {
|
|
||||||
return echo.NewHTTPError(http.StatusForbidden, "invalid csrf token")
|
for _, clientToken := range clientTokens {
|
||||||
|
if validateCSRFToken(token, clientToken) {
|
||||||
|
lastTokenErr = nil
|
||||||
|
lastExtractorErr = nil
|
||||||
|
break outer
|
||||||
|
}
|
||||||
|
lastTokenErr = ErrCSRFInvalid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var finalErr error
|
||||||
|
if lastTokenErr != nil {
|
||||||
|
finalErr = lastTokenErr
|
||||||
|
} else if lastExtractorErr != nil {
|
||||||
|
// ugly part to preserve backwards compatible errors. someone could rely on them
|
||||||
|
if lastExtractorErr == errQueryExtractorValueMissing {
|
||||||
|
lastExtractorErr = echo.NewHTTPError(http.StatusBadRequest, "missing csrf token in the query string")
|
||||||
|
} else if lastExtractorErr == errFormExtractorValueMissing {
|
||||||
|
lastExtractorErr = echo.NewHTTPError(http.StatusBadRequest, "missing csrf token in the form parameter")
|
||||||
|
} else if lastExtractorErr == errHeaderExtractorValueMissing {
|
||||||
|
lastExtractorErr = echo.NewHTTPError(http.StatusBadRequest, "missing csrf token in request header")
|
||||||
|
} else {
|
||||||
|
lastExtractorErr = echo.NewHTTPError(http.StatusBadRequest, lastExtractorErr.Error())
|
||||||
|
}
|
||||||
|
finalErr = lastExtractorErr
|
||||||
|
}
|
||||||
|
|
||||||
|
if finalErr != nil {
|
||||||
|
if config.ErrorHandler != nil {
|
||||||
|
return config.ErrorHandler(finalErr, c)
|
||||||
|
}
|
||||||
|
return finalErr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,38 +214,6 @@ func CSRFWithConfig(config CSRFConfig) echo.MiddlewareFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// csrfTokenFromForm returns a `csrfTokenExtractor` that extracts token from the
|
|
||||||
// provided request header.
|
|
||||||
func csrfTokenFromHeader(header string) csrfTokenExtractor {
|
|
||||||
return func(c echo.Context) (string, error) {
|
|
||||||
return c.Request().Header.Get(header), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// csrfTokenFromForm returns a `csrfTokenExtractor` that extracts token from the
|
|
||||||
// provided form parameter.
|
|
||||||
func csrfTokenFromForm(param string) csrfTokenExtractor {
|
|
||||||
return func(c echo.Context) (string, error) {
|
|
||||||
token := c.FormValue(param)
|
|
||||||
if token == "" {
|
|
||||||
return "", errors.New("missing csrf token in the form parameter")
|
|
||||||
}
|
|
||||||
return token, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// csrfTokenFromQuery returns a `csrfTokenExtractor` that extracts token from the
|
|
||||||
// provided query parameter.
|
|
||||||
func csrfTokenFromQuery(param string) csrfTokenExtractor {
|
|
||||||
return func(c echo.Context) (string, error) {
|
|
||||||
token := c.QueryParam(param)
|
|
||||||
if token == "" {
|
|
||||||
return "", errors.New("missing csrf token in the query string")
|
|
||||||
}
|
|
||||||
return token, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateCSRFToken(token, clientToken string) bool {
|
func validateCSRFToken(token, clientToken string) bool {
|
||||||
return subtle.ConstantTimeCompare([]byte(token), []byte(clientToken)) == 1
|
return subtle.ConstantTimeCompare([]byte(token), []byte(clientToken)) == 1
|
||||||
}
|
}
|
||||||
|
49
vendor/github.com/labstack/echo/v4/middleware/decompress.go
generated
vendored
49
vendor/github.com/labstack/echo/v4/middleware/decompress.go
generated
vendored
@ -1,10 +1,8 @@
|
|||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@ -43,26 +41,7 @@ type DefaultGzipDecompressPool struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *DefaultGzipDecompressPool) gzipDecompressPool() sync.Pool {
|
func (d *DefaultGzipDecompressPool) gzipDecompressPool() sync.Pool {
|
||||||
return sync.Pool{
|
return sync.Pool{New: func() interface{} { return new(gzip.Reader) }}
|
||||||
New: func() interface{} {
|
|
||||||
// create with an empty reader (but with GZIP header)
|
|
||||||
w, err := gzip.NewWriterLevel(ioutil.Discard, gzip.BestSpeed)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
b := new(bytes.Buffer)
|
|
||||||
w.Reset(b)
|
|
||||||
w.Flush()
|
|
||||||
w.Close()
|
|
||||||
|
|
||||||
r, err := gzip.NewReader(bytes.NewReader(b.Bytes()))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Decompress decompresses request body based if content encoding type is set to "gzip" with default config
|
//Decompress decompresses request body based if content encoding type is set to "gzip" with default config
|
||||||
@ -82,38 +61,38 @@ func DecompressWithConfig(config DecompressConfig) echo.MiddlewareFunc {
|
|||||||
|
|
||||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
pool := config.GzipDecompressPool.gzipDecompressPool()
|
pool := config.GzipDecompressPool.gzipDecompressPool()
|
||||||
|
|
||||||
return func(c echo.Context) error {
|
return func(c echo.Context) error {
|
||||||
if config.Skipper(c) {
|
if config.Skipper(c) {
|
||||||
return next(c)
|
return next(c)
|
||||||
}
|
}
|
||||||
switch c.Request().Header.Get(echo.HeaderContentEncoding) {
|
|
||||||
case GZIPEncoding:
|
if c.Request().Header.Get(echo.HeaderContentEncoding) != GZIPEncoding {
|
||||||
b := c.Request().Body
|
return next(c)
|
||||||
|
}
|
||||||
|
|
||||||
i := pool.Get()
|
i := pool.Get()
|
||||||
gr, ok := i.(*gzip.Reader)
|
gr, ok := i.(*gzip.Reader)
|
||||||
if !ok {
|
if !ok || gr == nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, i.(error).Error())
|
return echo.NewHTTPError(http.StatusInternalServerError, i.(error).Error())
|
||||||
}
|
}
|
||||||
|
defer pool.Put(gr)
|
||||||
|
|
||||||
|
b := c.Request().Body
|
||||||
|
defer b.Close()
|
||||||
|
|
||||||
if err := gr.Reset(b); err != nil {
|
if err := gr.Reset(b); err != nil {
|
||||||
pool.Put(gr)
|
|
||||||
if err == io.EOF { //ignore if body is empty
|
if err == io.EOF { //ignore if body is empty
|
||||||
return next(c)
|
return next(c)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var buf bytes.Buffer
|
|
||||||
io.Copy(&buf, gr)
|
|
||||||
|
|
||||||
gr.Close()
|
// only Close gzip reader if it was set to a proper gzip source otherwise it will panic on close.
|
||||||
pool.Put(gr)
|
defer gr.Close()
|
||||||
|
|
||||||
b.Close() // http.Request.Body is closed by the Server, but because we are replacing it, it must be closed here
|
c.Request().Body = gr
|
||||||
|
|
||||||
r := ioutil.NopCloser(&buf)
|
|
||||||
c.Request().Body = r
|
|
||||||
}
|
|
||||||
return next(c)
|
return next(c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
184
vendor/github.com/labstack/echo/v4/middleware/extractor.go
generated
vendored
Normal file
184
vendor/github.com/labstack/echo/v4/middleware/extractor.go
generated
vendored
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/labstack/echo/v4"
|
||||||
|
"net/textproto"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// extractorLimit is arbitrary number to limit values extractor can return. this limits possible resource exhaustion
|
||||||
|
// attack vector
|
||||||
|
extractorLimit = 20
|
||||||
|
)
|
||||||
|
|
||||||
|
var errHeaderExtractorValueMissing = errors.New("missing value in request header")
|
||||||
|
var errHeaderExtractorValueInvalid = errors.New("invalid value in request header")
|
||||||
|
var errQueryExtractorValueMissing = errors.New("missing value in the query string")
|
||||||
|
var errParamExtractorValueMissing = errors.New("missing value in path params")
|
||||||
|
var errCookieExtractorValueMissing = errors.New("missing value in cookies")
|
||||||
|
var errFormExtractorValueMissing = errors.New("missing value in the form")
|
||||||
|
|
||||||
|
// ValuesExtractor defines a function for extracting values (keys/tokens) from the given context.
|
||||||
|
type ValuesExtractor func(c echo.Context) ([]string, error)
|
||||||
|
|
||||||
|
func createExtractors(lookups string, authScheme string) ([]ValuesExtractor, error) {
|
||||||
|
if lookups == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
sources := strings.Split(lookups, ",")
|
||||||
|
var extractors = make([]ValuesExtractor, 0)
|
||||||
|
for _, source := range sources {
|
||||||
|
parts := strings.Split(source, ":")
|
||||||
|
if len(parts) < 2 {
|
||||||
|
return nil, fmt.Errorf("extractor source for lookup could not be split into needed parts: %v", source)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch parts[0] {
|
||||||
|
case "query":
|
||||||
|
extractors = append(extractors, valuesFromQuery(parts[1]))
|
||||||
|
case "param":
|
||||||
|
extractors = append(extractors, valuesFromParam(parts[1]))
|
||||||
|
case "cookie":
|
||||||
|
extractors = append(extractors, valuesFromCookie(parts[1]))
|
||||||
|
case "form":
|
||||||
|
extractors = append(extractors, valuesFromForm(parts[1]))
|
||||||
|
case "header":
|
||||||
|
prefix := ""
|
||||||
|
if len(parts) > 2 {
|
||||||
|
prefix = parts[2]
|
||||||
|
} else if authScheme != "" && parts[1] == echo.HeaderAuthorization {
|
||||||
|
// backwards compatibility for JWT and KeyAuth:
|
||||||
|
// * we only apply this fix to Authorization as header we use and uses prefixes like "Bearer <token-value>" etc
|
||||||
|
// * previously header extractor assumed that auth-scheme/prefix had a space as suffix we need to retain that
|
||||||
|
// behaviour for default values and Authorization header.
|
||||||
|
prefix = authScheme
|
||||||
|
if !strings.HasSuffix(prefix, " ") {
|
||||||
|
prefix += " "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extractors = append(extractors, valuesFromHeader(parts[1], prefix))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return extractors, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// valuesFromHeader returns a functions that extracts values from the request header.
|
||||||
|
// valuePrefix is parameter to remove first part (prefix) of the extracted value. This is useful if header value has static
|
||||||
|
// prefix like `Authorization: <auth-scheme> <authorisation-parameters>` where part that we want to remove is `<auth-scheme> `
|
||||||
|
// note the space at the end. In case of basic authentication `Authorization: Basic <credentials>` prefix we want to remove
|
||||||
|
// is `Basic `. In case of JWT tokens `Authorization: Bearer <token>` prefix is `Bearer `.
|
||||||
|
// If prefix is left empty the whole value is returned.
|
||||||
|
func valuesFromHeader(header string, valuePrefix string) ValuesExtractor {
|
||||||
|
prefixLen := len(valuePrefix)
|
||||||
|
// standard library parses http.Request header keys in canonical form but we may provide something else so fix this
|
||||||
|
header = textproto.CanonicalMIMEHeaderKey(header)
|
||||||
|
return func(c echo.Context) ([]string, error) {
|
||||||
|
values := c.Request().Header.Values(header)
|
||||||
|
if len(values) == 0 {
|
||||||
|
return nil, errHeaderExtractorValueMissing
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make([]string, 0)
|
||||||
|
for i, value := range values {
|
||||||
|
if prefixLen == 0 {
|
||||||
|
result = append(result, value)
|
||||||
|
if i >= extractorLimit-1 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(value) > prefixLen && strings.EqualFold(value[:prefixLen], valuePrefix) {
|
||||||
|
result = append(result, value[prefixLen:])
|
||||||
|
if i >= extractorLimit-1 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(result) == 0 {
|
||||||
|
if prefixLen > 0 {
|
||||||
|
return nil, errHeaderExtractorValueInvalid
|
||||||
|
}
|
||||||
|
return nil, errHeaderExtractorValueMissing
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// valuesFromQuery returns a function that extracts values from the query string.
|
||||||
|
func valuesFromQuery(param string) ValuesExtractor {
|
||||||
|
return func(c echo.Context) ([]string, error) {
|
||||||
|
result := c.QueryParams()[param]
|
||||||
|
if len(result) == 0 {
|
||||||
|
return nil, errQueryExtractorValueMissing
|
||||||
|
} else if len(result) > extractorLimit-1 {
|
||||||
|
result = result[:extractorLimit]
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// valuesFromParam returns a function that extracts values from the url param string.
|
||||||
|
func valuesFromParam(param string) ValuesExtractor {
|
||||||
|
return func(c echo.Context) ([]string, error) {
|
||||||
|
result := make([]string, 0)
|
||||||
|
paramVales := c.ParamValues()
|
||||||
|
for i, p := range c.ParamNames() {
|
||||||
|
if param == p {
|
||||||
|
result = append(result, paramVales[i])
|
||||||
|
if i >= extractorLimit-1 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(result) == 0 {
|
||||||
|
return nil, errParamExtractorValueMissing
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// valuesFromCookie returns a function that extracts values from the named cookie.
|
||||||
|
func valuesFromCookie(name string) ValuesExtractor {
|
||||||
|
return func(c echo.Context) ([]string, error) {
|
||||||
|
cookies := c.Cookies()
|
||||||
|
if len(cookies) == 0 {
|
||||||
|
return nil, errCookieExtractorValueMissing
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make([]string, 0)
|
||||||
|
for i, cookie := range cookies {
|
||||||
|
if name == cookie.Name {
|
||||||
|
result = append(result, cookie.Value)
|
||||||
|
if i >= extractorLimit-1 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(result) == 0 {
|
||||||
|
return nil, errCookieExtractorValueMissing
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// valuesFromForm returns a function that extracts values from the form field.
|
||||||
|
func valuesFromForm(name string) ValuesExtractor {
|
||||||
|
return func(c echo.Context) ([]string, error) {
|
||||||
|
if c.Request().Form == nil {
|
||||||
|
_ = c.Request().ParseMultipartForm(32 << 20) // same what `c.Request().FormValue(name)` does
|
||||||
|
}
|
||||||
|
values := c.Request().Form[name]
|
||||||
|
if len(values) == 0 {
|
||||||
|
return nil, errFormExtractorValueMissing
|
||||||
|
}
|
||||||
|
if len(values) > extractorLimit-1 {
|
||||||
|
values = values[:extractorLimit]
|
||||||
|
}
|
||||||
|
result := append([]string{}, values...)
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
}
|
171
vendor/github.com/labstack/echo/v4/middleware/jwt.go
generated
vendored
171
vendor/github.com/labstack/echo/v4/middleware/jwt.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build go1.15
|
||||||
// +build go1.15
|
// +build go1.15
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
@ -5,12 +6,10 @@ package middleware
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt"
|
"github.com/golang-jwt/jwt"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
|
"net/http"
|
||||||
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@ -22,7 +21,8 @@ type (
|
|||||||
// BeforeFunc defines a function which is executed just before the middleware.
|
// BeforeFunc defines a function which is executed just before the middleware.
|
||||||
BeforeFunc BeforeFunc
|
BeforeFunc BeforeFunc
|
||||||
|
|
||||||
// SuccessHandler defines a function which is executed for a valid token.
|
// SuccessHandler defines a function which is executed for a valid token before middleware chain continues with next
|
||||||
|
// middleware or handler.
|
||||||
SuccessHandler JWTSuccessHandler
|
SuccessHandler JWTSuccessHandler
|
||||||
|
|
||||||
// ErrorHandler defines a function which is executed for an invalid token.
|
// ErrorHandler defines a function which is executed for an invalid token.
|
||||||
@ -32,6 +32,13 @@ type (
|
|||||||
// ErrorHandlerWithContext is almost identical to ErrorHandler, but it's passed the current context.
|
// ErrorHandlerWithContext is almost identical to ErrorHandler, but it's passed the current context.
|
||||||
ErrorHandlerWithContext JWTErrorHandlerWithContext
|
ErrorHandlerWithContext JWTErrorHandlerWithContext
|
||||||
|
|
||||||
|
// ContinueOnIgnoredError allows the next middleware/handler to be called when ErrorHandlerWithContext decides to
|
||||||
|
// ignore the error (by returning `nil`).
|
||||||
|
// This is useful when parts of your site/api allow public access and some authorized routes provide extra functionality.
|
||||||
|
// In that case you can use ErrorHandlerWithContext to set a default public JWT token value in the request context
|
||||||
|
// and continue. Some logic down the remaining execution chain needs to check that (public) token value then.
|
||||||
|
ContinueOnIgnoredError bool
|
||||||
|
|
||||||
// Signing key to validate token.
|
// Signing key to validate token.
|
||||||
// This is one of the three options to provide a token validation key.
|
// This is one of the three options to provide a token validation key.
|
||||||
// The order of precedence is a user-defined KeyFunc, SigningKeys and SigningKey.
|
// The order of precedence is a user-defined KeyFunc, SigningKeys and SigningKey.
|
||||||
@ -61,16 +68,26 @@ type (
|
|||||||
// to extract token from the request.
|
// to extract token from the request.
|
||||||
// Optional. Default value "header:Authorization".
|
// Optional. Default value "header:Authorization".
|
||||||
// Possible values:
|
// Possible values:
|
||||||
// - "header:<name>"
|
// - "header:<name>" or "header:<name>:<cut-prefix>"
|
||||||
|
// `<cut-prefix>` is argument value to cut/trim prefix of the extracted value. This is useful if header
|
||||||
|
// value has static prefix like `Authorization: <auth-scheme> <authorisation-parameters>` where part that we
|
||||||
|
// want to cut is `<auth-scheme> ` note the space at the end.
|
||||||
|
// In case of JWT tokens `Authorization: Bearer <token>` prefix we cut is `Bearer `.
|
||||||
|
// If prefix is left empty the whole value is returned.
|
||||||
// - "query:<name>"
|
// - "query:<name>"
|
||||||
// - "param:<name>"
|
// - "param:<name>"
|
||||||
// - "cookie:<name>"
|
// - "cookie:<name>"
|
||||||
// - "form:<name>"
|
// - "form:<name>"
|
||||||
// Multiply sources example:
|
// Multiple sources example:
|
||||||
// - "header:Authorization,cookie:myowncookie"
|
// - "header:Authorization,cookie:myowncookie"
|
||||||
|
|
||||||
TokenLookup string
|
TokenLookup string
|
||||||
|
|
||||||
|
// TokenLookupFuncs defines a list of user-defined functions that extract JWT token from the given context.
|
||||||
|
// This is one of the two options to provide a token extractor.
|
||||||
|
// The order of precedence is user-defined TokenLookupFuncs, and TokenLookup.
|
||||||
|
// You can also provide both if you want.
|
||||||
|
TokenLookupFuncs []ValuesExtractor
|
||||||
|
|
||||||
// AuthScheme to be used in the Authorization header.
|
// AuthScheme to be used in the Authorization header.
|
||||||
// Optional. Default value "Bearer".
|
// Optional. Default value "Bearer".
|
||||||
AuthScheme string
|
AuthScheme string
|
||||||
@ -95,15 +112,13 @@ type (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// JWTSuccessHandler defines a function which is executed for a valid token.
|
// JWTSuccessHandler defines a function which is executed for a valid token.
|
||||||
JWTSuccessHandler func(echo.Context)
|
JWTSuccessHandler func(c echo.Context)
|
||||||
|
|
||||||
// JWTErrorHandler defines a function which is executed for an invalid token.
|
// JWTErrorHandler defines a function which is executed for an invalid token.
|
||||||
JWTErrorHandler func(error) error
|
JWTErrorHandler func(err error) error
|
||||||
|
|
||||||
// JWTErrorHandlerWithContext is almost identical to JWTErrorHandler, but it's passed the current context.
|
// JWTErrorHandlerWithContext is almost identical to JWTErrorHandler, but it's passed the current context.
|
||||||
JWTErrorHandlerWithContext func(error, echo.Context) error
|
JWTErrorHandlerWithContext func(err error, c echo.Context) error
|
||||||
|
|
||||||
jwtExtractor func(echo.Context) (string, error)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Algorithms
|
// Algorithms
|
||||||
@ -124,6 +139,7 @@ var (
|
|||||||
SigningMethod: AlgorithmHS256,
|
SigningMethod: AlgorithmHS256,
|
||||||
ContextKey: "user",
|
ContextKey: "user",
|
||||||
TokenLookup: "header:" + echo.HeaderAuthorization,
|
TokenLookup: "header:" + echo.HeaderAuthorization,
|
||||||
|
TokenLookupFuncs: nil,
|
||||||
AuthScheme: "Bearer",
|
AuthScheme: "Bearer",
|
||||||
Claims: jwt.MapClaims{},
|
Claims: jwt.MapClaims{},
|
||||||
KeyFunc: nil,
|
KeyFunc: nil,
|
||||||
@ -163,7 +179,7 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
|
|||||||
if config.Claims == nil {
|
if config.Claims == nil {
|
||||||
config.Claims = DefaultJWTConfig.Claims
|
config.Claims = DefaultJWTConfig.Claims
|
||||||
}
|
}
|
||||||
if config.TokenLookup == "" {
|
if config.TokenLookup == "" && len(config.TokenLookupFuncs) == 0 {
|
||||||
config.TokenLookup = DefaultJWTConfig.TokenLookup
|
config.TokenLookup = DefaultJWTConfig.TokenLookup
|
||||||
}
|
}
|
||||||
if config.AuthScheme == "" {
|
if config.AuthScheme == "" {
|
||||||
@ -176,25 +192,12 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
|
|||||||
config.ParseTokenFunc = config.defaultParseToken
|
config.ParseTokenFunc = config.defaultParseToken
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize
|
extractors, err := createExtractors(config.TokenLookup, config.AuthScheme)
|
||||||
// Split sources
|
if err != nil {
|
||||||
sources := strings.Split(config.TokenLookup, ",")
|
panic(err)
|
||||||
var extractors []jwtExtractor
|
|
||||||
for _, source := range sources {
|
|
||||||
parts := strings.Split(source, ":")
|
|
||||||
|
|
||||||
switch parts[0] {
|
|
||||||
case "query":
|
|
||||||
extractors = append(extractors, jwtFromQuery(parts[1]))
|
|
||||||
case "param":
|
|
||||||
extractors = append(extractors, jwtFromParam(parts[1]))
|
|
||||||
case "cookie":
|
|
||||||
extractors = append(extractors, jwtFromCookie(parts[1]))
|
|
||||||
case "form":
|
|
||||||
extractors = append(extractors, jwtFromForm(parts[1]))
|
|
||||||
case "header":
|
|
||||||
extractors = append(extractors, jwtFromHeader(parts[1], config.AuthScheme))
|
|
||||||
}
|
}
|
||||||
|
if len(config.TokenLookupFuncs) > 0 {
|
||||||
|
extractors = append(config.TokenLookupFuncs, extractors...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
@ -206,30 +209,21 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
|
|||||||
if config.BeforeFunc != nil {
|
if config.BeforeFunc != nil {
|
||||||
config.BeforeFunc(c)
|
config.BeforeFunc(c)
|
||||||
}
|
}
|
||||||
var auth string
|
|
||||||
var err error
|
var lastExtractorErr error
|
||||||
|
var lastTokenErr error
|
||||||
for _, extractor := range extractors {
|
for _, extractor := range extractors {
|
||||||
// Extract token from extractor, if it's not fail break the loop and
|
auths, err := extractor(c)
|
||||||
// set auth
|
|
||||||
auth, err = extractor(c)
|
|
||||||
if err == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If none of extractor has a token, handle error
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if config.ErrorHandler != nil {
|
lastExtractorErr = ErrJWTMissing // backwards compatibility: all extraction errors are same (unlike KeyAuth)
|
||||||
return config.ErrorHandler(err)
|
continue
|
||||||
}
|
}
|
||||||
|
for _, auth := range auths {
|
||||||
if config.ErrorHandlerWithContext != nil {
|
|
||||||
return config.ErrorHandlerWithContext(err, c)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
token, err := config.ParseTokenFunc(auth, c)
|
token, err := config.ParseTokenFunc(auth, c)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
|
lastTokenErr = err
|
||||||
|
continue
|
||||||
|
}
|
||||||
// Store user information from token into context.
|
// Store user information from token into context.
|
||||||
c.Set(config.ContextKey, token)
|
c.Set(config.ContextKey, token)
|
||||||
if config.SuccessHandler != nil {
|
if config.SuccessHandler != nil {
|
||||||
@ -237,18 +231,33 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
|
|||||||
}
|
}
|
||||||
return next(c)
|
return next(c)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// we are here only when we did not successfully extract or parse any of the tokens
|
||||||
|
err := lastTokenErr
|
||||||
|
if err == nil { // prioritize token errors over extracting errors
|
||||||
|
err = lastExtractorErr
|
||||||
|
}
|
||||||
if config.ErrorHandler != nil {
|
if config.ErrorHandler != nil {
|
||||||
return config.ErrorHandler(err)
|
return config.ErrorHandler(err)
|
||||||
}
|
}
|
||||||
if config.ErrorHandlerWithContext != nil {
|
if config.ErrorHandlerWithContext != nil {
|
||||||
return config.ErrorHandlerWithContext(err, c)
|
tmpErr := config.ErrorHandlerWithContext(err, c)
|
||||||
|
if config.ContinueOnIgnoredError && tmpErr == nil {
|
||||||
|
return next(c)
|
||||||
}
|
}
|
||||||
|
return tmpErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// backwards compatible errors codes
|
||||||
|
if lastTokenErr != nil {
|
||||||
return &echo.HTTPError{
|
return &echo.HTTPError{
|
||||||
Code: ErrJWTInvalid.Code,
|
Code: ErrJWTInvalid.Code,
|
||||||
Message: ErrJWTInvalid.Message,
|
Message: ErrJWTInvalid.Message,
|
||||||
Internal: err,
|
Internal: err,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return err // this is lastExtractorErr value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,59 +298,3 @@ func (config *JWTConfig) defaultKeyFunc(t *jwt.Token) (interface{}, error) {
|
|||||||
|
|
||||||
return config.SigningKey, nil
|
return config.SigningKey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// jwtFromHeader returns a `jwtExtractor` that extracts token from the request header.
|
|
||||||
func jwtFromHeader(header string, authScheme string) jwtExtractor {
|
|
||||||
return func(c echo.Context) (string, error) {
|
|
||||||
auth := c.Request().Header.Get(header)
|
|
||||||
l := len(authScheme)
|
|
||||||
if len(auth) > l+1 && auth[:l] == authScheme {
|
|
||||||
return auth[l+1:], nil
|
|
||||||
}
|
|
||||||
return "", ErrJWTMissing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// jwtFromQuery returns a `jwtExtractor` that extracts token from the query string.
|
|
||||||
func jwtFromQuery(param string) jwtExtractor {
|
|
||||||
return func(c echo.Context) (string, error) {
|
|
||||||
token := c.QueryParam(param)
|
|
||||||
if token == "" {
|
|
||||||
return "", ErrJWTMissing
|
|
||||||
}
|
|
||||||
return token, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// jwtFromParam returns a `jwtExtractor` that extracts token from the url param string.
|
|
||||||
func jwtFromParam(param string) jwtExtractor {
|
|
||||||
return func(c echo.Context) (string, error) {
|
|
||||||
token := c.Param(param)
|
|
||||||
if token == "" {
|
|
||||||
return "", ErrJWTMissing
|
|
||||||
}
|
|
||||||
return token, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// jwtFromCookie returns a `jwtExtractor` that extracts token from the named cookie.
|
|
||||||
func jwtFromCookie(name string) jwtExtractor {
|
|
||||||
return func(c echo.Context) (string, error) {
|
|
||||||
cookie, err := c.Cookie(name)
|
|
||||||
if err != nil {
|
|
||||||
return "", ErrJWTMissing
|
|
||||||
}
|
|
||||||
return cookie.Value, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// jwtFromForm returns a `jwtExtractor` that extracts token from the form field.
|
|
||||||
func jwtFromForm(name string) jwtExtractor {
|
|
||||||
return func(c echo.Context) (string, error) {
|
|
||||||
field := c.FormValue(name)
|
|
||||||
if field == "" {
|
|
||||||
return "", ErrJWTMissing
|
|
||||||
}
|
|
||||||
return field, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
166
vendor/github.com/labstack/echo/v4/middleware/key_auth.go
generated
vendored
166
vendor/github.com/labstack/echo/v4/middleware/key_auth.go
generated
vendored
@ -2,10 +2,8 @@ package middleware
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@ -14,14 +12,21 @@ type (
|
|||||||
// Skipper defines a function to skip middleware.
|
// Skipper defines a function to skip middleware.
|
||||||
Skipper Skipper
|
Skipper Skipper
|
||||||
|
|
||||||
// KeyLookup is a string in the form of "<source>:<name>" that is used
|
// KeyLookup is a string in the form of "<source>:<name>" or "<source>:<name>,<source>:<name>" that is used
|
||||||
// to extract key from the request.
|
// to extract key from the request.
|
||||||
// Optional. Default value "header:Authorization".
|
// Optional. Default value "header:Authorization".
|
||||||
// Possible values:
|
// Possible values:
|
||||||
// - "header:<name>"
|
// - "header:<name>" or "header:<name>:<cut-prefix>"
|
||||||
|
// `<cut-prefix>` is argument value to cut/trim prefix of the extracted value. This is useful if header
|
||||||
|
// value has static prefix like `Authorization: <auth-scheme> <authorisation-parameters>` where part that we
|
||||||
|
// want to cut is `<auth-scheme> ` note the space at the end.
|
||||||
|
// In case of basic authentication `Authorization: Basic <credentials>` prefix we want to remove is `Basic `.
|
||||||
// - "query:<name>"
|
// - "query:<name>"
|
||||||
// - "form:<name>"
|
// - "form:<name>"
|
||||||
KeyLookup string `yaml:"key_lookup"`
|
// - "cookie:<name>"
|
||||||
|
// Multiple sources example:
|
||||||
|
// - "header:Authorization,header:X-Api-Key"
|
||||||
|
KeyLookup string
|
||||||
|
|
||||||
// AuthScheme to be used in the Authorization header.
|
// AuthScheme to be used in the Authorization header.
|
||||||
// Optional. Default value "Bearer".
|
// Optional. Default value "Bearer".
|
||||||
@ -34,15 +39,20 @@ type (
|
|||||||
// ErrorHandler defines a function which is executed for an invalid key.
|
// ErrorHandler defines a function which is executed for an invalid key.
|
||||||
// It may be used to define a custom error.
|
// It may be used to define a custom error.
|
||||||
ErrorHandler KeyAuthErrorHandler
|
ErrorHandler KeyAuthErrorHandler
|
||||||
|
|
||||||
|
// ContinueOnIgnoredError allows the next middleware/handler to be called when ErrorHandler decides to
|
||||||
|
// ignore the error (by returning `nil`).
|
||||||
|
// This is useful when parts of your site/api allow public access and some authorized routes provide extra functionality.
|
||||||
|
// In that case you can use ErrorHandler to set a default public key auth value in the request context
|
||||||
|
// and continue. Some logic down the remaining execution chain needs to check that (public) key auth value then.
|
||||||
|
ContinueOnIgnoredError bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyAuthValidator defines a function to validate KeyAuth credentials.
|
// KeyAuthValidator defines a function to validate KeyAuth credentials.
|
||||||
KeyAuthValidator func(string, echo.Context) (bool, error)
|
KeyAuthValidator func(auth string, c echo.Context) (bool, error)
|
||||||
|
|
||||||
keyExtractor func(echo.Context) (string, error)
|
|
||||||
|
|
||||||
// KeyAuthErrorHandler defines a function which is executed for an invalid key.
|
// KeyAuthErrorHandler defines a function which is executed for an invalid key.
|
||||||
KeyAuthErrorHandler func(error, echo.Context) error
|
KeyAuthErrorHandler func(err error, c echo.Context) error
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -54,6 +64,21 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ErrKeyAuthMissing is error type when KeyAuth middleware is unable to extract value from lookups
|
||||||
|
type ErrKeyAuthMissing struct {
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error returns errors text
|
||||||
|
func (e *ErrKeyAuthMissing) Error() string {
|
||||||
|
return e.Err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unwrap unwraps error
|
||||||
|
func (e *ErrKeyAuthMissing) Unwrap() error {
|
||||||
|
return e.Err
|
||||||
|
}
|
||||||
|
|
||||||
// KeyAuth returns an KeyAuth middleware.
|
// KeyAuth returns an KeyAuth middleware.
|
||||||
//
|
//
|
||||||
// For valid key it calls the next handler.
|
// For valid key it calls the next handler.
|
||||||
@ -83,14 +108,9 @@ func KeyAuthWithConfig(config KeyAuthConfig) echo.MiddlewareFunc {
|
|||||||
panic("echo: key-auth middleware requires a validator function")
|
panic("echo: key-auth middleware requires a validator function")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize
|
extractors, err := createExtractors(config.KeyLookup, config.AuthScheme)
|
||||||
parts := strings.Split(config.KeyLookup, ":")
|
if err != nil {
|
||||||
extractor := keyFromHeader(parts[1], config.AuthScheme)
|
panic(err)
|
||||||
switch parts[0] {
|
|
||||||
case "query":
|
|
||||||
extractor = keyFromQuery(parts[1])
|
|
||||||
case "form":
|
|
||||||
extractor = keyFromForm(parts[1])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
@ -99,68 +119,62 @@ func KeyAuthWithConfig(config KeyAuthConfig) echo.MiddlewareFunc {
|
|||||||
return next(c)
|
return next(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract and verify key
|
var lastExtractorErr error
|
||||||
key, err := extractor(c)
|
var lastValidatorErr error
|
||||||
|
for _, extractor := range extractors {
|
||||||
|
keys, err := extractor(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
lastExtractorErr = err
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, key := range keys {
|
||||||
|
valid, err := config.Validator(key, c)
|
||||||
|
if err != nil {
|
||||||
|
lastValidatorErr = err
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if valid {
|
||||||
|
return next(c)
|
||||||
|
}
|
||||||
|
lastValidatorErr = errors.New("invalid key")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we are here only when we did not successfully extract and validate any of keys
|
||||||
|
err := lastValidatorErr
|
||||||
|
if err == nil { // prioritize validator errors over extracting errors
|
||||||
|
// ugly part to preserve backwards compatible errors. someone could rely on them
|
||||||
|
if lastExtractorErr == errQueryExtractorValueMissing {
|
||||||
|
err = errors.New("missing key in the query string")
|
||||||
|
} else if lastExtractorErr == errCookieExtractorValueMissing {
|
||||||
|
err = errors.New("missing key in cookies")
|
||||||
|
} else if lastExtractorErr == errFormExtractorValueMissing {
|
||||||
|
err = errors.New("missing key in the form")
|
||||||
|
} else if lastExtractorErr == errHeaderExtractorValueMissing {
|
||||||
|
err = errors.New("missing key in request header")
|
||||||
|
} else if lastExtractorErr == errHeaderExtractorValueInvalid {
|
||||||
|
err = errors.New("invalid key in the request header")
|
||||||
|
} else {
|
||||||
|
err = lastExtractorErr
|
||||||
|
}
|
||||||
|
err = &ErrKeyAuthMissing{Err: err}
|
||||||
|
}
|
||||||
|
|
||||||
if config.ErrorHandler != nil {
|
if config.ErrorHandler != nil {
|
||||||
return config.ErrorHandler(err, c)
|
tmpErr := config.ErrorHandler(err, c)
|
||||||
|
if config.ContinueOnIgnoredError && tmpErr == nil {
|
||||||
|
return next(c)
|
||||||
|
}
|
||||||
|
return tmpErr
|
||||||
|
}
|
||||||
|
if lastValidatorErr != nil { // prioritize validator errors over extracting errors
|
||||||
|
return &echo.HTTPError{
|
||||||
|
Code: http.StatusUnauthorized,
|
||||||
|
Message: "Unauthorized",
|
||||||
|
Internal: lastValidatorErr,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
|
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
|
||||||
}
|
}
|
||||||
valid, err := config.Validator(key, c)
|
|
||||||
if err != nil {
|
|
||||||
if config.ErrorHandler != nil {
|
|
||||||
return config.ErrorHandler(err, c)
|
|
||||||
}
|
|
||||||
return &echo.HTTPError{
|
|
||||||
Code: http.StatusUnauthorized,
|
|
||||||
Message: "invalid key",
|
|
||||||
Internal: err,
|
|
||||||
}
|
|
||||||
} else if valid {
|
|
||||||
return next(c)
|
|
||||||
}
|
|
||||||
return echo.ErrUnauthorized
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// keyFromHeader returns a `keyExtractor` that extracts key from the request header.
|
|
||||||
func keyFromHeader(header string, authScheme string) keyExtractor {
|
|
||||||
return func(c echo.Context) (string, error) {
|
|
||||||
auth := c.Request().Header.Get(header)
|
|
||||||
if auth == "" {
|
|
||||||
return "", errors.New("missing key in request header")
|
|
||||||
}
|
|
||||||
if header == echo.HeaderAuthorization {
|
|
||||||
l := len(authScheme)
|
|
||||||
if len(auth) > l+1 && auth[:l] == authScheme {
|
|
||||||
return auth[l+1:], nil
|
|
||||||
}
|
|
||||||
return "", errors.New("invalid key in the request header")
|
|
||||||
}
|
|
||||||
return auth, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// keyFromQuery returns a `keyExtractor` that extracts key from the query string.
|
|
||||||
func keyFromQuery(param string) keyExtractor {
|
|
||||||
return func(c echo.Context) (string, error) {
|
|
||||||
key := c.QueryParam(param)
|
|
||||||
if key == "" {
|
|
||||||
return "", errors.New("missing key in the query string")
|
|
||||||
}
|
|
||||||
return key, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// keyFromForm returns a `keyExtractor` that extracts key from the form.
|
|
||||||
func keyFromForm(param string) keyExtractor {
|
|
||||||
return func(c echo.Context) (string, error) {
|
|
||||||
key := c.FormValue(param)
|
|
||||||
if key == "" {
|
|
||||||
return "", errors.New("missing key in the form")
|
|
||||||
}
|
|
||||||
return key, nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
8
vendor/github.com/labstack/echo/v4/middleware/logger.go
generated
vendored
8
vendor/github.com/labstack/echo/v4/middleware/logger.go
generated
vendored
@ -23,6 +23,8 @@ type (
|
|||||||
// Tags to construct the logger format.
|
// Tags to construct the logger format.
|
||||||
//
|
//
|
||||||
// - time_unix
|
// - time_unix
|
||||||
|
// - time_unix_milli
|
||||||
|
// - time_unix_micro
|
||||||
// - time_unix_nano
|
// - time_unix_nano
|
||||||
// - time_rfc3339
|
// - time_rfc3339
|
||||||
// - time_rfc3339_nano
|
// - time_rfc3339_nano
|
||||||
@ -126,6 +128,12 @@ func LoggerWithConfig(config LoggerConfig) echo.MiddlewareFunc {
|
|||||||
switch tag {
|
switch tag {
|
||||||
case "time_unix":
|
case "time_unix":
|
||||||
return buf.WriteString(strconv.FormatInt(time.Now().Unix(), 10))
|
return buf.WriteString(strconv.FormatInt(time.Now().Unix(), 10))
|
||||||
|
case "time_unix_milli":
|
||||||
|
// go 1.17 or later, it supports time#UnixMilli()
|
||||||
|
return buf.WriteString(strconv.FormatInt(time.Now().UnixNano()/1000000, 10))
|
||||||
|
case "time_unix_micro":
|
||||||
|
// go 1.17 or later, it supports time#UnixMicro()
|
||||||
|
return buf.WriteString(strconv.FormatInt(time.Now().UnixNano()/1000, 10))
|
||||||
case "time_unix_nano":
|
case "time_unix_nano":
|
||||||
return buf.WriteString(strconv.FormatInt(time.Now().UnixNano(), 10))
|
return buf.WriteString(strconv.FormatInt(time.Now().UnixNano(), 10))
|
||||||
case "time_rfc3339":
|
case "time_rfc3339":
|
||||||
|
4
vendor/github.com/labstack/echo/v4/middleware/middleware.go
generated
vendored
4
vendor/github.com/labstack/echo/v4/middleware/middleware.go
generated
vendored
@ -12,10 +12,10 @@ import (
|
|||||||
type (
|
type (
|
||||||
// Skipper defines a function to skip middleware. Returning true skips processing
|
// Skipper defines a function to skip middleware. Returning true skips processing
|
||||||
// the middleware.
|
// the middleware.
|
||||||
Skipper func(echo.Context) bool
|
Skipper func(c echo.Context) bool
|
||||||
|
|
||||||
// BeforeFunc defines a function which is executed just before the middleware.
|
// BeforeFunc defines a function which is executed just before the middleware.
|
||||||
BeforeFunc func(echo.Context)
|
BeforeFunc func(c echo.Context)
|
||||||
)
|
)
|
||||||
|
|
||||||
func captureTokens(pattern *regexp.Regexp, input string) *strings.Replacer {
|
func captureTokens(pattern *regexp.Regexp, input string) *strings.Replacer {
|
||||||
|
9
vendor/github.com/labstack/echo/v4/middleware/rate_limiter.go
generated
vendored
9
vendor/github.com/labstack/echo/v4/middleware/rate_limiter.go
generated
vendored
@ -155,7 +155,8 @@ type (
|
|||||||
RateLimiterMemoryStore struct {
|
RateLimiterMemoryStore struct {
|
||||||
visitors map[string]*Visitor
|
visitors map[string]*Visitor
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
rate rate.Limit
|
rate rate.Limit //for more info check out Limiter docs - https://pkg.go.dev/golang.org/x/time/rate#Limit.
|
||||||
|
|
||||||
burst int
|
burst int
|
||||||
expiresIn time.Duration
|
expiresIn time.Duration
|
||||||
lastCleanup time.Time
|
lastCleanup time.Time
|
||||||
@ -170,6 +171,8 @@ type (
|
|||||||
/*
|
/*
|
||||||
NewRateLimiterMemoryStore returns an instance of RateLimiterMemoryStore with
|
NewRateLimiterMemoryStore returns an instance of RateLimiterMemoryStore with
|
||||||
the provided rate (as req/s). The provided rate less than 1 will be treated as zero.
|
the provided rate (as req/s). The provided rate less than 1 will be treated as zero.
|
||||||
|
for more info check out Limiter docs - https://pkg.go.dev/golang.org/x/time/rate#Limit.
|
||||||
|
|
||||||
Burst and ExpiresIn will be set to default values.
|
Burst and ExpiresIn will be set to default values.
|
||||||
|
|
||||||
Example (with 20 requests/sec):
|
Example (with 20 requests/sec):
|
||||||
@ -199,7 +202,7 @@ Characteristics:
|
|||||||
Example:
|
Example:
|
||||||
|
|
||||||
limiterStore := middleware.NewRateLimiterMemoryStoreWithConfig(
|
limiterStore := middleware.NewRateLimiterMemoryStoreWithConfig(
|
||||||
middleware.RateLimiterMemoryStoreConfig{Rate: 50, Burst: 200, ExpiresIn: 5 * time.Minutes},
|
middleware.RateLimiterMemoryStoreConfig{Rate: 50, Burst: 200, ExpiresIn: 5 * time.Minute},
|
||||||
)
|
)
|
||||||
*/
|
*/
|
||||||
func NewRateLimiterMemoryStoreWithConfig(config RateLimiterMemoryStoreConfig) (store *RateLimiterMemoryStore) {
|
func NewRateLimiterMemoryStoreWithConfig(config RateLimiterMemoryStoreConfig) (store *RateLimiterMemoryStore) {
|
||||||
@ -221,7 +224,7 @@ func NewRateLimiterMemoryStoreWithConfig(config RateLimiterMemoryStoreConfig) (s
|
|||||||
|
|
||||||
// RateLimiterMemoryStoreConfig represents configuration for RateLimiterMemoryStore
|
// RateLimiterMemoryStoreConfig represents configuration for RateLimiterMemoryStore
|
||||||
type RateLimiterMemoryStoreConfig struct {
|
type RateLimiterMemoryStoreConfig struct {
|
||||||
Rate rate.Limit // Rate of requests allowed to pass as req/s
|
Rate rate.Limit // Rate of requests allowed to pass as req/s. For more info check out Limiter docs - https://pkg.go.dev/golang.org/x/time/rate#Limit.
|
||||||
Burst int // Burst additionally allows a number of requests to pass when rate limit is reached
|
Burst int // Burst additionally allows a number of requests to pass when rate limit is reached
|
||||||
ExpiresIn time.Duration // ExpiresIn is the duration after that a rate limiter is cleaned up
|
ExpiresIn time.Duration // ExpiresIn is the duration after that a rate limiter is cleaned up
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user