mirror of
https://github.com/prometheus/prometheus.git
synced 2024-11-14 09:34:05 -08:00
Merge pull request #3243 from prometheus/mergemaster
Merge master into dev-2.0
This commit is contained in:
commit
46dc7e356a
|
@ -3,7 +3,7 @@ sudo: false
|
||||||
language: go
|
language: go
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.8.x
|
- 1.9.x
|
||||||
- 1.x
|
- 1.x
|
||||||
|
|
||||||
go_import_path: github.com/prometheus/prometheus
|
go_import_path: github.com/prometheus/prometheus
|
||||||
|
|
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -1,3 +1,16 @@
|
||||||
|
## 1.7.2 / 2017-09-26
|
||||||
|
|
||||||
|
* [BUGFIX] Correctly remove all targets from DNS service discovery if the
|
||||||
|
corresponding DNS query succeeds and returns an empty result.
|
||||||
|
* [BUGFIX] Correctly parse resolution input in expression browser.
|
||||||
|
* [BUGFIX] Consistently use UTC in the date picker of the expression browser.
|
||||||
|
* [BUGFIX] Correctly handle multiple ports in Marathon service discovery.
|
||||||
|
* [BUGFIX] Fix HTML escaping so that HTML templates compile with Go1.9.
|
||||||
|
* [BUGFIX] Prevent number of remote write shards from going negative.
|
||||||
|
* [BUGFIX] In the graphs created by the expression browser, render very large
|
||||||
|
and small numbers in a readable way.
|
||||||
|
* [BUGFIX] Fix a rarely occurring iterator issue in varbit encoded chunks.
|
||||||
|
|
||||||
## v2.0.0-beta.5 / 2017-09-21
|
## v2.0.0-beta.5 / 2017-09-21
|
||||||
|
|
||||||
This release includes numerous changes to the new storage layer. The main changes are:
|
This release includes numerous changes to the new storage layer. The main changes are:
|
||||||
|
|
18
Makefile
18
Makefile
|
@ -14,6 +14,7 @@
|
||||||
GO := GO15VENDOREXPERIMENT=1 go
|
GO := GO15VENDOREXPERIMENT=1 go
|
||||||
FIRST_GOPATH := $(firstword $(subst :, ,$(shell $(GO) env GOPATH)))
|
FIRST_GOPATH := $(firstword $(subst :, ,$(shell $(GO) env GOPATH)))
|
||||||
PROMU := $(FIRST_GOPATH)/bin/promu
|
PROMU := $(FIRST_GOPATH)/bin/promu
|
||||||
|
STATICCHECK := $(FIRST_GOPATH)/bin/staticcheck
|
||||||
pkgs = $(shell $(GO) list ./... | grep -v /vendor/)
|
pkgs = $(shell $(GO) list ./... | grep -v /vendor/)
|
||||||
|
|
||||||
PREFIX ?= $(shell pwd)
|
PREFIX ?= $(shell pwd)
|
||||||
|
@ -25,8 +26,15 @@ ifdef DEBUG
|
||||||
bindata_flags = -debug
|
bindata_flags = -debug
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
STATICCHECK_IGNORE = \
|
||||||
|
github.com/prometheus/prometheus/discovery/kubernetes/node.go:SA1019 \
|
||||||
|
github.com/prometheus/prometheus/documentation/examples/remote_storage/remote_storage_adapter/main.go:SA1019 \
|
||||||
|
github.com/prometheus/prometheus/storage/local/codable/codable.go:SA6002 \
|
||||||
|
github.com/prometheus/prometheus/storage/local/persistence.go:SA6002 \
|
||||||
|
github.com/prometheus/prometheus/storage/remote/queue_manager.go:SA1015 \
|
||||||
|
github.com/prometheus/prometheus/web/web.go:SA1019
|
||||||
|
|
||||||
all: format build test
|
all: format staticcheck build test
|
||||||
|
|
||||||
style:
|
style:
|
||||||
@echo ">> checking code style"
|
@echo ">> checking code style"
|
||||||
|
@ -53,6 +61,10 @@ vet:
|
||||||
@echo ">> vetting code"
|
@echo ">> vetting code"
|
||||||
@$(GO) vet $(pkgs)
|
@$(GO) vet $(pkgs)
|
||||||
|
|
||||||
|
staticcheck: $(STATICCHECK)
|
||||||
|
@echo ">> running staticcheck"
|
||||||
|
@$(STATICCHECK) -ignore "$(STATICCHECK_IGNORE)" $(pkgs)
|
||||||
|
|
||||||
build: promu
|
build: promu
|
||||||
@echo ">> building binaries"
|
@echo ">> building binaries"
|
||||||
@$(PROMU) build --prefix $(PREFIX)
|
@$(PROMU) build --prefix $(PREFIX)
|
||||||
|
@ -77,5 +89,7 @@ promu:
|
||||||
GOARCH=$(subst x86_64,amd64,$(patsubst i%86,386,$(shell uname -m))) \
|
GOARCH=$(subst x86_64,amd64,$(patsubst i%86,386,$(shell uname -m))) \
|
||||||
$(GO) get -u github.com/prometheus/promu
|
$(GO) get -u github.com/prometheus/promu
|
||||||
|
|
||||||
|
$(FIRST_GOPATH)/bin/staticcheck:
|
||||||
|
@GOOS= GOARCH= $(GO) get -u honnef.co/go/tools/cmd/staticcheck
|
||||||
|
|
||||||
.PHONY: all style check_license format build test vet assets tarball docker promu
|
.PHONY: all style check_license format build test vet assets tarball docker promu staticcheck $(FIRST_GOPATH)/bin/staticcheck
|
||||||
|
|
|
@ -2,7 +2,7 @@ machine:
|
||||||
environment:
|
environment:
|
||||||
DOCKER_IMAGE_NAME: prom/prometheus
|
DOCKER_IMAGE_NAME: prom/prometheus
|
||||||
QUAY_IMAGE_NAME: quay.io/prometheus/prometheus
|
QUAY_IMAGE_NAME: quay.io/prometheus/prometheus
|
||||||
DOCKER_TEST_IMAGE_NAME: quay.io/prometheus/golang-builder:1.8-base
|
DOCKER_TEST_IMAGE_NAME: quay.io/prometheus/golang-builder:1.9-base
|
||||||
REPO_PATH: github.com/prometheus/prometheus
|
REPO_PATH: github.com/prometheus/prometheus
|
||||||
pre:
|
pre:
|
||||||
- sudo curl -L -o /usr/bin/docker 'https://s3-external-1.amazonaws.com/circle-downloads/docker-1.9.1-circleci'
|
- sudo curl -L -o /usr/bin/docker 'https://s3-external-1.amazonaws.com/circle-downloads/docker-1.9.1-circleci'
|
||||||
|
|
|
@ -27,7 +27,6 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/asaskevich/govalidator"
|
|
||||||
"github.com/go-kit/kit/log"
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/go-kit/kit/log/level"
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -363,7 +362,7 @@ func main() {
|
||||||
webHandler.Ready()
|
webHandler.Ready()
|
||||||
level.Info(logger).Log("msg", "Server is ready to receive requests.")
|
level.Info(logger).Log("msg", "Server is ready to receive requests.")
|
||||||
|
|
||||||
term := make(chan os.Signal)
|
term := make(chan os.Signal, 1)
|
||||||
signal.Notify(term, os.Interrupt, syscall.SIGTERM)
|
signal.Notify(term, os.Interrupt, syscall.SIGTERM)
|
||||||
select {
|
select {
|
||||||
case <-term:
|
case <-term:
|
||||||
|
@ -413,6 +412,11 @@ func reloadConfig(filename string, logger log.Logger, rls ...Reloadable) (err er
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func startsOrEndsWithQuote(s string) bool {
|
||||||
|
return strings.HasPrefix(s, "\"") || strings.HasPrefix(s, "'") ||
|
||||||
|
strings.HasSuffix(s, "\"") || strings.HasSuffix(s, "'")
|
||||||
|
}
|
||||||
|
|
||||||
// computeExternalURL computes a sanitized external URL from a raw input. It infers unset
|
// computeExternalURL computes a sanitized external URL from a raw input. It infers unset
|
||||||
// URL parts from the OS and the given listen address.
|
// URL parts from the OS and the given listen address.
|
||||||
func computeExternalURL(u, listenAddr string) (*url.URL, error) {
|
func computeExternalURL(u, listenAddr string) (*url.URL, error) {
|
||||||
|
@ -428,8 +432,8 @@ func computeExternalURL(u, listenAddr string) (*url.URL, error) {
|
||||||
u = fmt.Sprintf("http://%s:%s/", hostname, port)
|
u = fmt.Sprintf("http://%s:%s/", hostname, port)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ok := govalidator.IsURL(u); !ok {
|
if startsOrEndsWithQuote(u) {
|
||||||
return nil, fmt.Errorf("invalid external URL %q", u)
|
return nil, fmt.Errorf("URL must not begin or end with quotes")
|
||||||
}
|
}
|
||||||
|
|
||||||
eu, err := url.Parse(u)
|
eu, err := url.Parse(u)
|
||||||
|
|
|
@ -17,29 +17,49 @@ import "testing"
|
||||||
|
|
||||||
func TestComputeExternalURL(t *testing.T) {
|
func TestComputeExternalURL(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
extURL string
|
input string
|
||||||
valid bool
|
valid bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
extURL: "",
|
input: "",
|
||||||
valid: true,
|
valid: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
extURL: "http://proxy.com/prometheus",
|
input: "http://proxy.com/prometheus",
|
||||||
valid: true,
|
valid: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
extURL: "https:/proxy.com/prometheus",
|
input: "'https://url/prometheus'",
|
||||||
|
valid: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "'relative/path/with/quotes'",
|
||||||
|
valid: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "http://alertmanager.company.com",
|
||||||
|
valid: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "https://double--dash.de",
|
||||||
|
valid: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "'http://starts/with/quote",
|
||||||
|
valid: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "ends/with/quote\"",
|
||||||
valid: false,
|
valid: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
r, err := computeExternalURL(test.extURL, "0.0.0.0:9090")
|
r, err := computeExternalURL(test.input, "0.0.0.0:9090")
|
||||||
if test.valid && err != nil {
|
if test.valid && err != nil {
|
||||||
t.Errorf("%d. expected input to be valid, got %s", i, err)
|
t.Errorf("%d. expected input to be valid, got %s", i, err)
|
||||||
} else if !test.valid && err == nil {
|
} else if !test.valid && err == nil {
|
||||||
t.Logf("%+v", r)
|
t.Logf("%+v", test, r)
|
||||||
t.Errorf("%d. expected input to be invalid", i)
|
t.Errorf("%d. expected input to be invalid", i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -468,10 +468,7 @@ func (c *TLSConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
if err := unmarshal((*plain)(c)); err != nil {
|
if err := unmarshal((*plain)(c)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := checkOverflow(c.XXX, "TLS config"); err != nil {
|
return checkOverflow(c.XXX, "TLS config")
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServiceDiscoveryConfig configures lists of different service discovery mechanisms.
|
// ServiceDiscoveryConfig configures lists of different service discovery mechanisms.
|
||||||
|
@ -513,10 +510,7 @@ func (c *ServiceDiscoveryConfig) UnmarshalYAML(unmarshal func(interface{}) error
|
||||||
if err := unmarshal((*plain)(c)); err != nil {
|
if err := unmarshal((*plain)(c)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := checkOverflow(c.XXX, "service discovery config"); err != nil {
|
return checkOverflow(c.XXX, "service discovery config")
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTPClientConfig configures an HTTP client.
|
// HTTPClientConfig configures an HTTP client.
|
||||||
|
@ -633,10 +627,7 @@ func (c *AlertingConfig) UnmarshalYAML(unmarshal func(interface{}) error) error
|
||||||
if err := unmarshal((*plain)(c)); err != nil {
|
if err := unmarshal((*plain)(c)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := checkOverflow(c.XXX, "alerting config"); err != nil {
|
return checkOverflow(c.XXX, "alerting config")
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AlertmanagerConfig configures how Alertmanagers can be discovered and communicated with.
|
// AlertmanagerConfig configures how Alertmanagers can be discovered and communicated with.
|
||||||
|
@ -1088,10 +1079,7 @@ func (c *KubernetesNamespaceDiscovery) UnmarshalYAML(unmarshal func(interface{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := checkOverflow(c.XXX, "namespaces"); err != nil {
|
return checkOverflow(c.XXX, "namespaces")
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GCESDConfig is the configuration for GCE based service discovery.
|
// GCESDConfig is the configuration for GCE based service discovery.
|
||||||
|
@ -1472,10 +1460,7 @@ func (c *RemoteWriteConfig) UnmarshalYAML(unmarshal func(interface{}) error) err
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := checkOverflow(c.XXX, "remote_write"); err != nil {
|
return checkOverflow(c.XXX, "remote_write")
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueueConfig is the configuration for the queue used to write to remote
|
// QueueConfig is the configuration for the queue used to write to remote
|
||||||
|
@ -1532,8 +1517,5 @@ func (c *RemoteReadConfig) UnmarshalYAML(unmarshal func(interface{}) error) erro
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := checkOverflow(c.XXX, "remote_read"); err != nil {
|
return checkOverflow(c.XXX, "remote_read")
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,7 @@ func (d *Discovery) refreshAll(ctx context.Context, ch chan<- []*config.TargetGr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Discovery) refresh(ctx context.Context, name string, ch chan<- []*config.TargetGroup) error {
|
func (d *Discovery) refresh(ctx context.Context, name string, ch chan<- []*config.TargetGroup) error {
|
||||||
response, err := lookupAll(name, d.qtype, d.logger)
|
response, err := lookupWithSearchPath(name, d.qtype, d.logger)
|
||||||
dnsSDLookupsCount.Inc()
|
dnsSDLookupsCount.Inc()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
dnsSDLookupFailuresCount.Inc()
|
dnsSDLookupFailuresCount.Inc()
|
||||||
|
@ -156,7 +156,6 @@ func (d *Discovery) refresh(ctx context.Context, name string, ch chan<- []*confi
|
||||||
default:
|
default:
|
||||||
level.Warn(d.logger).Log("msg", "Invalid SRV record", "record", record)
|
level.Warn(d.logger).Log("msg", "Invalid SRV record", "record", record)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
}
|
}
|
||||||
tg.Targets = append(tg.Targets, model.LabelSet{
|
tg.Targets = append(tg.Targets, model.LabelSet{
|
||||||
model.AddressLabel: target,
|
model.AddressLabel: target,
|
||||||
|
@ -174,35 +173,109 @@ func (d *Discovery) refresh(ctx context.Context, name string, ch chan<- []*confi
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func lookupAll(name string, qtype uint16, logger log.Logger) (*dns.Msg, error) {
|
// lookupWithSearchPath tries to get an answer for various permutations of
|
||||||
|
// the given name, appending the system-configured search path as necessary.
|
||||||
|
//
|
||||||
|
// There are three possible outcomes:
|
||||||
|
//
|
||||||
|
// 1. One of the permutations of the given name is recognised as
|
||||||
|
// "valid" by the DNS, in which case we consider ourselves "done"
|
||||||
|
// and that answer is returned. Note that, due to the way the DNS
|
||||||
|
// handles "name has resource records, but none of the specified type",
|
||||||
|
// the answer received may have an empty set of results.
|
||||||
|
//
|
||||||
|
// 2. All of the permutations of the given name are responded to by one of
|
||||||
|
// the servers in the "nameservers" list with the answer "that name does
|
||||||
|
// not exist" (NXDOMAIN). In that case, it can be considered
|
||||||
|
// pseudo-authoritative that there are no records for that name.
|
||||||
|
//
|
||||||
|
// 3. One or more of the names was responded to by all servers with some
|
||||||
|
// sort of error indication. In that case, we can't know if, in fact,
|
||||||
|
// there are records for the name or not, so whatever state the
|
||||||
|
// configuration is in, we should keep it that way until we know for
|
||||||
|
// sure (by, presumably, all the names getting answers in the future).
|
||||||
|
//
|
||||||
|
// Outcomes 1 and 2 are indicated by a valid response message (possibly an
|
||||||
|
// empty one) and no error. Outcome 3 is indicated by an error return. The
|
||||||
|
// error will be generic-looking, because trying to return all the errors
|
||||||
|
// returned by the combination of all name permutations and servers is a
|
||||||
|
// nightmare.
|
||||||
|
func lookupWithSearchPath(name string, qtype uint16, logger log.Logger) (*dns.Msg, error) {
|
||||||
conf, err := dns.ClientConfigFromFile(resolvConf)
|
conf, err := dns.ClientConfigFromFile(resolvConf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not load resolv.conf: %s", err)
|
return nil, fmt.Errorf("could not load resolv.conf: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allResponsesValid := true
|
||||||
|
|
||||||
|
for _, lname := range conf.NameList(name) {
|
||||||
|
response, err := lookupFromAnyServer(lname, qtype, conf, logger)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// We can't go home yet, because a later name
|
||||||
|
// may give us a valid, successful answer. However
|
||||||
|
// we can no longer say "this name definitely doesn't
|
||||||
|
// exist", because we did not get that answer for
|
||||||
|
// at least one name.
|
||||||
|
allResponsesValid = false
|
||||||
|
} else if response.Rcode == dns.RcodeSuccess {
|
||||||
|
// Outcome 1: GOLD!
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if allResponsesValid {
|
||||||
|
// Outcome 2: everyone says NXDOMAIN, that's good enough for me
|
||||||
|
return &dns.Msg{}, nil
|
||||||
|
}
|
||||||
|
// Outcome 3: boned.
|
||||||
|
return nil, fmt.Errorf("could not resolve %q: all servers responded with errors to at least one search domain", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// lookupFromAnyServer uses all configured servers to try and resolve a specific
|
||||||
|
// name. If a viable answer is received from a server, then it is
|
||||||
|
// immediately returned, otherwise the other servers in the config are
|
||||||
|
// tried, and if none of them return a viable answer, an error is returned.
|
||||||
|
//
|
||||||
|
// A "viable answer" is one which indicates either:
|
||||||
|
//
|
||||||
|
// 1. "yes, I know that name, and here are its records of the requested type"
|
||||||
|
// (RCODE==SUCCESS, ANCOUNT > 0);
|
||||||
|
// 2. "yes, I know that name, but it has no records of the requested type"
|
||||||
|
// (RCODE==SUCCESS, ANCOUNT==0); or
|
||||||
|
// 3. "I know that name doesn't exist" (RCODE==NXDOMAIN).
|
||||||
|
//
|
||||||
|
// A non-viable answer is "anything else", which encompasses both various
|
||||||
|
// system-level problems (like network timeouts) and also
|
||||||
|
// valid-but-unexpected DNS responses (SERVFAIL, REFUSED, etc).
|
||||||
|
func lookupFromAnyServer(name string, qtype uint16, conf *dns.ClientConfig, logger log.Logger) (*dns.Msg, error) {
|
||||||
client := &dns.Client{}
|
client := &dns.Client{}
|
||||||
response := &dns.Msg{}
|
|
||||||
|
|
||||||
for _, server := range conf.Servers {
|
for _, server := range conf.Servers {
|
||||||
servAddr := net.JoinHostPort(server, conf.Port)
|
servAddr := net.JoinHostPort(server, conf.Port)
|
||||||
for _, lname := range conf.NameList(name) {
|
msg, err := askServerForName(name, qtype, client, servAddr, false)
|
||||||
response, err = lookup(lname, qtype, client, servAddr, false)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
level.Warn(logger).Log("msg", "DNS resolution failed", "server", server, "name", name, "err", err)
|
level.Warn(logger).Log("msg", "DNS resolution failed", "server", server, "name", name, "err", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if len(response.Answer) > 0 {
|
|
||||||
return response, nil
|
if msg.Rcode == dns.RcodeSuccess || msg.Rcode == dns.RcodeNameError {
|
||||||
|
// We have our answer. Time to go home.
|
||||||
|
return msg, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return response, fmt.Errorf("could not resolve %s: no server responded", name)
|
return nil, fmt.Errorf("could not resolve %s: no servers returned a viable answer", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func lookup(lname string, queryType uint16, client *dns.Client, servAddr string, edns bool) (*dns.Msg, error) {
|
// askServerForName makes a request to a specific DNS server for a specific
|
||||||
|
// name (and qtype). Retries in the event of response truncation, but
|
||||||
|
// otherwise just sends back whatever the server gave, whether that be a
|
||||||
|
// valid-looking response, or an error.
|
||||||
|
func askServerForName(name string, queryType uint16, client *dns.Client, servAddr string, edns bool) (*dns.Msg, error) {
|
||||||
msg := &dns.Msg{}
|
msg := &dns.Msg{}
|
||||||
msg.SetQuestion(dns.Fqdn(lname), queryType)
|
|
||||||
|
|
||||||
|
msg.SetQuestion(dns.Fqdn(name), queryType)
|
||||||
if edns {
|
if edns {
|
||||||
msg.SetEdns0(dns.DefaultMsgSize, false)
|
msg.SetEdns0(dns.DefaultMsgSize, false)
|
||||||
}
|
}
|
||||||
|
@ -215,7 +288,7 @@ func lookup(lname string, queryType uint16, client *dns.Client, servAddr string,
|
||||||
if edns { // Truncated even though EDNS is used
|
if edns { // Truncated even though EDNS is used
|
||||||
client.Net = "tcp"
|
client.Net = "tcp"
|
||||||
}
|
}
|
||||||
return lookup(lname, queryType, client, servAddr, !edns)
|
return askServerForName(name, queryType, client, servAddr, !edns)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -345,8 +345,8 @@ func (r *AlertingRule) HTMLSnippet(pathPrefix string) html_template.HTML {
|
||||||
}
|
}
|
||||||
|
|
||||||
ar := rulefmt.Rule{
|
ar := rulefmt.Rule{
|
||||||
Alert: fmt.Sprintf("<a href=%q>%s</a>", pathPrefix+strutil.GraphLinkForExpression(alertMetric.String()), r.name),
|
Alert: fmt.Sprintf("<a href=%q>%s</a>", pathPrefix+strutil.TableLinkForExpression(alertMetric.String()), r.name),
|
||||||
Expr: fmt.Sprintf("<a href=%q>%s</a>", pathPrefix+strutil.GraphLinkForExpression(r.vector.String()), html_template.HTMLEscapeString(r.vector.String())),
|
Expr: fmt.Sprintf("<a href=%q>%s</a>", pathPrefix+strutil.TableLinkForExpression(r.vector.String()), html_template.HTMLEscapeString(r.vector.String())),
|
||||||
For: model.Duration(r.holdDuration),
|
For: model.Duration(r.holdDuration),
|
||||||
Labels: labels,
|
Labels: labels,
|
||||||
Annotations: annotations,
|
Annotations: annotations,
|
||||||
|
|
|
@ -27,8 +27,8 @@ func TestAlertingRuleHTMLSnippet(t *testing.T) {
|
||||||
}
|
}
|
||||||
rule := NewAlertingRule("testrule", expr, 0, labels.FromStrings("html", "<b>BOLD</b>"), labels.FromStrings("html", "<b>BOLD</b>"), nil)
|
rule := NewAlertingRule("testrule", expr, 0, labels.FromStrings("html", "<b>BOLD</b>"), labels.FromStrings("html", "<b>BOLD</b>"), nil)
|
||||||
|
|
||||||
const want = `alert: <a href="/test/prefix/graph?g0.expr=ALERTS%7Balertname%3D%22testrule%22%7D&g0.tab=0">testrule</a>
|
const want = `alert: <a href="/test/prefix/graph?g0.expr=ALERTS%7Balertname%3D%22testrule%22%7D&g0.tab=1">testrule</a>
|
||||||
expr: <a href="/test/prefix/graph?g0.expr=foo%7Bhtml%3D%22%3Cb%3EBOLD%3Cb%3E%22%7D&g0.tab=0">foo{html="<b>BOLD<b>"}</a>
|
expr: <a href="/test/prefix/graph?g0.expr=foo%7Bhtml%3D%22%3Cb%3EBOLD%3Cb%3E%22%7D&g0.tab=1">foo{html="<b>BOLD<b>"}</a>
|
||||||
labels:
|
labels:
|
||||||
html: '<b>BOLD</b>'
|
html: '<b>BOLD</b>'
|
||||||
annotations:
|
annotations:
|
||||||
|
|
|
@ -390,7 +390,7 @@ func (g *Group) sendAlerts(rule *AlertingRule) error {
|
||||||
StartsAt: alert.ActiveAt.Add(rule.holdDuration),
|
StartsAt: alert.ActiveAt.Add(rule.holdDuration),
|
||||||
Labels: alert.Labels,
|
Labels: alert.Labels,
|
||||||
Annotations: alert.Annotations,
|
Annotations: alert.Annotations,
|
||||||
GeneratorURL: g.opts.ExternalURL.String() + strutil.GraphLinkForExpression(rule.vector.String()),
|
GeneratorURL: g.opts.ExternalURL.String() + strutil.TableLinkForExpression(rule.vector.String()),
|
||||||
}
|
}
|
||||||
if !alert.ResolvedAt.IsZero() {
|
if !alert.ResolvedAt.IsZero() {
|
||||||
a.EndsAt = alert.ResolvedAt
|
a.EndsAt = alert.ResolvedAt
|
||||||
|
|
|
@ -123,8 +123,8 @@ func (rule RecordingRule) HTMLSnippet(pathPrefix string) template.HTML {
|
||||||
}
|
}
|
||||||
|
|
||||||
r := rulefmt.Rule{
|
r := rulefmt.Rule{
|
||||||
Record: fmt.Sprintf(`<a href="%s">%s</a>`, pathPrefix+strutil.GraphLinkForExpression(rule.name), rule.name),
|
Record: fmt.Sprintf(`<a href="%s">%s</a>`, pathPrefix+strutil.TableLinkForExpression(rule.name), rule.name),
|
||||||
Expr: fmt.Sprintf(`<a href="%s">%s</a>`, pathPrefix+strutil.GraphLinkForExpression(ruleExpr), template.HTMLEscapeString(ruleExpr)),
|
Expr: fmt.Sprintf(`<a href="%s">%s</a>`, pathPrefix+strutil.TableLinkForExpression(ruleExpr), template.HTMLEscapeString(ruleExpr)),
|
||||||
Labels: labels,
|
Labels: labels,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,8 +81,8 @@ func TestRecordingRuleHTMLSnippet(t *testing.T) {
|
||||||
}
|
}
|
||||||
rule := NewRecordingRule("testrule", expr, labels.FromStrings("html", "<b>BOLD</b>"))
|
rule := NewRecordingRule("testrule", expr, labels.FromStrings("html", "<b>BOLD</b>"))
|
||||||
|
|
||||||
const want = `record: <a href="/test/prefix/graph?g0.expr=testrule&g0.tab=0">testrule</a>
|
const want = `record: <a href="/test/prefix/graph?g0.expr=testrule&g0.tab=1">testrule</a>
|
||||||
expr: <a href="/test/prefix/graph?g0.expr=foo%7Bhtml%3D%22%3Cb%3EBOLD%3Cb%3E%22%7D&g0.tab=0">foo{html="<b>BOLD<b>"}</a>
|
expr: <a href="/test/prefix/graph?g0.expr=foo%7Bhtml%3D%22%3Cb%3EBOLD%3Cb%3E%22%7D&g0.tab=1">foo{html="<b>BOLD<b>"}</a>
|
||||||
labels:
|
labels:
|
||||||
html: '<b>BOLD</b>'
|
html: '<b>BOLD</b>'
|
||||||
`
|
`
|
||||||
|
|
|
@ -41,7 +41,7 @@ func NewClientFromConfig(cfg config.HTTPClientConfig) (*http.Client, error) {
|
||||||
// It is applied on request. So we leave out any timings here.
|
// It is applied on request. So we leave out any timings here.
|
||||||
var rt http.RoundTripper = &http.Transport{
|
var rt http.RoundTripper = &http.Transport{
|
||||||
Proxy: http.ProxyURL(cfg.ProxyURL.URL),
|
Proxy: http.ProxyURL(cfg.ProxyURL.URL),
|
||||||
MaxIdleConns: 10000,
|
MaxIdleConns: 20000,
|
||||||
DisableKeepAlives: false,
|
DisableKeepAlives: false,
|
||||||
TLSClientConfig: tlsConfig,
|
TLSClientConfig: tlsConfig,
|
||||||
DisableCompression: true,
|
DisableCompression: true,
|
||||||
|
|
|
@ -53,7 +53,6 @@ func (t *Timer) String() string {
|
||||||
// A TimerGroup represents a group of timers relevant to a single query.
|
// A TimerGroup represents a group of timers relevant to a single query.
|
||||||
type TimerGroup struct {
|
type TimerGroup struct {
|
||||||
timers map[fmt.Stringer]*Timer
|
timers map[fmt.Stringer]*Timer
|
||||||
child *TimerGroup
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTimerGroup constructs a new TimerGroup.
|
// NewTimerGroup constructs a new TimerGroup.
|
||||||
|
|
21
vendor/github.com/asaskevich/govalidator/LICENSE
generated
vendored
21
vendor/github.com/asaskevich/govalidator/LICENSE
generated
vendored
|
@ -1,21 +0,0 @@
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2014 Alex Saskevich
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
421
vendor/github.com/asaskevich/govalidator/README.md
generated
vendored
421
vendor/github.com/asaskevich/govalidator/README.md
generated
vendored
|
@ -1,421 +0,0 @@
|
||||||
govalidator
|
|
||||||
===========
|
|
||||||
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/asaskevich/govalidator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![GoDoc](https://godoc.org/github.com/asaskevich/govalidator?status.png)](https://godoc.org/github.com/asaskevich/govalidator) [![Coverage Status](https://img.shields.io/coveralls/asaskevich/govalidator.svg)](https://coveralls.io/r/asaskevich/govalidator?branch=master) [![wercker status](https://app.wercker.com/status/1ec990b09ea86c910d5f08b0e02c6043/s "wercker status")](https://app.wercker.com/project/bykey/1ec990b09ea86c910d5f08b0e02c6043)
|
|
||||||
[![Build Status](https://travis-ci.org/asaskevich/govalidator.svg?branch=master)](https://travis-ci.org/asaskevich/govalidator) [![Go Report Card](https://goreportcard.com/badge/github.com/asaskevich/govalidator)](https://goreportcard.com/report/github.com/asaskevich/govalidator) [![GoSearch](http://go-search.org/badge?id=github.com%2Fasaskevich%2Fgovalidator)](http://go-search.org/view?id=github.com%2Fasaskevich%2Fgovalidator)
|
|
||||||
|
|
||||||
A package of validators and sanitizers for strings, structs and collections. Based on [validator.js](https://github.com/chriso/validator.js).
|
|
||||||
|
|
||||||
#### Installation
|
|
||||||
Make sure that Go is installed on your computer.
|
|
||||||
Type the following command in your terminal:
|
|
||||||
|
|
||||||
go get github.com/asaskevich/govalidator
|
|
||||||
|
|
||||||
or you can get specified release of the package with `gopkg.in`:
|
|
||||||
|
|
||||||
go get gopkg.in/asaskevich/govalidator.v4
|
|
||||||
|
|
||||||
After it the package is ready to use.
|
|
||||||
|
|
||||||
|
|
||||||
#### Import package in your project
|
|
||||||
Add following line in your `*.go` file:
|
|
||||||
```go
|
|
||||||
import "github.com/asaskevich/govalidator"
|
|
||||||
```
|
|
||||||
If you are unhappy to use long `govalidator`, you can do something like this:
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
valid "github.com/asaskevich/govalidator"
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Activate behavior to require all fields have a validation tag by default
|
|
||||||
`SetFieldsRequiredByDefault` causes validation to fail when struct fields do not include validations or are not explicitly marked as exempt (using `valid:"-"` or `valid:"email,optional"`). A good place to activate this is a package init function or the main() function.
|
|
||||||
|
|
||||||
```go
|
|
||||||
import "github.com/asaskevich/govalidator"
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
govalidator.SetFieldsRequiredByDefault(true)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Here's some code to explain it:
|
|
||||||
```go
|
|
||||||
// this struct definition will fail govalidator.ValidateStruct() (and the field values do not matter):
|
|
||||||
type exampleStruct struct {
|
|
||||||
Name string ``
|
|
||||||
Email string `valid:"email"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// this, however, will only fail when Email is empty or an invalid email address:
|
|
||||||
type exampleStruct2 struct {
|
|
||||||
Name string `valid:"-"`
|
|
||||||
Email string `valid:"email"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// lastly, this will only fail when Email is an invalid email address but not when it's empty:
|
|
||||||
type exampleStruct2 struct {
|
|
||||||
Name string `valid:"-"`
|
|
||||||
Email string `valid:"email,optional"`
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Recent breaking changes (see [#123](https://github.com/asaskevich/govalidator/pull/123))
|
|
||||||
##### Custom validator function signature
|
|
||||||
A context was added as the second parameter, for structs this is the object being validated – this makes dependent validation possible.
|
|
||||||
```go
|
|
||||||
import "github.com/asaskevich/govalidator"
|
|
||||||
|
|
||||||
// old signature
|
|
||||||
func(i interface{}) bool
|
|
||||||
|
|
||||||
// new signature
|
|
||||||
func(i interface{}, o interface{}) bool
|
|
||||||
```
|
|
||||||
|
|
||||||
##### Adding a custom validator
|
|
||||||
This was changed to prevent data races when accessing custom validators.
|
|
||||||
```go
|
|
||||||
import "github.com/asaskevich/govalidator"
|
|
||||||
|
|
||||||
// before
|
|
||||||
govalidator.CustomTypeTagMap["customByteArrayValidator"] = CustomTypeValidator(func(i interface{}, o interface{}) bool {
|
|
||||||
// ...
|
|
||||||
})
|
|
||||||
|
|
||||||
// after
|
|
||||||
govalidator.CustomTypeTagMap.Set("customByteArrayValidator", CustomTypeValidator(func(i interface{}, o interface{}) bool {
|
|
||||||
// ...
|
|
||||||
}))
|
|
||||||
```
|
|
||||||
|
|
||||||
#### List of functions:
|
|
||||||
```go
|
|
||||||
func Abs(value float64) float64
|
|
||||||
func BlackList(str, chars string) string
|
|
||||||
func ByteLength(str string, params ...string) bool
|
|
||||||
func CamelCaseToUnderscore(str string) string
|
|
||||||
func Contains(str, substring string) bool
|
|
||||||
func Count(array []interface{}, iterator ConditionIterator) int
|
|
||||||
func Each(array []interface{}, iterator Iterator)
|
|
||||||
func ErrorByField(e error, field string) string
|
|
||||||
func ErrorsByField(e error) map[string]string
|
|
||||||
func Filter(array []interface{}, iterator ConditionIterator) []interface{}
|
|
||||||
func Find(array []interface{}, iterator ConditionIterator) interface{}
|
|
||||||
func GetLine(s string, index int) (string, error)
|
|
||||||
func GetLines(s string) []string
|
|
||||||
func InRange(value, left, right float64) bool
|
|
||||||
func IsASCII(str string) bool
|
|
||||||
func IsAlpha(str string) bool
|
|
||||||
func IsAlphanumeric(str string) bool
|
|
||||||
func IsBase64(str string) bool
|
|
||||||
func IsByteLength(str string, min, max int) bool
|
|
||||||
func IsCIDR(str string) bool
|
|
||||||
func IsCreditCard(str string) bool
|
|
||||||
func IsDNSName(str string) bool
|
|
||||||
func IsDataURI(str string) bool
|
|
||||||
func IsDialString(str string) bool
|
|
||||||
func IsDivisibleBy(str, num string) bool
|
|
||||||
func IsEmail(str string) bool
|
|
||||||
func IsFilePath(str string) (bool, int)
|
|
||||||
func IsFloat(str string) bool
|
|
||||||
func IsFullWidth(str string) bool
|
|
||||||
func IsHalfWidth(str string) bool
|
|
||||||
func IsHexadecimal(str string) bool
|
|
||||||
func IsHexcolor(str string) bool
|
|
||||||
func IsHost(str string) bool
|
|
||||||
func IsIP(str string) bool
|
|
||||||
func IsIPv4(str string) bool
|
|
||||||
func IsIPv6(str string) bool
|
|
||||||
func IsISBN(str string, version int) bool
|
|
||||||
func IsISBN10(str string) bool
|
|
||||||
func IsISBN13(str string) bool
|
|
||||||
func IsISO3166Alpha2(str string) bool
|
|
||||||
func IsISO3166Alpha3(str string) bool
|
|
||||||
func IsISO4217(str string) bool
|
|
||||||
func IsIn(str string, params ...string) bool
|
|
||||||
func IsInt(str string) bool
|
|
||||||
func IsJSON(str string) bool
|
|
||||||
func IsLatitude(str string) bool
|
|
||||||
func IsLongitude(str string) bool
|
|
||||||
func IsLowerCase(str string) bool
|
|
||||||
func IsMAC(str string) bool
|
|
||||||
func IsMongoID(str string) bool
|
|
||||||
func IsMultibyte(str string) bool
|
|
||||||
func IsNatural(value float64) bool
|
|
||||||
func IsNegative(value float64) bool
|
|
||||||
func IsNonNegative(value float64) bool
|
|
||||||
func IsNonPositive(value float64) bool
|
|
||||||
func IsNull(str string) bool
|
|
||||||
func IsNumeric(str string) bool
|
|
||||||
func IsPort(str string) bool
|
|
||||||
func IsPositive(value float64) bool
|
|
||||||
func IsPrintableASCII(str string) bool
|
|
||||||
func IsRFC3339(str string) bool
|
|
||||||
func IsRGBcolor(str string) bool
|
|
||||||
func IsRequestURI(rawurl string) bool
|
|
||||||
func IsRequestURL(rawurl string) bool
|
|
||||||
func IsSSN(str string) bool
|
|
||||||
func IsSemver(str string) bool
|
|
||||||
func IsTime(str string, format string) bool
|
|
||||||
func IsURL(str string) bool
|
|
||||||
func IsUTFDigit(str string) bool
|
|
||||||
func IsUTFLetter(str string) bool
|
|
||||||
func IsUTFLetterNumeric(str string) bool
|
|
||||||
func IsUTFNumeric(str string) bool
|
|
||||||
func IsUUID(str string) bool
|
|
||||||
func IsUUIDv3(str string) bool
|
|
||||||
func IsUUIDv4(str string) bool
|
|
||||||
func IsUUIDv5(str string) bool
|
|
||||||
func IsUpperCase(str string) bool
|
|
||||||
func IsVariableWidth(str string) bool
|
|
||||||
func IsWhole(value float64) bool
|
|
||||||
func LeftTrim(str, chars string) string
|
|
||||||
func Map(array []interface{}, iterator ResultIterator) []interface{}
|
|
||||||
func Matches(str, pattern string) bool
|
|
||||||
func NormalizeEmail(str string) (string, error)
|
|
||||||
func PadBoth(str string, padStr string, padLen int) string
|
|
||||||
func PadLeft(str string, padStr string, padLen int) string
|
|
||||||
func PadRight(str string, padStr string, padLen int) string
|
|
||||||
func Range(str string, params ...string) bool
|
|
||||||
func RemoveTags(s string) string
|
|
||||||
func ReplacePattern(str, pattern, replace string) string
|
|
||||||
func Reverse(s string) string
|
|
||||||
func RightTrim(str, chars string) string
|
|
||||||
func RuneLength(str string, params ...string) bool
|
|
||||||
func SafeFileName(str string) string
|
|
||||||
func SetFieldsRequiredByDefault(value bool)
|
|
||||||
func Sign(value float64) float64
|
|
||||||
func StringLength(str string, params ...string) bool
|
|
||||||
func StringMatches(s string, params ...string) bool
|
|
||||||
func StripLow(str string, keepNewLines bool) string
|
|
||||||
func ToBoolean(str string) (bool, error)
|
|
||||||
func ToFloat(str string) (float64, error)
|
|
||||||
func ToInt(str string) (int64, error)
|
|
||||||
func ToJSON(obj interface{}) (string, error)
|
|
||||||
func ToString(obj interface{}) string
|
|
||||||
func Trim(str, chars string) string
|
|
||||||
func Truncate(str string, length int, ending string) string
|
|
||||||
func UnderscoreToCamelCase(s string) string
|
|
||||||
func ValidateStruct(s interface{}) (bool, error)
|
|
||||||
func WhiteList(str, chars string) string
|
|
||||||
type ConditionIterator
|
|
||||||
type CustomTypeValidator
|
|
||||||
type Error
|
|
||||||
func (e Error) Error() string
|
|
||||||
type Errors
|
|
||||||
func (es Errors) Error() string
|
|
||||||
func (es Errors) Errors() []error
|
|
||||||
type ISO3166Entry
|
|
||||||
type Iterator
|
|
||||||
type ParamValidator
|
|
||||||
type ResultIterator
|
|
||||||
type UnsupportedTypeError
|
|
||||||
func (e *UnsupportedTypeError) Error() string
|
|
||||||
type Validator
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Examples
|
|
||||||
###### IsURL
|
|
||||||
```go
|
|
||||||
println(govalidator.IsURL(`http://user@pass:domain.com/path/page`))
|
|
||||||
```
|
|
||||||
###### ToString
|
|
||||||
```go
|
|
||||||
type User struct {
|
|
||||||
FirstName string
|
|
||||||
LastName string
|
|
||||||
}
|
|
||||||
|
|
||||||
str := govalidator.ToString(&User{"John", "Juan"})
|
|
||||||
println(str)
|
|
||||||
```
|
|
||||||
###### Each, Map, Filter, Count for slices
|
|
||||||
Each iterates over the slice/array and calls Iterator for every item
|
|
||||||
```go
|
|
||||||
data := []interface{}{1, 2, 3, 4, 5}
|
|
||||||
var fn govalidator.Iterator = func(value interface{}, index int) {
|
|
||||||
println(value.(int))
|
|
||||||
}
|
|
||||||
govalidator.Each(data, fn)
|
|
||||||
```
|
|
||||||
```go
|
|
||||||
data := []interface{}{1, 2, 3, 4, 5}
|
|
||||||
var fn govalidator.ResultIterator = func(value interface{}, index int) interface{} {
|
|
||||||
return value.(int) * 3
|
|
||||||
}
|
|
||||||
_ = govalidator.Map(data, fn) // result = []interface{}{1, 6, 9, 12, 15}
|
|
||||||
```
|
|
||||||
```go
|
|
||||||
data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
|
|
||||||
var fn govalidator.ConditionIterator = func(value interface{}, index int) bool {
|
|
||||||
return value.(int)%2 == 0
|
|
||||||
}
|
|
||||||
_ = govalidator.Filter(data, fn) // result = []interface{}{2, 4, 6, 8, 10}
|
|
||||||
_ = govalidator.Count(data, fn) // result = 5
|
|
||||||
```
|
|
||||||
###### ValidateStruct [#2](https://github.com/asaskevich/govalidator/pull/2)
|
|
||||||
If you want to validate structs, you can use tag `valid` for any field in your structure. All validators used with this field in one tag are separated by comma. If you want to skip validation, place `-` in your tag. If you need a validator that is not on the list below, you can add it like this:
|
|
||||||
```go
|
|
||||||
govalidator.TagMap["duck"] = govalidator.Validator(func(str string) bool {
|
|
||||||
return str == "duck"
|
|
||||||
})
|
|
||||||
```
|
|
||||||
For completely custom validators (interface-based), see below.
|
|
||||||
|
|
||||||
Here is a list of available validators for struct fields (validator - used function):
|
|
||||||
```go
|
|
||||||
"email": IsEmail,
|
|
||||||
"url": IsURL,
|
|
||||||
"dialstring": IsDialString,
|
|
||||||
"requrl": IsRequestURL,
|
|
||||||
"requri": IsRequestURI,
|
|
||||||
"alpha": IsAlpha,
|
|
||||||
"utfletter": IsUTFLetter,
|
|
||||||
"alphanum": IsAlphanumeric,
|
|
||||||
"utfletternum": IsUTFLetterNumeric,
|
|
||||||
"numeric": IsNumeric,
|
|
||||||
"utfnumeric": IsUTFNumeric,
|
|
||||||
"utfdigit": IsUTFDigit,
|
|
||||||
"hexadecimal": IsHexadecimal,
|
|
||||||
"hexcolor": IsHexcolor,
|
|
||||||
"rgbcolor": IsRGBcolor,
|
|
||||||
"lowercase": IsLowerCase,
|
|
||||||
"uppercase": IsUpperCase,
|
|
||||||
"int": IsInt,
|
|
||||||
"float": IsFloat,
|
|
||||||
"null": IsNull,
|
|
||||||
"uuid": IsUUID,
|
|
||||||
"uuidv3": IsUUIDv3,
|
|
||||||
"uuidv4": IsUUIDv4,
|
|
||||||
"uuidv5": IsUUIDv5,
|
|
||||||
"creditcard": IsCreditCard,
|
|
||||||
"isbn10": IsISBN10,
|
|
||||||
"isbn13": IsISBN13,
|
|
||||||
"json": IsJSON,
|
|
||||||
"multibyte": IsMultibyte,
|
|
||||||
"ascii": IsASCII,
|
|
||||||
"printableascii": IsPrintableASCII,
|
|
||||||
"fullwidth": IsFullWidth,
|
|
||||||
"halfwidth": IsHalfWidth,
|
|
||||||
"variablewidth": IsVariableWidth,
|
|
||||||
"base64": IsBase64,
|
|
||||||
"datauri": IsDataURI,
|
|
||||||
"ip": IsIP,
|
|
||||||
"port": IsPort,
|
|
||||||
"ipv4": IsIPv4,
|
|
||||||
"ipv6": IsIPv6,
|
|
||||||
"dns": IsDNSName,
|
|
||||||
"host": IsHost,
|
|
||||||
"mac": IsMAC,
|
|
||||||
"latitude": IsLatitude,
|
|
||||||
"longitude": IsLongitude,
|
|
||||||
"ssn": IsSSN,
|
|
||||||
"semver": IsSemver,
|
|
||||||
"rfc3339": IsRFC3339,
|
|
||||||
"ISO3166Alpha2": IsISO3166Alpha2,
|
|
||||||
"ISO3166Alpha3": IsISO3166Alpha3,
|
|
||||||
```
|
|
||||||
Validators with parameters
|
|
||||||
|
|
||||||
```go
|
|
||||||
"range(min|max)": Range,
|
|
||||||
"length(min|max)": ByteLength,
|
|
||||||
"runelength(min|max)": RuneLength,
|
|
||||||
"matches(pattern)": StringMatches,
|
|
||||||
"in(string1|string2|...|stringN)": IsIn,
|
|
||||||
```
|
|
||||||
|
|
||||||
And here is small example of usage:
|
|
||||||
```go
|
|
||||||
type Post struct {
|
|
||||||
Title string `valid:"alphanum,required"`
|
|
||||||
Message string `valid:"duck,ascii"`
|
|
||||||
AuthorIP string `valid:"ipv4"`
|
|
||||||
Date string `valid:"-"`
|
|
||||||
}
|
|
||||||
post := &Post{
|
|
||||||
Title: "My Example Post",
|
|
||||||
Message: "duck",
|
|
||||||
AuthorIP: "123.234.54.3",
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add your own struct validation tags
|
|
||||||
govalidator.TagMap["duck"] = govalidator.Validator(func(str string) bool {
|
|
||||||
return str == "duck"
|
|
||||||
})
|
|
||||||
|
|
||||||
result, err := govalidator.ValidateStruct(post)
|
|
||||||
if err != nil {
|
|
||||||
println("error: " + err.Error())
|
|
||||||
}
|
|
||||||
println(result)
|
|
||||||
```
|
|
||||||
###### WhiteList
|
|
||||||
```go
|
|
||||||
// Remove all characters from string ignoring characters between "a" and "z"
|
|
||||||
println(govalidator.WhiteList("a3a43a5a4a3a2a23a4a5a4a3a4", "a-z") == "aaaaaaaaaaaa")
|
|
||||||
```
|
|
||||||
|
|
||||||
###### Custom validation functions
|
|
||||||
Custom validation using your own domain specific validators is also available - here's an example of how to use it:
|
|
||||||
```go
|
|
||||||
import "github.com/asaskevich/govalidator"
|
|
||||||
|
|
||||||
type CustomByteArray [6]byte // custom types are supported and can be validated
|
|
||||||
|
|
||||||
type StructWithCustomByteArray struct {
|
|
||||||
ID CustomByteArray `valid:"customByteArrayValidator,customMinLengthValidator"` // multiple custom validators are possible as well and will be evaluated in sequence
|
|
||||||
Email string `valid:"email"`
|
|
||||||
CustomMinLength int `valid:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
govalidator.CustomTypeTagMap.Set("customByteArrayValidator", CustomTypeValidator(func(i interface{}, context interface{}) bool {
|
|
||||||
switch v := context.(type) { // you can type switch on the context interface being validated
|
|
||||||
case StructWithCustomByteArray:
|
|
||||||
// you can check and validate against some other field in the context,
|
|
||||||
// return early or not validate against the context at all – your choice
|
|
||||||
case SomeOtherType:
|
|
||||||
// ...
|
|
||||||
default:
|
|
||||||
// expecting some other type? Throw/panic here or continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch v := i.(type) { // type switch on the struct field being validated
|
|
||||||
case CustomByteArray:
|
|
||||||
for _, e := range v { // this validator checks that the byte array is not empty, i.e. not all zeroes
|
|
||||||
if e != 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}))
|
|
||||||
govalidator.CustomTypeTagMap.Set("customMinLengthValidator", CustomTypeValidator(func(i interface{}, context interface{}) bool {
|
|
||||||
switch v := context.(type) { // this validates a field against the value in another field, i.e. dependent validation
|
|
||||||
case StructWithCustomByteArray:
|
|
||||||
return len(v.ID) >= v.CustomMinLength
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}))
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Notes
|
|
||||||
Documentation is available here: [godoc.org](https://godoc.org/github.com/asaskevich/govalidator).
|
|
||||||
Full information about code coverage is also available here: [govalidator on gocover.io](http://gocover.io/github.com/asaskevich/govalidator).
|
|
||||||
|
|
||||||
#### Support
|
|
||||||
If you do have a contribution for the package feel free to put up a Pull Request or open Issue.
|
|
||||||
|
|
||||||
#### Special thanks to [contributors](https://github.com/asaskevich/govalidator/graphs/contributors)
|
|
||||||
* [Daniel Lohse](https://github.com/annismckenzie)
|
|
||||||
* [Attila Oláh](https://github.com/attilaolah)
|
|
||||||
* [Daniel Korner](https://github.com/Dadie)
|
|
||||||
* [Steven Wilkin](https://github.com/stevenwilkin)
|
|
||||||
* [Deiwin Sarjas](https://github.com/deiwin)
|
|
||||||
* [Noah Shibley](https://github.com/slugmobile)
|
|
||||||
* [Nathan Davies](https://github.com/nathj07)
|
|
||||||
* [Matt Sanford](https://github.com/mzsanford)
|
|
||||||
* [Simon ccl1115](https://github.com/ccl1115)
|
|
58
vendor/github.com/asaskevich/govalidator/arrays.go
generated
vendored
58
vendor/github.com/asaskevich/govalidator/arrays.go
generated
vendored
|
@ -1,58 +0,0 @@
|
||||||
package govalidator
|
|
||||||
|
|
||||||
// Iterator is the function that accepts element of slice/array and its index
|
|
||||||
type Iterator func(interface{}, int)
|
|
||||||
|
|
||||||
// ResultIterator is the function that accepts element of slice/array and its index and returns any result
|
|
||||||
type ResultIterator func(interface{}, int) interface{}
|
|
||||||
|
|
||||||
// ConditionIterator is the function that accepts element of slice/array and its index and returns boolean
|
|
||||||
type ConditionIterator func(interface{}, int) bool
|
|
||||||
|
|
||||||
// Each iterates over the slice and apply Iterator to every item
|
|
||||||
func Each(array []interface{}, iterator Iterator) {
|
|
||||||
for index, data := range array {
|
|
||||||
iterator(data, index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map iterates over the slice and apply ResultIterator to every item. Returns new slice as a result.
|
|
||||||
func Map(array []interface{}, iterator ResultIterator) []interface{} {
|
|
||||||
var result = make([]interface{}, len(array))
|
|
||||||
for index, data := range array {
|
|
||||||
result[index] = iterator(data, index)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find iterates over the slice and apply ConditionIterator to every item. Returns first item that meet ConditionIterator or nil otherwise.
|
|
||||||
func Find(array []interface{}, iterator ConditionIterator) interface{} {
|
|
||||||
for index, data := range array {
|
|
||||||
if iterator(data, index) {
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter iterates over the slice and apply ConditionIterator to every item. Returns new slice.
|
|
||||||
func Filter(array []interface{}, iterator ConditionIterator) []interface{} {
|
|
||||||
var result = make([]interface{}, 0)
|
|
||||||
for index, data := range array {
|
|
||||||
if iterator(data, index) {
|
|
||||||
result = append(result, data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count iterates over the slice and apply ConditionIterator to every item. Returns count of items that meets ConditionIterator.
|
|
||||||
func Count(array []interface{}, iterator ConditionIterator) int {
|
|
||||||
count := 0
|
|
||||||
for index, data := range array {
|
|
||||||
if iterator(data, index) {
|
|
||||||
count = count + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count
|
|
||||||
}
|
|
49
vendor/github.com/asaskevich/govalidator/converter.go
generated
vendored
49
vendor/github.com/asaskevich/govalidator/converter.go
generated
vendored
|
@ -1,49 +0,0 @@
|
||||||
package govalidator
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ToString convert the input to a string.
|
|
||||||
func ToString(obj interface{}) string {
|
|
||||||
res := fmt.Sprintf("%v", obj)
|
|
||||||
return string(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToJSON convert the input to a valid JSON string
|
|
||||||
func ToJSON(obj interface{}) (string, error) {
|
|
||||||
res, err := json.Marshal(obj)
|
|
||||||
if err != nil {
|
|
||||||
res = []byte("")
|
|
||||||
}
|
|
||||||
return string(res), err
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToFloat convert the input string to a float, or 0.0 if the input is not a float.
|
|
||||||
func ToFloat(str string) (float64, error) {
|
|
||||||
res, err := strconv.ParseFloat(str, 64)
|
|
||||||
if err != nil {
|
|
||||||
res = 0.0
|
|
||||||
}
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToInt convert the input string to an integer, or 0 if the input is not an integer.
|
|
||||||
func ToInt(str string) (int64, error) {
|
|
||||||
res, err := strconv.ParseInt(str, 0, 64)
|
|
||||||
if err != nil {
|
|
||||||
res = 0
|
|
||||||
}
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToBoolean convert the input string to a boolean.
|
|
||||||
func ToBoolean(str string) (bool, error) {
|
|
||||||
res, err := strconv.ParseBool(str)
|
|
||||||
if err != nil {
|
|
||||||
res = false
|
|
||||||
}
|
|
||||||
return res, err
|
|
||||||
}
|
|
31
vendor/github.com/asaskevich/govalidator/error.go
generated
vendored
31
vendor/github.com/asaskevich/govalidator/error.go
generated
vendored
|
@ -1,31 +0,0 @@
|
||||||
package govalidator
|
|
||||||
|
|
||||||
// Errors is an array of multiple errors and conforms to the error interface.
|
|
||||||
type Errors []error
|
|
||||||
|
|
||||||
// Errors returns itself.
|
|
||||||
func (es Errors) Errors() []error {
|
|
||||||
return es
|
|
||||||
}
|
|
||||||
|
|
||||||
func (es Errors) Error() string {
|
|
||||||
var err string
|
|
||||||
for _, e := range es {
|
|
||||||
err += e.Error() + ";"
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error encapsulates a name, an error and whether there's a custom error message or not.
|
|
||||||
type Error struct {
|
|
||||||
Name string
|
|
||||||
Err error
|
|
||||||
CustomErrorMessageExists bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e Error) Error() string {
|
|
||||||
if e.CustomErrorMessageExists {
|
|
||||||
return e.Err.Error()
|
|
||||||
}
|
|
||||||
return e.Name + ": " + e.Err.Error()
|
|
||||||
}
|
|
57
vendor/github.com/asaskevich/govalidator/numerics.go
generated
vendored
57
vendor/github.com/asaskevich/govalidator/numerics.go
generated
vendored
|
@ -1,57 +0,0 @@
|
||||||
package govalidator
|
|
||||||
|
|
||||||
import "math"
|
|
||||||
|
|
||||||
// Abs returns absolute value of number
|
|
||||||
func Abs(value float64) float64 {
|
|
||||||
return value * Sign(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sign returns signum of number: 1 in case of value > 0, -1 in case of value < 0, 0 otherwise
|
|
||||||
func Sign(value float64) float64 {
|
|
||||||
if value > 0 {
|
|
||||||
return 1
|
|
||||||
} else if value < 0 {
|
|
||||||
return -1
|
|
||||||
} else {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNegative returns true if value < 0
|
|
||||||
func IsNegative(value float64) bool {
|
|
||||||
return value < 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsPositive returns true if value > 0
|
|
||||||
func IsPositive(value float64) bool {
|
|
||||||
return value > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNonNegative returns true if value >= 0
|
|
||||||
func IsNonNegative(value float64) bool {
|
|
||||||
return value >= 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNonPositive returns true if value <= 0
|
|
||||||
func IsNonPositive(value float64) bool {
|
|
||||||
return value <= 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// InRange returns true if value lies between left and right border
|
|
||||||
func InRange(value, left, right float64) bool {
|
|
||||||
if left > right {
|
|
||||||
left, right = right, left
|
|
||||||
}
|
|
||||||
return value >= left && value <= right
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsWhole returns true if value is whole number
|
|
||||||
func IsWhole(value float64) bool {
|
|
||||||
return Abs(math.Remainder(value, 1)) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNatural returns true if value is natural number (positive and whole)
|
|
||||||
func IsNatural(value float64) bool {
|
|
||||||
return IsWhole(value) && IsPositive(value)
|
|
||||||
}
|
|
91
vendor/github.com/asaskevich/govalidator/patterns.go
generated
vendored
91
vendor/github.com/asaskevich/govalidator/patterns.go
generated
vendored
|
@ -1,91 +0,0 @@
|
||||||
package govalidator
|
|
||||||
|
|
||||||
import "regexp"
|
|
||||||
|
|
||||||
// Basic regular expressions for validating strings
|
|
||||||
const (
|
|
||||||
Email string = "^(((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$"
|
|
||||||
CreditCard string = "^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11})$"
|
|
||||||
ISBN10 string = "^(?:[0-9]{9}X|[0-9]{10})$"
|
|
||||||
ISBN13 string = "^(?:[0-9]{13})$"
|
|
||||||
UUID3 string = "^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
|
||||||
UUID4 string = "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
|
||||||
UUID5 string = "^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
|
||||||
UUID string = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
|
||||||
Alpha string = "^[a-zA-Z]+$"
|
|
||||||
Alphanumeric string = "^[a-zA-Z0-9]+$"
|
|
||||||
Numeric string = "^[0-9]+$"
|
|
||||||
Int string = "^(?:[-+]?(?:0|[1-9][0-9]*))$"
|
|
||||||
Float string = "^(?:[-+]?(?:[0-9]+))?(?:\\.[0-9]*)?(?:[eE][\\+\\-]?(?:[0-9]+))?$"
|
|
||||||
Hexadecimal string = "^[0-9a-fA-F]+$"
|
|
||||||
Hexcolor string = "^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"
|
|
||||||
RGBcolor string = "^rgb\\(\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*\\)$"
|
|
||||||
ASCII string = "^[\x00-\x7F]+$"
|
|
||||||
Multibyte string = "[^\x00-\x7F]"
|
|
||||||
FullWidth string = "[^\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]"
|
|
||||||
HalfWidth string = "[\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]"
|
|
||||||
Base64 string = "^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$"
|
|
||||||
PrintableASCII string = "^[\x20-\x7E]+$"
|
|
||||||
DataURI string = "^data:.+\\/(.+);base64$"
|
|
||||||
Latitude string = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$"
|
|
||||||
Longitude string = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$"
|
|
||||||
DNSName string = `^([a-zA-Z0-9]{1}[a-zA-Z0-9_-]{0,62}){1}(\.[a-zA-Z0-9]{1}[a-zA-Z0-9_-]{0,62})*$`
|
|
||||||
IP string = `(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))`
|
|
||||||
URLSchema string = `((ftp|tcp|udp|wss?|https?):\/\/)`
|
|
||||||
URLUsername string = `(\S+(:\S*)?@)`
|
|
||||||
Hostname string = ``
|
|
||||||
URLPath string = `((\/|\?|#)[^\s]*)`
|
|
||||||
URLPort string = `(:(\d{1,5}))`
|
|
||||||
URLIP string = `([1-9]\d?|1\d\d|2[01]\d|22[0-3])(\.(1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))`
|
|
||||||
URLSubdomain string = `((www\.)|([a-zA-Z0-9]([-\.][-\._a-zA-Z0-9]+)*))`
|
|
||||||
URL string = `^` + URLSchema + `?` + URLUsername + `?` + `((` + URLIP + `|(\[` + IP + `\])|(([a-zA-Z0-9]([a-zA-Z0-9-_]+)?[a-zA-Z0-9]([-\.][a-zA-Z0-9]+)*)|(` + URLSubdomain + `?))?(([a-zA-Z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-zA-Z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-zA-Z\x{00a1}-\x{ffff}]{1,}))?))\.?` + URLPort + `?` + URLPath + `?$`
|
|
||||||
SSN string = `^\d{3}[- ]?\d{2}[- ]?\d{4}$`
|
|
||||||
WinPath string = `^[a-zA-Z]:\\(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*$`
|
|
||||||
UnixPath string = `^(/[^/\x00]*)+/?$`
|
|
||||||
Semver string = "^v?(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(-(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(\\.(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\\+[0-9a-zA-Z-]+(\\.[0-9a-zA-Z-]+)*)?$"
|
|
||||||
tagName string = "valid"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Used by IsFilePath func
|
|
||||||
const (
|
|
||||||
// Unknown is unresolved OS type
|
|
||||||
Unknown = iota
|
|
||||||
// Win is Windows type
|
|
||||||
Win
|
|
||||||
// Unix is *nix OS types
|
|
||||||
Unix
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
rxEmail = regexp.MustCompile(Email)
|
|
||||||
rxCreditCard = regexp.MustCompile(CreditCard)
|
|
||||||
rxISBN10 = regexp.MustCompile(ISBN10)
|
|
||||||
rxISBN13 = regexp.MustCompile(ISBN13)
|
|
||||||
rxUUID3 = regexp.MustCompile(UUID3)
|
|
||||||
rxUUID4 = regexp.MustCompile(UUID4)
|
|
||||||
rxUUID5 = regexp.MustCompile(UUID5)
|
|
||||||
rxUUID = regexp.MustCompile(UUID)
|
|
||||||
rxAlpha = regexp.MustCompile(Alpha)
|
|
||||||
rxAlphanumeric = regexp.MustCompile(Alphanumeric)
|
|
||||||
rxNumeric = regexp.MustCompile(Numeric)
|
|
||||||
rxInt = regexp.MustCompile(Int)
|
|
||||||
rxFloat = regexp.MustCompile(Float)
|
|
||||||
rxHexadecimal = regexp.MustCompile(Hexadecimal)
|
|
||||||
rxHexcolor = regexp.MustCompile(Hexcolor)
|
|
||||||
rxRGBcolor = regexp.MustCompile(RGBcolor)
|
|
||||||
rxASCII = regexp.MustCompile(ASCII)
|
|
||||||
rxPrintableASCII = regexp.MustCompile(PrintableASCII)
|
|
||||||
rxMultibyte = regexp.MustCompile(Multibyte)
|
|
||||||
rxFullWidth = regexp.MustCompile(FullWidth)
|
|
||||||
rxHalfWidth = regexp.MustCompile(HalfWidth)
|
|
||||||
rxBase64 = regexp.MustCompile(Base64)
|
|
||||||
rxDataURI = regexp.MustCompile(DataURI)
|
|
||||||
rxLatitude = regexp.MustCompile(Latitude)
|
|
||||||
rxLongitude = regexp.MustCompile(Longitude)
|
|
||||||
rxDNSName = regexp.MustCompile(DNSName)
|
|
||||||
rxURL = regexp.MustCompile(URL)
|
|
||||||
rxSSN = regexp.MustCompile(SSN)
|
|
||||||
rxWinPath = regexp.MustCompile(WinPath)
|
|
||||||
rxUnixPath = regexp.MustCompile(UnixPath)
|
|
||||||
rxSemver = regexp.MustCompile(Semver)
|
|
||||||
)
|
|
418
vendor/github.com/asaskevich/govalidator/types.go
generated
vendored
418
vendor/github.com/asaskevich/govalidator/types.go
generated
vendored
|
@ -1,418 +0,0 @@
|
||||||
package govalidator
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"regexp"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Validator is a wrapper for a validator function that returns bool and accepts string.
|
|
||||||
type Validator func(str string) bool
|
|
||||||
|
|
||||||
// CustomTypeValidator is a wrapper for validator functions that returns bool and accepts any type.
|
|
||||||
// The second parameter should be the context (in the case of validating a struct: the whole object being validated).
|
|
||||||
type CustomTypeValidator func(i interface{}, o interface{}) bool
|
|
||||||
|
|
||||||
// ParamValidator is a wrapper for validator functions that accepts additional parameters.
|
|
||||||
type ParamValidator func(str string, params ...string) bool
|
|
||||||
type tagOptionsMap map[string]string
|
|
||||||
|
|
||||||
// UnsupportedTypeError is a wrapper for reflect.Type
|
|
||||||
type UnsupportedTypeError struct {
|
|
||||||
Type reflect.Type
|
|
||||||
}
|
|
||||||
|
|
||||||
// stringValues is a slice of reflect.Value holding *reflect.StringValue.
|
|
||||||
// It implements the methods to sort by string.
|
|
||||||
type stringValues []reflect.Value
|
|
||||||
|
|
||||||
// ParamTagMap is a map of functions accept variants parameters
|
|
||||||
var ParamTagMap = map[string]ParamValidator{
|
|
||||||
"length": ByteLength,
|
|
||||||
"range": Range,
|
|
||||||
"runelength": RuneLength,
|
|
||||||
"stringlength": StringLength,
|
|
||||||
"matches": StringMatches,
|
|
||||||
"in": isInRaw,
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParamTagRegexMap maps param tags to their respective regexes.
|
|
||||||
var ParamTagRegexMap = map[string]*regexp.Regexp{
|
|
||||||
"range": regexp.MustCompile("^range\\((\\d+)\\|(\\d+)\\)$"),
|
|
||||||
"length": regexp.MustCompile("^length\\((\\d+)\\|(\\d+)\\)$"),
|
|
||||||
"runelength": regexp.MustCompile("^runelength\\((\\d+)\\|(\\d+)\\)$"),
|
|
||||||
"stringlength": regexp.MustCompile("^stringlength\\((\\d+)\\|(\\d+)\\)$"),
|
|
||||||
"in": regexp.MustCompile(`^in\((.*)\)`),
|
|
||||||
"matches": regexp.MustCompile(`^matches\((.+)\)$`),
|
|
||||||
}
|
|
||||||
|
|
||||||
type customTypeTagMap struct {
|
|
||||||
validators map[string]CustomTypeValidator
|
|
||||||
|
|
||||||
sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tm *customTypeTagMap) Get(name string) (CustomTypeValidator, bool) {
|
|
||||||
tm.RLock()
|
|
||||||
defer tm.RUnlock()
|
|
||||||
v, ok := tm.validators[name]
|
|
||||||
return v, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tm *customTypeTagMap) Set(name string, ctv CustomTypeValidator) {
|
|
||||||
tm.Lock()
|
|
||||||
defer tm.Unlock()
|
|
||||||
tm.validators[name] = ctv
|
|
||||||
}
|
|
||||||
|
|
||||||
// CustomTypeTagMap is a map of functions that can be used as tags for ValidateStruct function.
|
|
||||||
// Use this to validate compound or custom types that need to be handled as a whole, e.g.
|
|
||||||
// `type UUID [16]byte` (this would be handled as an array of bytes).
|
|
||||||
var CustomTypeTagMap = &customTypeTagMap{validators: make(map[string]CustomTypeValidator)}
|
|
||||||
|
|
||||||
// TagMap is a map of functions, that can be used as tags for ValidateStruct function.
|
|
||||||
var TagMap = map[string]Validator{
|
|
||||||
"email": IsEmail,
|
|
||||||
"url": IsURL,
|
|
||||||
"dialstring": IsDialString,
|
|
||||||
"requrl": IsRequestURL,
|
|
||||||
"requri": IsRequestURI,
|
|
||||||
"alpha": IsAlpha,
|
|
||||||
"utfletter": IsUTFLetter,
|
|
||||||
"alphanum": IsAlphanumeric,
|
|
||||||
"utfletternum": IsUTFLetterNumeric,
|
|
||||||
"numeric": IsNumeric,
|
|
||||||
"utfnumeric": IsUTFNumeric,
|
|
||||||
"utfdigit": IsUTFDigit,
|
|
||||||
"hexadecimal": IsHexadecimal,
|
|
||||||
"hexcolor": IsHexcolor,
|
|
||||||
"rgbcolor": IsRGBcolor,
|
|
||||||
"lowercase": IsLowerCase,
|
|
||||||
"uppercase": IsUpperCase,
|
|
||||||
"int": IsInt,
|
|
||||||
"float": IsFloat,
|
|
||||||
"null": IsNull,
|
|
||||||
"uuid": IsUUID,
|
|
||||||
"uuidv3": IsUUIDv3,
|
|
||||||
"uuidv4": IsUUIDv4,
|
|
||||||
"uuidv5": IsUUIDv5,
|
|
||||||
"creditcard": IsCreditCard,
|
|
||||||
"isbn10": IsISBN10,
|
|
||||||
"isbn13": IsISBN13,
|
|
||||||
"json": IsJSON,
|
|
||||||
"multibyte": IsMultibyte,
|
|
||||||
"ascii": IsASCII,
|
|
||||||
"printableascii": IsPrintableASCII,
|
|
||||||
"fullwidth": IsFullWidth,
|
|
||||||
"halfwidth": IsHalfWidth,
|
|
||||||
"variablewidth": IsVariableWidth,
|
|
||||||
"base64": IsBase64,
|
|
||||||
"datauri": IsDataURI,
|
|
||||||
"ip": IsIP,
|
|
||||||
"port": IsPort,
|
|
||||||
"ipv4": IsIPv4,
|
|
||||||
"ipv6": IsIPv6,
|
|
||||||
"dns": IsDNSName,
|
|
||||||
"host": IsHost,
|
|
||||||
"mac": IsMAC,
|
|
||||||
"latitude": IsLatitude,
|
|
||||||
"longitude": IsLongitude,
|
|
||||||
"ssn": IsSSN,
|
|
||||||
"semver": IsSemver,
|
|
||||||
"rfc3339": IsRFC3339,
|
|
||||||
"ISO3166Alpha2": IsISO3166Alpha2,
|
|
||||||
"ISO3166Alpha3": IsISO3166Alpha3,
|
|
||||||
"ISO4217": IsISO4217,
|
|
||||||
}
|
|
||||||
|
|
||||||
// ISO3166Entry stores country codes
|
|
||||||
type ISO3166Entry struct {
|
|
||||||
EnglishShortName string
|
|
||||||
FrenchShortName string
|
|
||||||
Alpha2Code string
|
|
||||||
Alpha3Code string
|
|
||||||
Numeric string
|
|
||||||
}
|
|
||||||
|
|
||||||
//ISO3166List based on https://www.iso.org/obp/ui/#search/code/ Code Type "Officially Assigned Codes"
|
|
||||||
var ISO3166List = []ISO3166Entry{
|
|
||||||
{"Afghanistan", "Afghanistan (l')", "AF", "AFG", "004"},
|
|
||||||
{"Albania", "Albanie (l')", "AL", "ALB", "008"},
|
|
||||||
{"Antarctica", "Antarctique (l')", "AQ", "ATA", "010"},
|
|
||||||
{"Algeria", "Algérie (l')", "DZ", "DZA", "012"},
|
|
||||||
{"American Samoa", "Samoa américaines (les)", "AS", "ASM", "016"},
|
|
||||||
{"Andorra", "Andorre (l')", "AD", "AND", "020"},
|
|
||||||
{"Angola", "Angola (l')", "AO", "AGO", "024"},
|
|
||||||
{"Antigua and Barbuda", "Antigua-et-Barbuda", "AG", "ATG", "028"},
|
|
||||||
{"Azerbaijan", "Azerbaïdjan (l')", "AZ", "AZE", "031"},
|
|
||||||
{"Argentina", "Argentine (l')", "AR", "ARG", "032"},
|
|
||||||
{"Australia", "Australie (l')", "AU", "AUS", "036"},
|
|
||||||
{"Austria", "Autriche (l')", "AT", "AUT", "040"},
|
|
||||||
{"Bahamas (the)", "Bahamas (les)", "BS", "BHS", "044"},
|
|
||||||
{"Bahrain", "Bahreïn", "BH", "BHR", "048"},
|
|
||||||
{"Bangladesh", "Bangladesh (le)", "BD", "BGD", "050"},
|
|
||||||
{"Armenia", "Arménie (l')", "AM", "ARM", "051"},
|
|
||||||
{"Barbados", "Barbade (la)", "BB", "BRB", "052"},
|
|
||||||
{"Belgium", "Belgique (la)", "BE", "BEL", "056"},
|
|
||||||
{"Bermuda", "Bermudes (les)", "BM", "BMU", "060"},
|
|
||||||
{"Bhutan", "Bhoutan (le)", "BT", "BTN", "064"},
|
|
||||||
{"Bolivia (Plurinational State of)", "Bolivie (État plurinational de)", "BO", "BOL", "068"},
|
|
||||||
{"Bosnia and Herzegovina", "Bosnie-Herzégovine (la)", "BA", "BIH", "070"},
|
|
||||||
{"Botswana", "Botswana (le)", "BW", "BWA", "072"},
|
|
||||||
{"Bouvet Island", "Bouvet (l'Île)", "BV", "BVT", "074"},
|
|
||||||
{"Brazil", "Brésil (le)", "BR", "BRA", "076"},
|
|
||||||
{"Belize", "Belize (le)", "BZ", "BLZ", "084"},
|
|
||||||
{"British Indian Ocean Territory (the)", "Indien (le Territoire britannique de l'océan)", "IO", "IOT", "086"},
|
|
||||||
{"Solomon Islands", "Salomon (Îles)", "SB", "SLB", "090"},
|
|
||||||
{"Virgin Islands (British)", "Vierges britanniques (les Îles)", "VG", "VGB", "092"},
|
|
||||||
{"Brunei Darussalam", "Brunéi Darussalam (le)", "BN", "BRN", "096"},
|
|
||||||
{"Bulgaria", "Bulgarie (la)", "BG", "BGR", "100"},
|
|
||||||
{"Myanmar", "Myanmar (le)", "MM", "MMR", "104"},
|
|
||||||
{"Burundi", "Burundi (le)", "BI", "BDI", "108"},
|
|
||||||
{"Belarus", "Bélarus (le)", "BY", "BLR", "112"},
|
|
||||||
{"Cambodia", "Cambodge (le)", "KH", "KHM", "116"},
|
|
||||||
{"Cameroon", "Cameroun (le)", "CM", "CMR", "120"},
|
|
||||||
{"Canada", "Canada (le)", "CA", "CAN", "124"},
|
|
||||||
{"Cabo Verde", "Cabo Verde", "CV", "CPV", "132"},
|
|
||||||
{"Cayman Islands (the)", "Caïmans (les Îles)", "KY", "CYM", "136"},
|
|
||||||
{"Central African Republic (the)", "République centrafricaine (la)", "CF", "CAF", "140"},
|
|
||||||
{"Sri Lanka", "Sri Lanka", "LK", "LKA", "144"},
|
|
||||||
{"Chad", "Tchad (le)", "TD", "TCD", "148"},
|
|
||||||
{"Chile", "Chili (le)", "CL", "CHL", "152"},
|
|
||||||
{"China", "Chine (la)", "CN", "CHN", "156"},
|
|
||||||
{"Taiwan (Province of China)", "Taïwan (Province de Chine)", "TW", "TWN", "158"},
|
|
||||||
{"Christmas Island", "Christmas (l'Île)", "CX", "CXR", "162"},
|
|
||||||
{"Cocos (Keeling) Islands (the)", "Cocos (les Îles)/ Keeling (les Îles)", "CC", "CCK", "166"},
|
|
||||||
{"Colombia", "Colombie (la)", "CO", "COL", "170"},
|
|
||||||
{"Comoros (the)", "Comores (les)", "KM", "COM", "174"},
|
|
||||||
{"Mayotte", "Mayotte", "YT", "MYT", "175"},
|
|
||||||
{"Congo (the)", "Congo (le)", "CG", "COG", "178"},
|
|
||||||
{"Congo (the Democratic Republic of the)", "Congo (la République démocratique du)", "CD", "COD", "180"},
|
|
||||||
{"Cook Islands (the)", "Cook (les Îles)", "CK", "COK", "184"},
|
|
||||||
{"Costa Rica", "Costa Rica (le)", "CR", "CRI", "188"},
|
|
||||||
{"Croatia", "Croatie (la)", "HR", "HRV", "191"},
|
|
||||||
{"Cuba", "Cuba", "CU", "CUB", "192"},
|
|
||||||
{"Cyprus", "Chypre", "CY", "CYP", "196"},
|
|
||||||
{"Czech Republic (the)", "tchèque (la République)", "CZ", "CZE", "203"},
|
|
||||||
{"Benin", "Bénin (le)", "BJ", "BEN", "204"},
|
|
||||||
{"Denmark", "Danemark (le)", "DK", "DNK", "208"},
|
|
||||||
{"Dominica", "Dominique (la)", "DM", "DMA", "212"},
|
|
||||||
{"Dominican Republic (the)", "dominicaine (la République)", "DO", "DOM", "214"},
|
|
||||||
{"Ecuador", "Équateur (l')", "EC", "ECU", "218"},
|
|
||||||
{"El Salvador", "El Salvador", "SV", "SLV", "222"},
|
|
||||||
{"Equatorial Guinea", "Guinée équatoriale (la)", "GQ", "GNQ", "226"},
|
|
||||||
{"Ethiopia", "Éthiopie (l')", "ET", "ETH", "231"},
|
|
||||||
{"Eritrea", "Érythrée (l')", "ER", "ERI", "232"},
|
|
||||||
{"Estonia", "Estonie (l')", "EE", "EST", "233"},
|
|
||||||
{"Faroe Islands (the)", "Féroé (les Îles)", "FO", "FRO", "234"},
|
|
||||||
{"Falkland Islands (the) [Malvinas]", "Falkland (les Îles)/Malouines (les Îles)", "FK", "FLK", "238"},
|
|
||||||
{"South Georgia and the South Sandwich Islands", "Géorgie du Sud-et-les Îles Sandwich du Sud (la)", "GS", "SGS", "239"},
|
|
||||||
{"Fiji", "Fidji (les)", "FJ", "FJI", "242"},
|
|
||||||
{"Finland", "Finlande (la)", "FI", "FIN", "246"},
|
|
||||||
{"Åland Islands", "Åland(les Îles)", "AX", "ALA", "248"},
|
|
||||||
{"France", "France (la)", "FR", "FRA", "250"},
|
|
||||||
{"French Guiana", "Guyane française (la )", "GF", "GUF", "254"},
|
|
||||||
{"French Polynesia", "Polynésie française (la)", "PF", "PYF", "258"},
|
|
||||||
{"French Southern Territories (the)", "Terres australes françaises (les)", "TF", "ATF", "260"},
|
|
||||||
{"Djibouti", "Djibouti", "DJ", "DJI", "262"},
|
|
||||||
{"Gabon", "Gabon (le)", "GA", "GAB", "266"},
|
|
||||||
{"Georgia", "Géorgie (la)", "GE", "GEO", "268"},
|
|
||||||
{"Gambia (the)", "Gambie (la)", "GM", "GMB", "270"},
|
|
||||||
{"Palestine, State of", "Palestine, État de", "PS", "PSE", "275"},
|
|
||||||
{"Germany", "Allemagne (l')", "DE", "DEU", "276"},
|
|
||||||
{"Ghana", "Ghana (le)", "GH", "GHA", "288"},
|
|
||||||
{"Gibraltar", "Gibraltar", "GI", "GIB", "292"},
|
|
||||||
{"Kiribati", "Kiribati", "KI", "KIR", "296"},
|
|
||||||
{"Greece", "Grèce (la)", "GR", "GRC", "300"},
|
|
||||||
{"Greenland", "Groenland (le)", "GL", "GRL", "304"},
|
|
||||||
{"Grenada", "Grenade (la)", "GD", "GRD", "308"},
|
|
||||||
{"Guadeloupe", "Guadeloupe (la)", "GP", "GLP", "312"},
|
|
||||||
{"Guam", "Guam", "GU", "GUM", "316"},
|
|
||||||
{"Guatemala", "Guatemala (le)", "GT", "GTM", "320"},
|
|
||||||
{"Guinea", "Guinée (la)", "GN", "GIN", "324"},
|
|
||||||
{"Guyana", "Guyana (le)", "GY", "GUY", "328"},
|
|
||||||
{"Haiti", "Haïti", "HT", "HTI", "332"},
|
|
||||||
{"Heard Island and McDonald Islands", "Heard-et-Îles MacDonald (l'Île)", "HM", "HMD", "334"},
|
|
||||||
{"Holy See (the)", "Saint-Siège (le)", "VA", "VAT", "336"},
|
|
||||||
{"Honduras", "Honduras (le)", "HN", "HND", "340"},
|
|
||||||
{"Hong Kong", "Hong Kong", "HK", "HKG", "344"},
|
|
||||||
{"Hungary", "Hongrie (la)", "HU", "HUN", "348"},
|
|
||||||
{"Iceland", "Islande (l')", "IS", "ISL", "352"},
|
|
||||||
{"India", "Inde (l')", "IN", "IND", "356"},
|
|
||||||
{"Indonesia", "Indonésie (l')", "ID", "IDN", "360"},
|
|
||||||
{"Iran (Islamic Republic of)", "Iran (République Islamique d')", "IR", "IRN", "364"},
|
|
||||||
{"Iraq", "Iraq (l')", "IQ", "IRQ", "368"},
|
|
||||||
{"Ireland", "Irlande (l')", "IE", "IRL", "372"},
|
|
||||||
{"Israel", "Israël", "IL", "ISR", "376"},
|
|
||||||
{"Italy", "Italie (l')", "IT", "ITA", "380"},
|
|
||||||
{"Côte d'Ivoire", "Côte d'Ivoire (la)", "CI", "CIV", "384"},
|
|
||||||
{"Jamaica", "Jamaïque (la)", "JM", "JAM", "388"},
|
|
||||||
{"Japan", "Japon (le)", "JP", "JPN", "392"},
|
|
||||||
{"Kazakhstan", "Kazakhstan (le)", "KZ", "KAZ", "398"},
|
|
||||||
{"Jordan", "Jordanie (la)", "JO", "JOR", "400"},
|
|
||||||
{"Kenya", "Kenya (le)", "KE", "KEN", "404"},
|
|
||||||
{"Korea (the Democratic People's Republic of)", "Corée (la République populaire démocratique de)", "KP", "PRK", "408"},
|
|
||||||
{"Korea (the Republic of)", "Corée (la République de)", "KR", "KOR", "410"},
|
|
||||||
{"Kuwait", "Koweït (le)", "KW", "KWT", "414"},
|
|
||||||
{"Kyrgyzstan", "Kirghizistan (le)", "KG", "KGZ", "417"},
|
|
||||||
{"Lao People's Democratic Republic (the)", "Lao, République démocratique populaire", "LA", "LAO", "418"},
|
|
||||||
{"Lebanon", "Liban (le)", "LB", "LBN", "422"},
|
|
||||||
{"Lesotho", "Lesotho (le)", "LS", "LSO", "426"},
|
|
||||||
{"Latvia", "Lettonie (la)", "LV", "LVA", "428"},
|
|
||||||
{"Liberia", "Libéria (le)", "LR", "LBR", "430"},
|
|
||||||
{"Libya", "Libye (la)", "LY", "LBY", "434"},
|
|
||||||
{"Liechtenstein", "Liechtenstein (le)", "LI", "LIE", "438"},
|
|
||||||
{"Lithuania", "Lituanie (la)", "LT", "LTU", "440"},
|
|
||||||
{"Luxembourg", "Luxembourg (le)", "LU", "LUX", "442"},
|
|
||||||
{"Macao", "Macao", "MO", "MAC", "446"},
|
|
||||||
{"Madagascar", "Madagascar", "MG", "MDG", "450"},
|
|
||||||
{"Malawi", "Malawi (le)", "MW", "MWI", "454"},
|
|
||||||
{"Malaysia", "Malaisie (la)", "MY", "MYS", "458"},
|
|
||||||
{"Maldives", "Maldives (les)", "MV", "MDV", "462"},
|
|
||||||
{"Mali", "Mali (le)", "ML", "MLI", "466"},
|
|
||||||
{"Malta", "Malte", "MT", "MLT", "470"},
|
|
||||||
{"Martinique", "Martinique (la)", "MQ", "MTQ", "474"},
|
|
||||||
{"Mauritania", "Mauritanie (la)", "MR", "MRT", "478"},
|
|
||||||
{"Mauritius", "Maurice", "MU", "MUS", "480"},
|
|
||||||
{"Mexico", "Mexique (le)", "MX", "MEX", "484"},
|
|
||||||
{"Monaco", "Monaco", "MC", "MCO", "492"},
|
|
||||||
{"Mongolia", "Mongolie (la)", "MN", "MNG", "496"},
|
|
||||||
{"Moldova (the Republic of)", "Moldova , République de", "MD", "MDA", "498"},
|
|
||||||
{"Montenegro", "Monténégro (le)", "ME", "MNE", "499"},
|
|
||||||
{"Montserrat", "Montserrat", "MS", "MSR", "500"},
|
|
||||||
{"Morocco", "Maroc (le)", "MA", "MAR", "504"},
|
|
||||||
{"Mozambique", "Mozambique (le)", "MZ", "MOZ", "508"},
|
|
||||||
{"Oman", "Oman", "OM", "OMN", "512"},
|
|
||||||
{"Namibia", "Namibie (la)", "NA", "NAM", "516"},
|
|
||||||
{"Nauru", "Nauru", "NR", "NRU", "520"},
|
|
||||||
{"Nepal", "Népal (le)", "NP", "NPL", "524"},
|
|
||||||
{"Netherlands (the)", "Pays-Bas (les)", "NL", "NLD", "528"},
|
|
||||||
{"Curaçao", "Curaçao", "CW", "CUW", "531"},
|
|
||||||
{"Aruba", "Aruba", "AW", "ABW", "533"},
|
|
||||||
{"Sint Maarten (Dutch part)", "Saint-Martin (partie néerlandaise)", "SX", "SXM", "534"},
|
|
||||||
{"Bonaire, Sint Eustatius and Saba", "Bonaire, Saint-Eustache et Saba", "BQ", "BES", "535"},
|
|
||||||
{"New Caledonia", "Nouvelle-Calédonie (la)", "NC", "NCL", "540"},
|
|
||||||
{"Vanuatu", "Vanuatu (le)", "VU", "VUT", "548"},
|
|
||||||
{"New Zealand", "Nouvelle-Zélande (la)", "NZ", "NZL", "554"},
|
|
||||||
{"Nicaragua", "Nicaragua (le)", "NI", "NIC", "558"},
|
|
||||||
{"Niger (the)", "Niger (le)", "NE", "NER", "562"},
|
|
||||||
{"Nigeria", "Nigéria (le)", "NG", "NGA", "566"},
|
|
||||||
{"Niue", "Niue", "NU", "NIU", "570"},
|
|
||||||
{"Norfolk Island", "Norfolk (l'Île)", "NF", "NFK", "574"},
|
|
||||||
{"Norway", "Norvège (la)", "NO", "NOR", "578"},
|
|
||||||
{"Northern Mariana Islands (the)", "Mariannes du Nord (les Îles)", "MP", "MNP", "580"},
|
|
||||||
{"United States Minor Outlying Islands (the)", "Îles mineures éloignées des États-Unis (les)", "UM", "UMI", "581"},
|
|
||||||
{"Micronesia (Federated States of)", "Micronésie (États fédérés de)", "FM", "FSM", "583"},
|
|
||||||
{"Marshall Islands (the)", "Marshall (Îles)", "MH", "MHL", "584"},
|
|
||||||
{"Palau", "Palaos (les)", "PW", "PLW", "585"},
|
|
||||||
{"Pakistan", "Pakistan (le)", "PK", "PAK", "586"},
|
|
||||||
{"Panama", "Panama (le)", "PA", "PAN", "591"},
|
|
||||||
{"Papua New Guinea", "Papouasie-Nouvelle-Guinée (la)", "PG", "PNG", "598"},
|
|
||||||
{"Paraguay", "Paraguay (le)", "PY", "PRY", "600"},
|
|
||||||
{"Peru", "Pérou (le)", "PE", "PER", "604"},
|
|
||||||
{"Philippines (the)", "Philippines (les)", "PH", "PHL", "608"},
|
|
||||||
{"Pitcairn", "Pitcairn", "PN", "PCN", "612"},
|
|
||||||
{"Poland", "Pologne (la)", "PL", "POL", "616"},
|
|
||||||
{"Portugal", "Portugal (le)", "PT", "PRT", "620"},
|
|
||||||
{"Guinea-Bissau", "Guinée-Bissau (la)", "GW", "GNB", "624"},
|
|
||||||
{"Timor-Leste", "Timor-Leste (le)", "TL", "TLS", "626"},
|
|
||||||
{"Puerto Rico", "Porto Rico", "PR", "PRI", "630"},
|
|
||||||
{"Qatar", "Qatar (le)", "QA", "QAT", "634"},
|
|
||||||
{"Réunion", "Réunion (La)", "RE", "REU", "638"},
|
|
||||||
{"Romania", "Roumanie (la)", "RO", "ROU", "642"},
|
|
||||||
{"Russian Federation (the)", "Russie (la Fédération de)", "RU", "RUS", "643"},
|
|
||||||
{"Rwanda", "Rwanda (le)", "RW", "RWA", "646"},
|
|
||||||
{"Saint Barthélemy", "Saint-Barthélemy", "BL", "BLM", "652"},
|
|
||||||
{"Saint Helena, Ascension and Tristan da Cunha", "Sainte-Hélène, Ascension et Tristan da Cunha", "SH", "SHN", "654"},
|
|
||||||
{"Saint Kitts and Nevis", "Saint-Kitts-et-Nevis", "KN", "KNA", "659"},
|
|
||||||
{"Anguilla", "Anguilla", "AI", "AIA", "660"},
|
|
||||||
{"Saint Lucia", "Sainte-Lucie", "LC", "LCA", "662"},
|
|
||||||
{"Saint Martin (French part)", "Saint-Martin (partie française)", "MF", "MAF", "663"},
|
|
||||||
{"Saint Pierre and Miquelon", "Saint-Pierre-et-Miquelon", "PM", "SPM", "666"},
|
|
||||||
{"Saint Vincent and the Grenadines", "Saint-Vincent-et-les Grenadines", "VC", "VCT", "670"},
|
|
||||||
{"San Marino", "Saint-Marin", "SM", "SMR", "674"},
|
|
||||||
{"Sao Tome and Principe", "Sao Tomé-et-Principe", "ST", "STP", "678"},
|
|
||||||
{"Saudi Arabia", "Arabie saoudite (l')", "SA", "SAU", "682"},
|
|
||||||
{"Senegal", "Sénégal (le)", "SN", "SEN", "686"},
|
|
||||||
{"Serbia", "Serbie (la)", "RS", "SRB", "688"},
|
|
||||||
{"Seychelles", "Seychelles (les)", "SC", "SYC", "690"},
|
|
||||||
{"Sierra Leone", "Sierra Leone (la)", "SL", "SLE", "694"},
|
|
||||||
{"Singapore", "Singapour", "SG", "SGP", "702"},
|
|
||||||
{"Slovakia", "Slovaquie (la)", "SK", "SVK", "703"},
|
|
||||||
{"Viet Nam", "Viet Nam (le)", "VN", "VNM", "704"},
|
|
||||||
{"Slovenia", "Slovénie (la)", "SI", "SVN", "705"},
|
|
||||||
{"Somalia", "Somalie (la)", "SO", "SOM", "706"},
|
|
||||||
{"South Africa", "Afrique du Sud (l')", "ZA", "ZAF", "710"},
|
|
||||||
{"Zimbabwe", "Zimbabwe (le)", "ZW", "ZWE", "716"},
|
|
||||||
{"Spain", "Espagne (l')", "ES", "ESP", "724"},
|
|
||||||
{"South Sudan", "Soudan du Sud (le)", "SS", "SSD", "728"},
|
|
||||||
{"Sudan (the)", "Soudan (le)", "SD", "SDN", "729"},
|
|
||||||
{"Western Sahara*", "Sahara occidental (le)*", "EH", "ESH", "732"},
|
|
||||||
{"Suriname", "Suriname (le)", "SR", "SUR", "740"},
|
|
||||||
{"Svalbard and Jan Mayen", "Svalbard et l'Île Jan Mayen (le)", "SJ", "SJM", "744"},
|
|
||||||
{"Swaziland", "Swaziland (le)", "SZ", "SWZ", "748"},
|
|
||||||
{"Sweden", "Suède (la)", "SE", "SWE", "752"},
|
|
||||||
{"Switzerland", "Suisse (la)", "CH", "CHE", "756"},
|
|
||||||
{"Syrian Arab Republic", "République arabe syrienne (la)", "SY", "SYR", "760"},
|
|
||||||
{"Tajikistan", "Tadjikistan (le)", "TJ", "TJK", "762"},
|
|
||||||
{"Thailand", "Thaïlande (la)", "TH", "THA", "764"},
|
|
||||||
{"Togo", "Togo (le)", "TG", "TGO", "768"},
|
|
||||||
{"Tokelau", "Tokelau (les)", "TK", "TKL", "772"},
|
|
||||||
{"Tonga", "Tonga (les)", "TO", "TON", "776"},
|
|
||||||
{"Trinidad and Tobago", "Trinité-et-Tobago (la)", "TT", "TTO", "780"},
|
|
||||||
{"United Arab Emirates (the)", "Émirats arabes unis (les)", "AE", "ARE", "784"},
|
|
||||||
{"Tunisia", "Tunisie (la)", "TN", "TUN", "788"},
|
|
||||||
{"Turkey", "Turquie (la)", "TR", "TUR", "792"},
|
|
||||||
{"Turkmenistan", "Turkménistan (le)", "TM", "TKM", "795"},
|
|
||||||
{"Turks and Caicos Islands (the)", "Turks-et-Caïcos (les Îles)", "TC", "TCA", "796"},
|
|
||||||
{"Tuvalu", "Tuvalu (les)", "TV", "TUV", "798"},
|
|
||||||
{"Uganda", "Ouganda (l')", "UG", "UGA", "800"},
|
|
||||||
{"Ukraine", "Ukraine (l')", "UA", "UKR", "804"},
|
|
||||||
{"Macedonia (the former Yugoslav Republic of)", "Macédoine (l'ex‑République yougoslave de)", "MK", "MKD", "807"},
|
|
||||||
{"Egypt", "Égypte (l')", "EG", "EGY", "818"},
|
|
||||||
{"United Kingdom of Great Britain and Northern Ireland (the)", "Royaume-Uni de Grande-Bretagne et d'Irlande du Nord (le)", "GB", "GBR", "826"},
|
|
||||||
{"Guernsey", "Guernesey", "GG", "GGY", "831"},
|
|
||||||
{"Jersey", "Jersey", "JE", "JEY", "832"},
|
|
||||||
{"Isle of Man", "Île de Man", "IM", "IMN", "833"},
|
|
||||||
{"Tanzania, United Republic of", "Tanzanie, République-Unie de", "TZ", "TZA", "834"},
|
|
||||||
{"United States of America (the)", "États-Unis d'Amérique (les)", "US", "USA", "840"},
|
|
||||||
{"Virgin Islands (U.S.)", "Vierges des États-Unis (les Îles)", "VI", "VIR", "850"},
|
|
||||||
{"Burkina Faso", "Burkina Faso (le)", "BF", "BFA", "854"},
|
|
||||||
{"Uruguay", "Uruguay (l')", "UY", "URY", "858"},
|
|
||||||
{"Uzbekistan", "Ouzbékistan (l')", "UZ", "UZB", "860"},
|
|
||||||
{"Venezuela (Bolivarian Republic of)", "Venezuela (République bolivarienne du)", "VE", "VEN", "862"},
|
|
||||||
{"Wallis and Futuna", "Wallis-et-Futuna", "WF", "WLF", "876"},
|
|
||||||
{"Samoa", "Samoa (le)", "WS", "WSM", "882"},
|
|
||||||
{"Yemen", "Yémen (le)", "YE", "YEM", "887"},
|
|
||||||
{"Zambia", "Zambie (la)", "ZM", "ZMB", "894"},
|
|
||||||
}
|
|
||||||
|
|
||||||
// ISO4217List is the list of ISO currency codes
|
|
||||||
var ISO4217List = []string{
|
|
||||||
"AED", "AFN", "ALL", "AMD", "ANG", "AOA", "ARS", "AUD", "AWG", "AZN",
|
|
||||||
"BAM", "BBD", "BDT", "BGN", "BHD", "BIF", "BMD", "BND", "BOB", "BOV", "BRL", "BSD", "BTN", "BWP", "BYN", "BZD",
|
|
||||||
"CAD", "CDF", "CHE", "CHF", "CHW", "CLF", "CLP", "CNY", "COP", "COU", "CRC", "CUC", "CUP", "CVE", "CZK",
|
|
||||||
"DJF", "DKK", "DOP", "DZD",
|
|
||||||
"EGP", "ERN", "ETB", "EUR",
|
|
||||||
"FJD", "FKP",
|
|
||||||
"GBP", "GEL", "GHS", "GIP", "GMD", "GNF", "GTQ", "GYD",
|
|
||||||
"HKD", "HNL", "HRK", "HTG", "HUF",
|
|
||||||
"IDR", "ILS", "INR", "IQD", "IRR", "ISK",
|
|
||||||
"JMD", "JOD", "JPY",
|
|
||||||
"KES", "KGS", "KHR", "KMF", "KPW", "KRW", "KWD", "KYD", "KZT",
|
|
||||||
"LAK", "LBP", "LKR", "LRD", "LSL", "LYD",
|
|
||||||
"MAD", "MDL", "MGA", "MKD", "MMK", "MNT", "MOP", "MRO", "MUR", "MVR", "MWK", "MXN", "MXV", "MYR", "MZN",
|
|
||||||
"NAD", "NGN", "NIO", "NOK", "NPR", "NZD",
|
|
||||||
"OMR",
|
|
||||||
"PAB", "PEN", "PGK", "PHP", "PKR", "PLN", "PYG",
|
|
||||||
"QAR",
|
|
||||||
"RON", "RSD", "RUB", "RWF",
|
|
||||||
"SAR", "SBD", "SCR", "SDG", "SEK", "SGD", "SHP", "SLL", "SOS", "SRD", "SSP", "STD", "SVC", "SYP", "SZL",
|
|
||||||
"THB", "TJS", "TMT", "TND", "TOP", "TRY", "TTD", "TWD", "TZS",
|
|
||||||
"UAH", "UGX", "USD", "USN", "UYI", "UYU", "UZS",
|
|
||||||
"VEF", "VND", "VUV",
|
|
||||||
"WST",
|
|
||||||
"XAF", "XAG", "XAU", "XBA", "XBB", "XBC", "XBD", "XCD", "XDR", "XOF", "XPD", "XPF", "XPT", "XSU", "XTS", "XUA", "XXX",
|
|
||||||
"YER",
|
|
||||||
"ZAR", "ZMW", "ZWL",
|
|
||||||
}
|
|
268
vendor/github.com/asaskevich/govalidator/utils.go
generated
vendored
268
vendor/github.com/asaskevich/govalidator/utils.go
generated
vendored
|
@ -1,268 +0,0 @@
|
||||||
package govalidator
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"html"
|
|
||||||
"math"
|
|
||||||
"path"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
"unicode"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Contains check if the string contains the substring.
|
|
||||||
func Contains(str, substring string) bool {
|
|
||||||
return strings.Contains(str, substring)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Matches check if string matches the pattern (pattern is regular expression)
|
|
||||||
// In case of error return false
|
|
||||||
func Matches(str, pattern string) bool {
|
|
||||||
match, _ := regexp.MatchString(pattern, str)
|
|
||||||
return match
|
|
||||||
}
|
|
||||||
|
|
||||||
// LeftTrim trim characters from the left-side of the input.
|
|
||||||
// If second argument is empty, it's will be remove leading spaces.
|
|
||||||
func LeftTrim(str, chars string) string {
|
|
||||||
pattern := ""
|
|
||||||
if chars == "" {
|
|
||||||
pattern = "^\\s+"
|
|
||||||
} else {
|
|
||||||
pattern = "^[" + chars + "]+"
|
|
||||||
}
|
|
||||||
r, _ := regexp.Compile(pattern)
|
|
||||||
return string(r.ReplaceAll([]byte(str), []byte("")))
|
|
||||||
}
|
|
||||||
|
|
||||||
// RightTrim trim characters from the right-side of the input.
|
|
||||||
// If second argument is empty, it's will be remove spaces.
|
|
||||||
func RightTrim(str, chars string) string {
|
|
||||||
pattern := ""
|
|
||||||
if chars == "" {
|
|
||||||
pattern = "\\s+$"
|
|
||||||
} else {
|
|
||||||
pattern = "[" + chars + "]+$"
|
|
||||||
}
|
|
||||||
r, _ := regexp.Compile(pattern)
|
|
||||||
return string(r.ReplaceAll([]byte(str), []byte("")))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trim trim characters from both sides of the input.
|
|
||||||
// If second argument is empty, it's will be remove spaces.
|
|
||||||
func Trim(str, chars string) string {
|
|
||||||
return LeftTrim(RightTrim(str, chars), chars)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhiteList remove characters that do not appear in the whitelist.
|
|
||||||
func WhiteList(str, chars string) string {
|
|
||||||
pattern := "[^" + chars + "]+"
|
|
||||||
r, _ := regexp.Compile(pattern)
|
|
||||||
return string(r.ReplaceAll([]byte(str), []byte("")))
|
|
||||||
}
|
|
||||||
|
|
||||||
// BlackList remove characters that appear in the blacklist.
|
|
||||||
func BlackList(str, chars string) string {
|
|
||||||
pattern := "[" + chars + "]+"
|
|
||||||
r, _ := regexp.Compile(pattern)
|
|
||||||
return string(r.ReplaceAll([]byte(str), []byte("")))
|
|
||||||
}
|
|
||||||
|
|
||||||
// StripLow remove characters with a numerical value < 32 and 127, mostly control characters.
|
|
||||||
// If keep_new_lines is true, newline characters are preserved (\n and \r, hex 0xA and 0xD).
|
|
||||||
func StripLow(str string, keepNewLines bool) string {
|
|
||||||
chars := ""
|
|
||||||
if keepNewLines {
|
|
||||||
chars = "\x00-\x09\x0B\x0C\x0E-\x1F\x7F"
|
|
||||||
} else {
|
|
||||||
chars = "\x00-\x1F\x7F"
|
|
||||||
}
|
|
||||||
return BlackList(str, chars)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReplacePattern replace regular expression pattern in string
|
|
||||||
func ReplacePattern(str, pattern, replace string) string {
|
|
||||||
r, _ := regexp.Compile(pattern)
|
|
||||||
return string(r.ReplaceAll([]byte(str), []byte(replace)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Escape replace <, >, & and " with HTML entities.
|
|
||||||
var Escape = html.EscapeString
|
|
||||||
|
|
||||||
func addSegment(inrune, segment []rune) []rune {
|
|
||||||
if len(segment) == 0 {
|
|
||||||
return inrune
|
|
||||||
}
|
|
||||||
if len(inrune) != 0 {
|
|
||||||
inrune = append(inrune, '_')
|
|
||||||
}
|
|
||||||
inrune = append(inrune, segment...)
|
|
||||||
return inrune
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnderscoreToCamelCase converts from underscore separated form to camel case form.
|
|
||||||
// Ex.: my_func => MyFunc
|
|
||||||
func UnderscoreToCamelCase(s string) string {
|
|
||||||
return strings.Replace(strings.Title(strings.Replace(strings.ToLower(s), "_", " ", -1)), " ", "", -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CamelCaseToUnderscore converts from camel case form to underscore separated form.
|
|
||||||
// Ex.: MyFunc => my_func
|
|
||||||
func CamelCaseToUnderscore(str string) string {
|
|
||||||
var output []rune
|
|
||||||
var segment []rune
|
|
||||||
for _, r := range str {
|
|
||||||
if !unicode.IsLower(r) {
|
|
||||||
output = addSegment(output, segment)
|
|
||||||
segment = nil
|
|
||||||
}
|
|
||||||
segment = append(segment, unicode.ToLower(r))
|
|
||||||
}
|
|
||||||
output = addSegment(output, segment)
|
|
||||||
return string(output)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reverse return reversed string
|
|
||||||
func Reverse(s string) string {
|
|
||||||
r := []rune(s)
|
|
||||||
for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
|
|
||||||
r[i], r[j] = r[j], r[i]
|
|
||||||
}
|
|
||||||
return string(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetLines split string by "\n" and return array of lines
|
|
||||||
func GetLines(s string) []string {
|
|
||||||
return strings.Split(s, "\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetLine return specified line of multiline string
|
|
||||||
func GetLine(s string, index int) (string, error) {
|
|
||||||
lines := GetLines(s)
|
|
||||||
if index < 0 || index >= len(lines) {
|
|
||||||
return "", errors.New("line index out of bounds")
|
|
||||||
}
|
|
||||||
return lines[index], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveTags remove all tags from HTML string
|
|
||||||
func RemoveTags(s string) string {
|
|
||||||
return ReplacePattern(s, "<[^>]*>", "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// SafeFileName return safe string that can be used in file names
|
|
||||||
func SafeFileName(str string) string {
|
|
||||||
name := strings.ToLower(str)
|
|
||||||
name = path.Clean(path.Base(name))
|
|
||||||
name = strings.Trim(name, " ")
|
|
||||||
separators, err := regexp.Compile(`[ &_=+:]`)
|
|
||||||
if err == nil {
|
|
||||||
name = separators.ReplaceAllString(name, "-")
|
|
||||||
}
|
|
||||||
legal, err := regexp.Compile(`[^[:alnum:]-.]`)
|
|
||||||
if err == nil {
|
|
||||||
name = legal.ReplaceAllString(name, "")
|
|
||||||
}
|
|
||||||
for strings.Contains(name, "--") {
|
|
||||||
name = strings.Replace(name, "--", "-", -1)
|
|
||||||
}
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
|
|
||||||
// NormalizeEmail canonicalize an email address.
|
|
||||||
// The local part of the email address is lowercased for all domains; the hostname is always lowercased and
|
|
||||||
// the local part of the email address is always lowercased for hosts that are known to be case-insensitive (currently only GMail).
|
|
||||||
// Normalization follows special rules for known providers: currently, GMail addresses have dots removed in the local part and
|
|
||||||
// are stripped of tags (e.g. some.one+tag@gmail.com becomes someone@gmail.com) and all @googlemail.com addresses are
|
|
||||||
// normalized to @gmail.com.
|
|
||||||
func NormalizeEmail(str string) (string, error) {
|
|
||||||
if !IsEmail(str) {
|
|
||||||
return "", fmt.Errorf("%s is not an email", str)
|
|
||||||
}
|
|
||||||
parts := strings.Split(str, "@")
|
|
||||||
parts[0] = strings.ToLower(parts[0])
|
|
||||||
parts[1] = strings.ToLower(parts[1])
|
|
||||||
if parts[1] == "gmail.com" || parts[1] == "googlemail.com" {
|
|
||||||
parts[1] = "gmail.com"
|
|
||||||
parts[0] = strings.Split(ReplacePattern(parts[0], `\.`, ""), "+")[0]
|
|
||||||
}
|
|
||||||
return strings.Join(parts, "@"), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Truncate a string to the closest length without breaking words.
|
|
||||||
func Truncate(str string, length int, ending string) string {
|
|
||||||
var aftstr, befstr string
|
|
||||||
if len(str) > length {
|
|
||||||
words := strings.Fields(str)
|
|
||||||
before, present := 0, 0
|
|
||||||
for i := range words {
|
|
||||||
befstr = aftstr
|
|
||||||
before = present
|
|
||||||
aftstr = aftstr + words[i] + " "
|
|
||||||
present = len(aftstr)
|
|
||||||
if present > length && i != 0 {
|
|
||||||
if (length - before) < (present - length) {
|
|
||||||
return Trim(befstr, " /\\.,\"'#!?&@+-") + ending
|
|
||||||
}
|
|
||||||
return Trim(aftstr, " /\\.,\"'#!?&@+-") + ending
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
|
|
||||||
// PadLeft pad left side of string if size of string is less then indicated pad length
|
|
||||||
func PadLeft(str string, padStr string, padLen int) string {
|
|
||||||
return buildPadStr(str, padStr, padLen, true, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PadRight pad right side of string if size of string is less then indicated pad length
|
|
||||||
func PadRight(str string, padStr string, padLen int) string {
|
|
||||||
return buildPadStr(str, padStr, padLen, false, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PadBoth pad sides of string if size of string is less then indicated pad length
|
|
||||||
func PadBoth(str string, padStr string, padLen int) string {
|
|
||||||
return buildPadStr(str, padStr, padLen, true, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PadString either left, right or both sides, not the padding string can be unicode and more then one
|
|
||||||
// character
|
|
||||||
func buildPadStr(str string, padStr string, padLen int, padLeft bool, padRight bool) string {
|
|
||||||
|
|
||||||
// When padded length is less then the current string size
|
|
||||||
if padLen < utf8.RuneCountInString(str) {
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
|
|
||||||
padLen -= utf8.RuneCountInString(str)
|
|
||||||
|
|
||||||
targetLen := padLen
|
|
||||||
|
|
||||||
targetLenLeft := targetLen
|
|
||||||
targetLenRight := targetLen
|
|
||||||
if padLeft && padRight {
|
|
||||||
targetLenLeft = padLen / 2
|
|
||||||
targetLenRight = padLen - targetLenLeft
|
|
||||||
}
|
|
||||||
|
|
||||||
strToRepeatLen := utf8.RuneCountInString(padStr)
|
|
||||||
|
|
||||||
repeatTimes := int(math.Ceil(float64(targetLen) / float64(strToRepeatLen)))
|
|
||||||
repeatedString := strings.Repeat(padStr, repeatTimes)
|
|
||||||
|
|
||||||
leftSide := ""
|
|
||||||
if padLeft {
|
|
||||||
leftSide = repeatedString[0:targetLenLeft]
|
|
||||||
}
|
|
||||||
|
|
||||||
rightSide := ""
|
|
||||||
if padRight {
|
|
||||||
rightSide = repeatedString[0:targetLenRight]
|
|
||||||
}
|
|
||||||
|
|
||||||
return leftSide + str + rightSide
|
|
||||||
}
|
|
1066
vendor/github.com/asaskevich/govalidator/validator.go
generated
vendored
1066
vendor/github.com/asaskevich/govalidator/validator.go
generated
vendored
File diff suppressed because it is too large
Load diff
15
vendor/github.com/asaskevich/govalidator/wercker.yml
generated
vendored
15
vendor/github.com/asaskevich/govalidator/wercker.yml
generated
vendored
|
@ -1,15 +0,0 @@
|
||||||
box: golang
|
|
||||||
build:
|
|
||||||
steps:
|
|
||||||
- setup-go-workspace
|
|
||||||
|
|
||||||
- script:
|
|
||||||
name: go get
|
|
||||||
code: |
|
|
||||||
go version
|
|
||||||
go get -t ./...
|
|
||||||
|
|
||||||
- script:
|
|
||||||
name: go test
|
|
||||||
code: |
|
|
||||||
go test -race ./...
|
|
6
vendor/vendor.json
vendored
6
vendor/vendor.json
vendored
|
@ -76,12 +76,6 @@
|
||||||
"revision": "2efee857e7cfd4f3d0138cc3cbb1b4966962b93a",
|
"revision": "2efee857e7cfd4f3d0138cc3cbb1b4966962b93a",
|
||||||
"revisionTime": "2015-10-22T06:55:26Z"
|
"revisionTime": "2015-10-22T06:55:26Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"checksumSHA1": "ddYc7mKe3g1x1UUKBrGR4vArJs8=",
|
|
||||||
"path": "github.com/asaskevich/govalidator",
|
|
||||||
"revision": "065ea97278837088c52c0cd0d963473f61b2d98c",
|
|
||||||
"revisionTime": "2017-05-13T08:31:01Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"checksumSHA1": "WNfR3yhLjRC5/uccgju/bwrdsxQ=",
|
"checksumSHA1": "WNfR3yhLjRC5/uccgju/bwrdsxQ=",
|
||||||
"path": "github.com/aws/aws-sdk-go/aws",
|
"path": "github.com/aws/aws-sdk-go/aws",
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -120,6 +120,7 @@ Prometheus.Graph.prototype.initialize = function() {
|
||||||
showTodayButton: true,
|
showTodayButton: true,
|
||||||
showClear: true,
|
showClear: true,
|
||||||
showClose: true,
|
showClose: true,
|
||||||
|
timeZone: 'UTC',
|
||||||
});
|
});
|
||||||
if (self.options.end_input) {
|
if (self.options.end_input) {
|
||||||
self.endDate.data('DateTimePicker').date(self.options.end_input);
|
self.endDate.data('DateTimePicker').date(self.options.end_input);
|
||||||
|
@ -620,7 +621,7 @@ Prometheus.Graph.prototype.updateGraph = function() {
|
||||||
var yAxis = new Rickshaw.Graph.Axis.Y({
|
var yAxis = new Rickshaw.Graph.Axis.Y({
|
||||||
graph: self.rickshawGraph,
|
graph: self.rickshawGraph,
|
||||||
orientation: "left",
|
orientation: "left",
|
||||||
tickFormat: Rickshaw.Fixtures.Number.formatKMBT,
|
tickFormat: this.formatKMBT,
|
||||||
element: self.yAxis[0],
|
element: self.yAxis[0],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -733,6 +734,49 @@ Prometheus.Graph.prototype.remove = function() {
|
||||||
self.handleChange();
|
self.handleChange();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Prometheus.Graph.prototype.formatKMBT = function(y) {
|
||||||
|
var abs_y = Math.abs(y);
|
||||||
|
if (abs_y >= 1e24) {
|
||||||
|
return (y / 1e24).toString() + "Y";
|
||||||
|
} else if (abs_y >= 1e21) {
|
||||||
|
return (y / 1e21).toString() + "Z";
|
||||||
|
} else if (abs_y >= 1e18) {
|
||||||
|
return (y / 1e18).toString() + "E";
|
||||||
|
} else if (abs_y >= 1e15) {
|
||||||
|
return (y / 1e15).toString() + "P";
|
||||||
|
} else if (abs_y >= 1e12) {
|
||||||
|
return (y / 1e12).toString() + "T";
|
||||||
|
} else if (abs_y >= 1e9) {
|
||||||
|
return (y / 1e9).toString() + "G";
|
||||||
|
} else if (abs_y >= 1e6) {
|
||||||
|
return (y / 1e6).toString() + "M";
|
||||||
|
} else if (abs_y >= 1e3) {
|
||||||
|
return (y / 1e3).toString() + "k";
|
||||||
|
} else if (abs_y >= 1) {
|
||||||
|
return y
|
||||||
|
} else if (abs_y === 0) {
|
||||||
|
return y
|
||||||
|
} else if (abs_y <= 1e-24) {
|
||||||
|
return (y / 1e-24).toString() + "y";
|
||||||
|
} else if (abs_y <= 1e-21) {
|
||||||
|
return (y / 1e-21).toString() + "z";
|
||||||
|
} else if (abs_y <= 1e-18) {
|
||||||
|
return (y / 1e-18).toString() + "a";
|
||||||
|
} else if (abs_y <= 1e-15) {
|
||||||
|
return (y / 1e-15).toString() + "f";
|
||||||
|
} else if (abs_y <= 1e-12) {
|
||||||
|
return (y / 1e-12).toString() + "p";
|
||||||
|
} else if (abs_y <= 1e-9) {
|
||||||
|
return (y / 1e-9).toString() + "n";
|
||||||
|
} else if (abs_y <= 1e-6) {
|
||||||
|
return (y / 1e-6).toString() + "µ";
|
||||||
|
} else if (abs_y <=1e-3) {
|
||||||
|
return (y / 1e-3).toString() + "m";
|
||||||
|
} else if (abs_y <= 1) {
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function escapeHTML(string) {
|
function escapeHTML(string) {
|
||||||
var entityMap = {
|
var entityMap = {
|
||||||
"&": "&",
|
"&": "&",
|
||||||
|
|
|
@ -77,7 +77,7 @@
|
||||||
<input
|
<input
|
||||||
class="pull-left date_input input"
|
class="pull-left date_input input"
|
||||||
id="end{{id}}"
|
id="end{{id}}"
|
||||||
title="End time of graph"
|
title="End time of graph (UTC)"
|
||||||
placeholder="Until"
|
placeholder="Until"
|
||||||
data-format="yyyy-MM-dd"
|
data-format="yyyy-MM-dd"
|
||||||
type="text"
|
type="text"
|
||||||
|
|
41
web/ui/static/vendor/js/jquery.hotkeys.js
vendored
41
web/ui/static/vendor/js/jquery.hotkeys.js
vendored
|
@ -13,7 +13,7 @@
|
||||||
(function(jQuery){
|
(function(jQuery){
|
||||||
|
|
||||||
jQuery.hotkeys = {
|
jQuery.hotkeys = {
|
||||||
version: "0.8",
|
version: "0.8+",
|
||||||
|
|
||||||
specialKeys: {
|
specialKeys: {
|
||||||
8: "backspace", 9: "tab", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause",
|
8: "backspace", 9: "tab", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause",
|
||||||
|
@ -22,7 +22,8 @@
|
||||||
96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7",
|
96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7",
|
||||||
104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111 : "/",
|
104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111 : "/",
|
||||||
112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8",
|
112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8",
|
||||||
120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 191: "/", 224: "meta"
|
120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 188: ",", 190: ".",
|
||||||
|
191: "/", 224: "meta"
|
||||||
},
|
},
|
||||||
|
|
||||||
shiftNums: {
|
shiftNums: {
|
||||||
|
@ -33,19 +34,31 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
function keyHandler( handleObj ) {
|
function keyHandler( handleObj ) {
|
||||||
// Only care when a possible input has been specified
|
|
||||||
if ( typeof handleObj.data !== "string" ) {
|
var origHandler = handleObj.handler,
|
||||||
|
//use namespace as keys so it works with event delegation as well
|
||||||
|
//will also allow removing listeners of a specific key combination
|
||||||
|
//and support data objects
|
||||||
|
keys = (handleObj.namespace || "").toLowerCase().split(" ");
|
||||||
|
keys = jQuery.map(keys, function(key) { return key.split("."); });
|
||||||
|
|
||||||
|
//no need to modify handler if no keys specified
|
||||||
|
//Added keys[0].substring(0, 12) to work with jQuery ui 1.9.0
|
||||||
|
//Added accordion, tabs and menu, then jquery ui can use keys.
|
||||||
|
|
||||||
|
if (keys.length === 1 && (keys[0] === "" ||
|
||||||
|
keys[0].substring(0, 12) === "autocomplete" ||
|
||||||
|
keys[0].substring(0, 9) === "accordion" ||
|
||||||
|
keys[0].substring(0, 4) === "tabs" ||
|
||||||
|
keys[0].substring(0, 4) === "menu")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var origHandler = handleObj.handler,
|
|
||||||
keys = handleObj.data.toLowerCase().split(" "),
|
|
||||||
textAcceptingInputTypes = ["text", "password", "number", "email", "url", "range", "date", "month", "week", "time", "datetime", "datetime-local", "search", "color"];
|
|
||||||
|
|
||||||
handleObj.handler = function( event ) {
|
handleObj.handler = function( event ) {
|
||||||
// Don't fire in text-accepting inputs that we didn't directly bind to
|
// Don't fire in text-accepting inputs that we didn't directly bind to
|
||||||
|
// important to note that $.fn.prop is only available on jquery 1.6+
|
||||||
if ( this !== event.target && (/textarea|select/i.test( event.target.nodeName ) ||
|
if ( this !== event.target && (/textarea|select/i.test( event.target.nodeName ) ||
|
||||||
jQuery.inArray(event.target.type, textAcceptingInputTypes) > -1 ) ) {
|
event.target.type === "text" || $(event.target).prop('contenteditable') == 'true' )) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,20 +69,20 @@
|
||||||
|
|
||||||
// check combinations (alt|ctrl|shift+anything)
|
// check combinations (alt|ctrl|shift+anything)
|
||||||
if ( event.altKey && special !== "alt" ) {
|
if ( event.altKey && special !== "alt" ) {
|
||||||
modif += "alt+";
|
modif += "alt_";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( event.ctrlKey && special !== "ctrl" ) {
|
if ( event.ctrlKey && special !== "ctrl" ) {
|
||||||
modif += "ctrl+";
|
modif += "ctrl_";
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Need to make sure this works consistently across platforms
|
// TODO: Need to make sure this works consistently across platforms
|
||||||
if ( event.metaKey && !event.ctrlKey && special !== "meta" ) {
|
if ( event.metaKey && !event.ctrlKey && special !== "meta" ) {
|
||||||
modif += "meta+";
|
modif += "meta_";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( event.shiftKey && special !== "shift" ) {
|
if ( event.shiftKey && special !== "shift" ) {
|
||||||
modif += "shift+";
|
modif += "shift_";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( special ) {
|
if ( special ) {
|
||||||
|
@ -80,7 +93,7 @@
|
||||||
possible[ modif + jQuery.hotkeys.shiftNums[ character ] ] = true;
|
possible[ modif + jQuery.hotkeys.shiftNums[ character ] ] = true;
|
||||||
|
|
||||||
// "$" can be triggered as "Shift+4" or "Shift+$" or just "$"
|
// "$" can be triggered as "Shift+4" or "Shift+$" or just "$"
|
||||||
if ( modif === "shift+" ) {
|
if ( modif === "shift_" ) {
|
||||||
possible[ jQuery.hotkeys.shiftNums[ character ] ] = true;
|
possible[ jQuery.hotkeys.shiftNums[ character ] ] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
8
web/ui/static/vendor/js/jquery.min.js
vendored
8
web/ui/static/vendor/js/jquery.min.js
vendored
File diff suppressed because one or more lines are too long
136
web/ui/static/vendor/js/jquery.selection.js
vendored
136
web/ui/static/vendor/js/jquery.selection.js
vendored
|
@ -1,7 +1,7 @@
|
||||||
/*!
|
/*!
|
||||||
* jQuery.selection - jQuery Plugin
|
* jQuery.selection - jQuery Plugin
|
||||||
*
|
*
|
||||||
* Copyright (c) 2010-2012 IWASAKI Koji (@madapaja).
|
* Copyright (c) 2010-2014 IWASAKI Koji (@madapaja).
|
||||||
* http://blog.madapaja.net/
|
* http://blog.madapaja.net/
|
||||||
* Under The MIT License
|
* Under The MIT License
|
||||||
*
|
*
|
||||||
|
@ -26,13 +26,13 @@
|
||||||
*/
|
*/
|
||||||
(function($, win, doc) {
|
(function($, win, doc) {
|
||||||
/**
|
/**
|
||||||
* 要素の文字列選択状態を取得します
|
* get caret status of the selection of the element
|
||||||
*
|
*
|
||||||
* @param {Element} element 対象要素
|
* @param {Element} element target DOM element
|
||||||
* @return {Object} return
|
* @return {Object} return
|
||||||
* @return {String} return.text 選択されている文字列
|
* @return {String} return.text selected text
|
||||||
* @return {Integer} return.start 選択開始位置
|
* @return {Number} return.start start position of the selection
|
||||||
* @return {Integer} return.end 選択終了位置
|
* @return {Number} return.end end position of the selection
|
||||||
*/
|
*/
|
||||||
var _getCaretInfo = function(element){
|
var _getCaretInfo = function(element){
|
||||||
var res = {
|
var res = {
|
||||||
|
@ -42,13 +42,13 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!element.value) {
|
if (!element.value) {
|
||||||
/* 値がない、もしくは空文字列 */
|
/* no value or empty string */
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (win.getSelection) {
|
if (win.getSelection) {
|
||||||
/* IE 以外 */
|
/* except IE */
|
||||||
res.start = element.selectionStart;
|
res.start = element.selectionStart;
|
||||||
res.end = element.selectionEnd;
|
res.end = element.selectionEnd;
|
||||||
res.text = element.value.slice(res.start, res.end);
|
res.text = element.value.slice(res.start, res.end);
|
||||||
|
@ -57,8 +57,7 @@
|
||||||
element.focus();
|
element.focus();
|
||||||
|
|
||||||
var range = doc.selection.createRange(),
|
var range = doc.selection.createRange(),
|
||||||
range2 = doc.body.createTextRange(),
|
range2 = doc.body.createTextRange();
|
||||||
tmpLength;
|
|
||||||
|
|
||||||
res.text = range.text;
|
res.text = range.text;
|
||||||
|
|
||||||
|
@ -74,24 +73,24 @@
|
||||||
res.end = res.start + range.text.length;
|
res.end = res.start + range.text.length;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
/* あきらめる */
|
/* give up */
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 要素に対するキャレット操作
|
* caret operation for the element
|
||||||
* @type {Object}
|
* @type {Object}
|
||||||
*/
|
*/
|
||||||
var _CaretOperation = {
|
var _CaretOperation = {
|
||||||
/**
|
/**
|
||||||
* 要素のキャレット位置を取得します
|
* get caret position
|
||||||
*
|
*
|
||||||
* @param {Element} element 対象要素
|
* @param {Element} element target element
|
||||||
* @return {Object} return
|
* @return {Object} return
|
||||||
* @return {Integer} return.start 選択開始位置
|
* @return {Number} return.start start position for the selection
|
||||||
* @return {Integer} return.end 選択終了位置
|
* @return {Number} return.end end position for the selection
|
||||||
*/
|
*/
|
||||||
getPos: function(element) {
|
getPos: function(element) {
|
||||||
var tmp = _getCaretInfo(element);
|
var tmp = _getCaretInfo(element);
|
||||||
|
@ -99,20 +98,20 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 要素のキャレット位置を設定します
|
* set caret position
|
||||||
*
|
*
|
||||||
* @param {Element} element 対象要素
|
* @param {Element} element target element
|
||||||
* @param {Object} toRange 設定するキャレット位置
|
* @param {Object} toRange caret position
|
||||||
* @param {Integer} toRange.start 選択開始位置
|
* @param {Number} toRange.start start position for the selection
|
||||||
* @param {Integer} toRange.end 選択終了位置
|
* @param {Number} toRange.end end position for the selection
|
||||||
* @param {String} caret キャレットモード "keep" | "start" | "end" のいずれか
|
* @param {String} caret caret mode: any of the following: "keep" | "start" | "end"
|
||||||
*/
|
*/
|
||||||
setPos: function(element, toRange, caret) {
|
setPos: function(element, toRange, caret) {
|
||||||
caret = this._caretMode(caret);
|
caret = this._caretMode(caret);
|
||||||
|
|
||||||
if (caret == 'start') {
|
if (caret === 'start') {
|
||||||
toRange.end = toRange.start;
|
toRange.end = toRange.start;
|
||||||
} else if (caret == 'end') {
|
} else if (caret === 'end') {
|
||||||
toRange.start = toRange.end;
|
toRange.start = toRange.end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,29 +134,29 @@
|
||||||
element.setSelectionRange(toRange.start, toRange.end);
|
element.setSelectionRange(toRange.start, toRange.end);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
/* あきらめる */
|
/* give up */
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 要素内の選択文字列を取得します
|
* get selected text
|
||||||
*
|
*
|
||||||
* @param {Element} element 対象要素
|
* @param {Element} element target element
|
||||||
* @return {String} return 選択文字列
|
* @return {String} return selected text
|
||||||
*/
|
*/
|
||||||
getText: function(element) {
|
getText: function(element) {
|
||||||
return _getCaretInfo(element).text;
|
return _getCaretInfo(element).text;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* キャレットモードを選択します
|
* get caret mode
|
||||||
*
|
*
|
||||||
* @param {String} caret キャレットモード
|
* @param {String} caret caret mode
|
||||||
* @return {String} return "keep" | "start" | "end" のいずれか
|
* @return {String} return any of the following: "keep" | "start" | "end"
|
||||||
*/
|
*/
|
||||||
_caretMode: function(caret) {
|
_caretMode: function(caret) {
|
||||||
caret = caret || "keep";
|
caret = caret || "keep";
|
||||||
if (caret == false) {
|
if (caret === false) {
|
||||||
caret = 'end';
|
caret = 'end';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,11 +174,11 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 選択文字列を置き換えます
|
* replace selected text
|
||||||
*
|
*
|
||||||
* @param {Element} element 対象要素
|
* @param {Element} element target element
|
||||||
* @param {String} text 置き換える文字列
|
* @param {String} text replacement text
|
||||||
* @param {String} caret キャレットモード "keep" | "start" | "end" のいずれか
|
* @param {String} caret caret mode: any of the following: "keep" | "start" | "end"
|
||||||
*/
|
*/
|
||||||
replace: function(element, text, caret) {
|
replace: function(element, text, caret) {
|
||||||
var tmp = _getCaretInfo(element),
|
var tmp = _getCaretInfo(element),
|
||||||
|
@ -194,11 +193,11 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文字列を選択文字列の前に挿入します
|
* insert before the selected text
|
||||||
*
|
*
|
||||||
* @param {Element} element 対象要素
|
* @param {Element} element target element
|
||||||
* @param {String} text 挿入文字列
|
* @param {String} text insertion text
|
||||||
* @param {String} caret キャレットモード "keep" | "start" | "end" のいずれか
|
* @param {String} caret caret mode: any of the following: "keep" | "start" | "end"
|
||||||
*/
|
*/
|
||||||
insertBefore: function(element, text, caret) {
|
insertBefore: function(element, text, caret) {
|
||||||
var tmp = _getCaretInfo(element),
|
var tmp = _getCaretInfo(element),
|
||||||
|
@ -213,11 +212,11 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文字列を選択文字列の後に挿入します
|
* insert after the selected text
|
||||||
*
|
*
|
||||||
* @param {Element} element 対象要素
|
* @param {Element} element target element
|
||||||
* @param {String} text 挿入文字列
|
* @param {String} text insertion text
|
||||||
* @param {String} caret キャレットモード "keep" | "start" | "end" のいずれか
|
* @param {String} caret caret mode: any of the following: "keep" | "start" | "end"
|
||||||
*/
|
*/
|
||||||
insertAfter: function(element, text, caret) {
|
insertAfter: function(element, text, caret) {
|
||||||
var tmp = _getCaretInfo(element),
|
var tmp = _getCaretInfo(element),
|
||||||
|
@ -232,16 +231,16 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* jQuery.selection を追加 */
|
/* add jQuery.selection */
|
||||||
$.extend({
|
$.extend({
|
||||||
/**
|
/**
|
||||||
* ウィンドウの選択されている文字列を取得
|
* get selected text on the window
|
||||||
*
|
*
|
||||||
* @param {String} mode 選択モード "text" | "html" のいずれか
|
* @param {String} mode selection mode: any of the following: "text" | "html"
|
||||||
* @return {String} return
|
* @return {String} return
|
||||||
*/
|
*/
|
||||||
selection: function(mode) {
|
selection: function(mode) {
|
||||||
var getText = ((mode || 'text').toLowerCase() == 'text');
|
var getText = ((mode || 'text').toLowerCase() === 'text');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (win.getSelection) {
|
if (win.getSelection) {
|
||||||
|
@ -272,14 +271,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
/* あきらめる */
|
/* give up */
|
||||||
}
|
}
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/* selection を追加 */
|
/* add selection */
|
||||||
$.fn.extend({
|
$.fn.extend({
|
||||||
selection: function(mode, opts) {
|
selection: function(mode, opts) {
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
|
@ -287,71 +286,66 @@
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
/**
|
/**
|
||||||
* selection('getPos')
|
* selection('getPos')
|
||||||
* キャレット位置を取得します
|
* get caret position
|
||||||
*
|
*
|
||||||
* @return {Object} return
|
* @return {Object} return
|
||||||
* @return {Integer} return.start 選択開始位置
|
* @return {Number} return.start start position for the selection
|
||||||
* @return {Integer} return.end 選択終了位置
|
* @return {Number} return.end end position for the selection
|
||||||
*/
|
*/
|
||||||
case 'getPos':
|
case 'getPos':
|
||||||
return _CaretOperation.getPos(this[0]);
|
return _CaretOperation.getPos(this[0]);
|
||||||
break;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* selection('setPos', opts)
|
* selection('setPos', opts)
|
||||||
* キャレット位置を設定します
|
* set caret position
|
||||||
*
|
*
|
||||||
* @param {Integer} opts.start 選択開始位置
|
* @param {Number} opts.start start position for the selection
|
||||||
* @param {Integer} opts.end 選択終了位置
|
* @param {Number} opts.end end position for the selection
|
||||||
*/
|
*/
|
||||||
case 'setPos':
|
case 'setPos':
|
||||||
return this.each(function() {
|
return this.each(function() {
|
||||||
_CaretOperation.setPos(this, opts);
|
_CaretOperation.setPos(this, opts);
|
||||||
});
|
});
|
||||||
break;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* selection('replace', opts)
|
* selection('replace', opts)
|
||||||
* 選択文字列を置き換えます
|
* replace the selected text
|
||||||
*
|
*
|
||||||
* @param {String} opts.text 置き換える文字列
|
* @param {String} opts.text replacement text
|
||||||
* @param {String} opts.caret キャレットモード "keep" | "start" | "end" のいずれか
|
* @param {String} opts.caret caret mode: any of the following: "keep" | "start" | "end"
|
||||||
*/
|
*/
|
||||||
case 'replace':
|
case 'replace':
|
||||||
return this.each(function() {
|
return this.each(function() {
|
||||||
_CaretOperation.replace(this, opts.text, opts.caret);
|
_CaretOperation.replace(this, opts.text, opts.caret);
|
||||||
});
|
});
|
||||||
break;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* selection('insert', opts)
|
* selection('insert', opts)
|
||||||
* 選択文字列の前、もしくは後に文字列を挿入えます
|
* insert before/after the selected text
|
||||||
*
|
*
|
||||||
* @param {String} opts.text 挿入文字列
|
* @param {String} opts.text insertion text
|
||||||
* @param {String} opts.caret キャレットモード "keep" | "start" | "end" のいずれか
|
* @param {String} opts.caret caret mode: any of the following: "keep" | "start" | "end"
|
||||||
* @param {String} opts.mode 挿入モード "before" | "after" のいずれか
|
* @param {String} opts.mode insertion mode: any of the following: "before" | "after"
|
||||||
*/
|
*/
|
||||||
case 'insert':
|
case 'insert':
|
||||||
return this.each(function() {
|
return this.each(function() {
|
||||||
if (opts.mode == 'before') {
|
if (opts.mode === 'before') {
|
||||||
_CaretOperation.insertBefore(this, opts.text, opts.caret);
|
_CaretOperation.insertBefore(this, opts.text, opts.caret);
|
||||||
} else {
|
} else {
|
||||||
_CaretOperation.insertAfter(this, opts.text, opts.caret);
|
_CaretOperation.insertAfter(this, opts.text, opts.caret);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* selection('get')
|
* selection('get')
|
||||||
* 選択されている文字列を取得
|
* get selected text
|
||||||
*
|
*
|
||||||
* @return {String} return
|
* @return {String} return
|
||||||
*/
|
*/
|
||||||
case 'get':
|
case 'get':
|
||||||
|
/* falls through */
|
||||||
default:
|
default:
|
||||||
return _CaretOperation.getText(this[0]);
|
return _CaretOperation.getText(this[0]);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
|
7
web/ui/static/vendor/moment/moment-timezone-with-data.min.js
vendored
Normal file
7
web/ui/static/vendor/moment/moment-timezone-with-data.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -8,6 +8,7 @@
|
||||||
<script src="{{ pathPrefix }}/static/vendor/rickshaw/vendor/d3.layout.min.js?v={{ buildVersion }}"></script>
|
<script src="{{ pathPrefix }}/static/vendor/rickshaw/vendor/d3.layout.min.js?v={{ buildVersion }}"></script>
|
||||||
<script src="{{ pathPrefix }}/static/vendor/rickshaw/rickshaw.min.js?v={{ buildVersion }}"></script>
|
<script src="{{ pathPrefix }}/static/vendor/rickshaw/rickshaw.min.js?v={{ buildVersion }}"></script>
|
||||||
<script src="{{ pathPrefix }}/static/vendor/moment/moment.min.js?v={{ buildVersion }}"></script>
|
<script src="{{ pathPrefix }}/static/vendor/moment/moment.min.js?v={{ buildVersion }}"></script>
|
||||||
|
<script src="{{ pathPrefix }}/static/vendor/moment/moment-timezone-with-data.min.js?v={{ buildVersion }}"></script>
|
||||||
<script src="{{ pathPrefix }}/static/vendor/eonasdan-bootstrap-datetimepicker/bootstrap-datetimepicker.min.js?v={{ buildVersion }}"></script>
|
<script src="{{ pathPrefix }}/static/vendor/eonasdan-bootstrap-datetimepicker/bootstrap-datetimepicker.min.js?v={{ buildVersion }}"></script>
|
||||||
<script src="{{ pathPrefix }}/static/vendor/bootstrap3-typeahead/bootstrap3-typeahead.min.js?v={{ buildVersion }}"></script>
|
<script src="{{ pathPrefix }}/static/vendor/bootstrap3-typeahead/bootstrap3-typeahead.min.js?v={{ buildVersion }}"></script>
|
||||||
<script src="{{ pathPrefix }}/static/vendor/fuzzy/fuzzy.js?v={{ buildVersion }}"></script>
|
<script src="{{ pathPrefix }}/static/vendor/fuzzy/fuzzy.js?v={{ buildVersion }}"></script>
|
||||||
|
|
|
@ -284,6 +284,11 @@ func serveDebug(w http.ResponseWriter, req *http.Request) {
|
||||||
ctx := req.Context()
|
ctx := req.Context()
|
||||||
subpath := route.Param(ctx, "subpath")
|
subpath := route.Param(ctx, "subpath")
|
||||||
|
|
||||||
|
if subpath == "/pprof" {
|
||||||
|
http.Redirect(w, req, req.URL.Path+"/", http.StatusMovedPermanently)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if !strings.HasPrefix(subpath, "/pprof/") {
|
if !strings.HasPrefix(subpath, "/pprof/") {
|
||||||
http.NotFound(w, req)
|
http.NotFound(w, req)
|
||||||
return
|
return
|
||||||
|
@ -300,6 +305,7 @@ func serveDebug(w http.ResponseWriter, req *http.Request) {
|
||||||
case "trace":
|
case "trace":
|
||||||
pprof.Trace(w, req)
|
pprof.Trace(w, req)
|
||||||
default:
|
default:
|
||||||
|
req.URL.Path = "/debug/pprof/" + subpath
|
||||||
pprof.Index(w, req)
|
pprof.Index(w, req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ package web
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
"net/url"
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -231,3 +232,37 @@ func TestRoutePrefix(t *testing.T) {
|
||||||
t.Fatalf("Path "+opts.RoutePrefix+"/version with server ready test, Expected status 200 got: %s", resp.Status)
|
t.Fatalf("Path "+opts.RoutePrefix+"/version with server ready test, Expected status 200 got: %s", resp.Status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDebugHandler(t *testing.T) {
|
||||||
|
for _, tc := range []struct {
|
||||||
|
prefix, url string
|
||||||
|
code int
|
||||||
|
}{
|
||||||
|
{"/", "/debug/pprof/cmdline", 200},
|
||||||
|
{"/foo", "/foo/debug/pprof/cmdline", 200},
|
||||||
|
|
||||||
|
{"/", "/debug/pprof/goroutine", 200},
|
||||||
|
{"/foo", "/foo/debug/pprof/goroutine", 200},
|
||||||
|
|
||||||
|
{"/", "/debug/pprof/foo", 404},
|
||||||
|
{"/foo", "/bar/debug/pprof/goroutine", 404},
|
||||||
|
} {
|
||||||
|
opts := &Options{
|
||||||
|
RoutePrefix: tc.prefix,
|
||||||
|
MetricsPath: "/metrics",
|
||||||
|
}
|
||||||
|
handler := New(nil, opts)
|
||||||
|
handler.Ready()
|
||||||
|
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
req, err := http.NewRequest("GET", tc.url, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unexpected error %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.router.ServeHTTP(w, req)
|
||||||
|
if w.Code != tc.code {
|
||||||
|
t.Fatalf("Unexpected status code %d: %s", w.Code, w.Body.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue