Migrate to Go modules

Signed-off-by: Alex Ellis (OpenFaaS Ltd) <alexellis2@gmail.com>
This commit is contained in:
Alex Ellis (OpenFaaS Ltd)
2021-01-20 12:12:11 +00:00
committed by Alex Ellis
parent 2e2250afe8
commit 7ce266adc0
667 changed files with 211781 additions and 17546 deletions

View File

@ -13,4 +13,6 @@
# IDE Files
.vscode
.idea/
.idea/
coverage.out

View File

@ -1,22 +1,38 @@
os:
- linux
- windows
language: go
sudo: false
go:
- 1.13.x
- 1.12.x
- 1.13.x
- 1.14.x
git:
depth: false
env:
- V=
- V=v2
install:
- go get -t ./...
- go get github.com/mattn/goveralls
- go get github.com/wadey/gocovmerge
- go get -u honnef.co/go/tools/cmd/staticcheck
- go get -u github.com/client9/misspell/cmd/misspell
- go get -t ./...
- go get -u honnef.co/go/tools/cmd/staticcheck
- go get -u github.com/client9/misspell/cmd/misspell
- go get github.com/mattn/goveralls
- go get github.com/wadey/gocovmerge
before_script:
- $(exit $(go fmt ./... | wc -l))
- go vet ./...
- misspell -error -locale US .
- staticcheck ./...
- cd $TRAVIS_BUILD_DIR/${V}
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then EXCLUDE_VENDOR=$(go list ./... | grep -v "/vendor/") && $(exit $(go fmt $EXCLUDE_VENDOR | wc -l)) && go vet $EXCLUDE_VENDOR; fi
- go vet ./...
- misspell -error -locale US .
- staticcheck ./...
script:
- go test -v -race ./...
- if [[ "$TRAVIS_GO_VERSION" =~ 1.12 ]]; then ./scripts/cov.sh TRAVIS; fi
- mkdir cov
- go test -v -race -covermode=atomic -coverprofile=./cov/coverage.out -coverpkg=github.com/nats-io/jwt .
- gocovmerge ./cov/*.out > coverage.out
deploy:
- provider: script
skip_cleanup: true
script: $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service travis-ci
on:
condition: ${V} = "" && $TRAVIS_OS_NAME = linux && $TRAVIS_GO_VERSION =~ ^1.14

View File

@ -11,8 +11,20 @@ test:
go test -v --race
staticcheck ./...
cd v2/
gofmt -s -w *.go
goimports -w *.go
go vet ./...
go test -v
go test -v --race
staticcheck ./...
fmt:
gofmt -w -s *.go
go mod tidy
cd v2/
gofmt -w -s *.go
go mod tidy
cover:
go test -v -covermode=count -coverprofile=coverage.out

View File

@ -1,11 +1,11 @@
# JWT
A [JWT](https://jwt.io/) implementation that uses [nkeys](https://github.com/nats-io/nkeys) to digitally sign JWT tokens.
A [JWT](https://jwt.io/) implementation that uses [nkeys](https://github.com/nats-io/nkeys) to digitally sign JWT tokens.
Nkeys use [Ed25519](https://ed25519.cr.yp.to/) to provide authentication of JWT claims.
[![License Apache 2](https://img.shields.io/badge/License-Apache2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
[![ReportCard](http://goreportcard.com/badge/nats-io/jwt)](http://goreportcard.com/report/nats-io/jwt)
[![Build Status](https://travis-ci.org/nats-io/jwt.svg?branch=master)](http://travis-ci.org/nats-io/jwt)
[![Build Status](https://travis-ci.com/nats-io/jwt.svg?branch=master)](https://travis-ci.com/github/nats-io/jwt)
[![GoDoc](http://godoc.org/github.com/nats-io/jwt?status.png)](http://godoc.org/github.com/nats-io/jwt)
[![Coverage Status](https://coveralls.io/repos/github/nats-io/jwt/badge.svg?branch=master&t=NmEFup)](https://coveralls.io/github/nats-io/jwt?branch=master)

View File

@ -1,5 +1,5 @@
/*
* Copyright 2018-2019 The NATS Authors
* Copyright 2018-2020 The NATS Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@ -194,7 +194,8 @@ func (a *AccountClaims) Revoke(pubKey string) {
a.RevokeAt(pubKey, time.Now())
}
// RevokeAt enters a revocation by publickey and timestamp into this export
// RevokeAt enters a revocation by public key and timestamp into this account
// This will revoke all jwt issued for pubKey, prior to timestamp
// If there is already a revocation for this public key that is newer, it is kept.
func (a *AccountClaims) RevokeAt(pubKey string, timestamp time.Time) {
if a.Revocations == nil {
@ -209,14 +210,24 @@ func (a *AccountClaims) ClearRevocation(pubKey string) {
a.Revocations.ClearRevocation(pubKey)
}
// IsRevokedAt checks if the public key is in the revoked list with a timestamp later than
// the one passed in. Generally this method is called with time.Now() but other time's can
// be used for testing.
// IsRevokedAt checks if the public key is in the revoked list with a timestamp later than the one passed in.
// Generally this method is called with the subject and issue time of the jwt to be tested.
// DO NOT pass time.Now(), it will not produce a stable/expected response.
// The value is expected to be a public key or "*" (means all public keys)
func (a *AccountClaims) IsRevokedAt(pubKey string, timestamp time.Time) bool {
return a.Revocations.IsRevoked(pubKey, timestamp)
}
// IsRevoked checks if the public key is in the revoked list with time.Now()
func (a *AccountClaims) IsRevoked(pubKey string) bool {
return a.Revocations.IsRevoked(pubKey, time.Now())
// IsRevoked does not perform a valid check. Use IsRevokedAt instead.
func (a *AccountClaims) IsRevoked(_ string) bool {
return true
}
// IsClaimRevoked checks if the account revoked the claim passed in.
// Invalid claims (nil, no Subject or IssuedAt) will return true.
func (a *AccountClaims) IsClaimRevoked(claim *UserClaims) bool {
if claim == nil || claim.IssuedAt == 0 || claim.Subject == "" {
return true
}
return a.Revocations.IsRevoked(claim.Subject, time.Unix(claim.IssuedAt, 0))
}

View File

@ -38,12 +38,15 @@ const (
ActivationClaim = "activation"
//UserClaim is the type of an user JWT
UserClaim = "user"
//ServerClaim is the type of an server JWT
ServerClaim = "server"
//ClusterClaim is the type of an cluster JWT
ClusterClaim = "cluster"
//OperatorClaim is the type of an operator JWT
OperatorClaim = "operator"
//ServerClaim is the type of an server JWT
// Deprecated: ServerClaim is not supported
ServerClaim = "server"
// ClusterClaim is the type of an cluster JWT
// Deprecated: ClusterClaim is not supported
ClusterClaim = "cluster"
)
// Claims is a JWT claims

View File

@ -1,5 +1,5 @@
/*
* Copyright 2018 The NATS Authors
* Copyright 2018-2020 The NATS Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@ -22,6 +22,7 @@ import (
)
// Cluster stores the cluster specific elements of a cluster JWT
// Deprecated: ClusterClaims are not supported
type Cluster struct {
Trust []string `json:"identity,omitempty"`
Accounts []string `json:"accts,omitempty"`
@ -35,12 +36,14 @@ func (c *Cluster) Validate(vr *ValidationResults) {
}
// ClusterClaims defines the data in a cluster JWT
// Deprecated: ClusterClaims are not supported
type ClusterClaims struct {
ClaimsData
Cluster `json:"nats,omitempty"`
}
// NewClusterClaims creates a new cluster JWT with the specified subject/public key
// Deprecated: ClusterClaims are not supported
func NewClusterClaims(subject string) *ClusterClaims {
if subject == "" {
return nil
@ -60,6 +63,7 @@ func (c *ClusterClaims) Encode(pair nkeys.KeyPair) (string, error) {
}
// DecodeClusterClaims tries to parse cluster claims from a JWT string
// Deprecated: ClusterClaims are not supported
func DecodeClusterClaims(token string) (*ClusterClaims, error) {
v := ClusterClaims{}
if err := Decode(token, &v); err != nil {

View File

@ -1,3 +1,18 @@
/*
* Copyright 2019-2020 The NATS Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jwt
import (

View File

@ -71,13 +71,14 @@ func (sl *ServiceLatency) Validate(vr *ValidationResults) {
// Export represents a single export
type Export struct {
Name string `json:"name,omitempty"`
Subject Subject `json:"subject,omitempty"`
Type ExportType `json:"type,omitempty"`
TokenReq bool `json:"token_req,omitempty"`
Revocations RevocationList `json:"revocations,omitempty"`
ResponseType ResponseType `json:"response_type,omitempty"`
Latency *ServiceLatency `json:"service_latency,omitempty"`
Name string `json:"name,omitempty"`
Subject Subject `json:"subject,omitempty"`
Type ExportType `json:"type,omitempty"`
TokenReq bool `json:"token_req,omitempty"`
Revocations RevocationList `json:"revocations,omitempty"`
ResponseType ResponseType `json:"response_type,omitempty"`
Latency *ServiceLatency `json:"service_latency,omitempty"`
AccountTokenPosition uint `json:"account_token_position,omitempty"`
}
// IsService returns true if an export is for a service
@ -108,6 +109,10 @@ func (e *Export) IsStreamResponse() bool {
// Validate appends validation issues to the passed in results list
func (e *Export) Validate(vr *ValidationResults) {
if e == nil {
vr.AddError("null export is not allowed")
return
}
if !e.IsService() && !e.IsStream() {
vr.AddError("invalid export type: %q", e.Type)
}
@ -146,16 +151,16 @@ func (e *Export) ClearRevocation(pubKey string) {
e.Revocations.ClearRevocation(pubKey)
}
// IsRevokedAt checks if the public key is in the revoked list with a timestamp later than
// the one passed in. Generally this method is called with time.Now() but other time's can
// be used for testing.
// IsRevokedAt checks if the public key is in the revoked list with a timestamp later than the one passed in.
// Generally this method is called with the subject and issue time of the jwt to be tested.
// DO NOT pass time.Now(), it will not produce a stable/expected response.
func (e *Export) IsRevokedAt(pubKey string, timestamp time.Time) bool {
return e.Revocations.IsRevoked(pubKey, timestamp)
}
// IsRevoked checks if the public key is in the revoked list with time.Now()
func (e *Export) IsRevoked(pubKey string) bool {
return e.Revocations.IsRevoked(pubKey, time.Now())
// IsRevoked does not perform a valid check. Use IsRevokedAt instead.
func (e *Export) IsRevoked(_ string) bool {
return true
}
// Exports is a slice of exports
@ -199,6 +204,10 @@ func (e *Exports) Validate(vr *ValidationResults) error {
var streamSubjects []Subject
for _, v := range *e {
if v == nil {
vr.AddError("null export is not allowed")
continue
}
if v.IsService() {
serviceSubjects = append(serviceSubjects, v.Subject)
} else {

View File

@ -1,3 +1,5 @@
module github.com/nats-io/jwt
require github.com/nats-io/nkeys v0.1.3
require github.com/nats-io/nkeys v0.2.0
go 1.14

View File

@ -1,8 +1,8 @@
github.com/nats-io/nkeys v0.1.3 h1:6JrEfig+HzTH85yxzhSVbjHRJv9cn0p6n3IngIcM5/k=
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.2.0 h1:WXKF7diOaPU9cJdLD7nuzwasQy9vT1tBqzXZZf3AMJM=
github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM=
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@ -23,7 +23,7 @@ import (
const (
// Version is semantic version.
Version = "0.3.2"
Version = "1.2.2"
// TokenTypeJwt is the JWT token type supported JWT tokens
// encoded and decoded by this library
@ -64,7 +64,10 @@ func (h *Header) Valid() error {
return fmt.Errorf("not supported type %q", h.Type)
}
if AlgorithmNkey != strings.ToLower(h.Algorithm) {
if alg := strings.ToLower(h.Algorithm); alg != AlgorithmNkey {
if alg == "ed25519-nkey" {
return fmt.Errorf("more recent jwt version")
}
return fmt.Errorf("unexpected %q algorithm", h.Algorithm)
}
return nil

View File

@ -53,6 +53,10 @@ func (i *Import) IsStream() bool {
// Validate checks if an import is valid for the wrapping account
func (i *Import) Validate(actPubKey string, vr *ValidationResults) {
if i == nil {
vr.AddError("null import is not allowed")
return
}
if !i.IsService() && !i.IsStream() {
vr.AddError("invalid import type: %q", i.Type)
}
@ -123,6 +127,10 @@ type Imports []*Import
func (i *Imports) Validate(acctPubKey string, vr *ValidationResults) {
toSet := make(map[Subject]bool, len(*i))
for _, v := range *i {
if v == nil {
vr.AddError("null import is not allowed")
continue
}
if v.Type == Service {
if _, ok := toSet[v.To]; ok {
vr.AddError("Duplicate To subjects for %q", v.To)

View File

@ -26,7 +26,7 @@ import (
// Operator specific claims
type Operator struct {
// Slice of real identies (like websites) that can be used to identify the operator.
// Slice of real identities (like websites) that can be used to identify the operator.
Identities []Identity `json:"identity,omitempty"`
// Slice of other operator NKeys that can be used to sign on behalf of the main
// operator identity.
@ -40,6 +40,8 @@ type Operator struct {
// A list of NATS urls (tls://host:port) where tools can connect to the server
// using proper credentials.
OperatorServiceURLs StringList `json:"operator_service_urls,omitempty"`
// Identity of the system account
SystemAccount string `json:"system_account,omitempty"`
}
// Validate checks the validity of the operators contents
@ -63,6 +65,11 @@ func (o *Operator) Validate(vr *ValidationResults) {
vr.AddError("%s is not an operator public key", k)
}
}
if o.SystemAccount != "" {
if !nkeys.IsValidPublicAccountKey(o.SystemAccount) {
vr.AddError("%s is not an account public key", o.SystemAccount)
}
}
}
func (o *Operator) validateAccountServerURL() error {
@ -112,15 +119,15 @@ func ValidateOperatorServiceURL(v string) error {
}
func (o *Operator) validateOperatorServiceURLs() []error {
var errors []error
var errs []error
for _, v := range o.OperatorServiceURLs {
if v != "" {
if err := ValidateOperatorServiceURL(v); err != nil {
errors = append(errors, err)
errs = append(errs, err)
}
}
}
return errors
return errs
}
// OperatorClaims define the data for an operator JWT

View File

@ -1,9 +1,26 @@
/*
* Copyright 2020 The NATS Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jwt
import (
"time"
)
const All = "*"
// RevocationList is used to store a mapping of public keys to unix timestamps
type RevocationList map[string]int64
@ -24,9 +41,19 @@ func (r RevocationList) ClearRevocation(pubKey string) {
}
// IsRevoked checks if the public key is in the revoked list with a timestamp later than
// the one passed in. Generally this method is called with time.Now() but other time's can
// the one passed in. Generally this method is called with an issue time but other time's can
// be used for testing.
func (r RevocationList) IsRevoked(pubKey string, timestamp time.Time) bool {
if r.allRevoked(timestamp) {
return true
}
ts, ok := r[pubKey]
return ok && ts > timestamp.Unix()
return ok && ts >= timestamp.Unix()
}
// allRevoked returns true if All is set and the timestamp is later or same as the
// one passed. This is called by IsRevoked.
func (r RevocationList) allRevoked(timestamp time.Time) bool {
ts, ok := r[All]
return ok && ts >= timestamp.Unix()
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2018 The NATS Authors
* Copyright 2018-2020 The NATS Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@ -21,7 +21,7 @@ import (
"github.com/nats-io/nkeys"
)
// Server defines the custom part of a server jwt
// Deprecated: ServerClaims are not supported
type Server struct {
Permissions
Cluster string `json:"cluster,omitempty"`
@ -34,13 +34,13 @@ func (s *Server) Validate(vr *ValidationResults) {
}
}
// ServerClaims defines the data in a server JWT
// Deprecated: ServerClaims are not supported
type ServerClaims struct {
ClaimsData
Server `json:"nats,omitempty"`
}
// NewServerClaims creates a new server JWT with the specified subject/public key
// Deprecated: ServerClaims are not supported
func NewServerClaims(subject string) *ServerClaims {
if subject == "" {
return nil
@ -59,7 +59,7 @@ func (s *ServerClaims) Encode(pair nkeys.KeyPair) (string, error) {
return s.ClaimsData.Encode(pair, s)
}
// DecodeServerClaims tries to parse server claims from a JWT string
// Deprecated: ServerClaims are not supported
func DecodeServerClaims(token string) (*ServerClaims, error) {
v := ServerClaims{}
if err := Decode(token, &v); err != nil {

View File

@ -25,12 +25,14 @@ import (
type User struct {
Permissions
Limits
BearerToken bool `json:"bearer_token,omitempty"`
}
// Validate checks the permissions and limits in a User jwt
func (u *User) Validate(vr *ValidationResults) {
u.Permissions.Validate(vr)
u.Limits.Validate(vr)
// When BearerToken is true server will ignore any nonce-signing verification
}
// UserClaims defines a user JWT
@ -97,3 +99,8 @@ func (u *UserClaims) Payload() interface{} {
func (u *UserClaims) String() string {
return u.ClaimsData.String(u)
}
// IsBearerToken returns true if nonce-signing requirements should be skipped
func (u *UserClaims) IsBearerToken() bool {
return u.BearerToken
}

View File

@ -105,3 +105,14 @@ func (v *ValidationResults) Errors() []error {
}
return errs
}
// Warnings returns only non blocking issues as strings
func (v *ValidationResults) Warnings() []string {
var errs []string
for _, v := range v.Issues {
if !v.Blocking {
errs = append(errs, v.Description)
}
}
return errs
}

View File

@ -1,8 +1,7 @@
language: go
sudo: false
go:
- 1.14.x
- 1.13.x
- 1.12.x
env:
- GO111MODULE=off
go_import_path: github.com/nats-io/nats.go
@ -21,4 +20,4 @@ before_script:
script:
- go test -i -race ./...
- go test -v -run=TestNoRace -p=1 ./...
- if [[ "$TRAVIS_GO_VERSION" =~ 1.13 ]]; then ./scripts/cov.sh TRAVIS; else go test -race -v -p=1 ./... --failfast; fi
- if [[ "$TRAVIS_GO_VERSION" =~ 1.14 ]]; then ./scripts/cov.sh TRAVIS; else go test -race -v -p=1 ./... --failfast; fi

View File

@ -20,7 +20,7 @@ When using or transitioning to Go modules support:
```bash
# Go client latest or explicit version
go get github.com/nats-io/nats.go/@latest
go get github.com/nats-io/nats.go/@v1.9.2
go get github.com/nats-io/nats.go/@v1.10.0
# For latest NATS Server, add /v2 at the end
go get github.com/nats-io/nats-server/v2
@ -325,6 +325,18 @@ nc, err := nats.Connect(servers)
// This example means 10 seconds total per backend.
nc, err = nats.Connect(servers, nats.MaxReconnects(5), nats.ReconnectWait(2 * time.Second))
// You can also add some jitter for the reconnection.
// This call will add up to 500 milliseconds for non TLS connections and 2 seconds for TLS connections.
// If not specified, the library defaults to 100 milliseconds and 1 second, respectively.
nc, err = nats.Connect(servers, nats.ReconnectJitter(500*time.Millisecond, 2*time.Second))
// You can also specify a custom reconnect delay handler. If set, the library will invoke it when it has tried
// all URLs in its list. The value returned will be used as the total sleep time, so add your own jitter.
// The library will pass the number of times it went through the whole list.
nc, err = nats.Connect(servers, nats.CustomReconnectDelay(func(attempts int) time.Duration {
return someBackoffFunction(attempts)
}))
// Optionally disable randomization of the server pool
nc, err = nats.Connect(servers, nats.DontRandomize())

View File

@ -1,4 +1,4 @@
// Copyright 2012-2019 The NATS Authors
// Copyright 2012-2020 The NATS Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
@ -45,19 +45,21 @@ import (
// Default Constants
const (
Version = "1.9.2"
DefaultURL = "nats://127.0.0.1:4222"
DefaultPort = 4222
DefaultMaxReconnect = 60
DefaultReconnectWait = 2 * time.Second
DefaultTimeout = 2 * time.Second
DefaultPingInterval = 2 * time.Minute
DefaultMaxPingOut = 2
DefaultMaxChanLen = 8192 // 8k
DefaultReconnectBufSize = 8 * 1024 * 1024 // 8MB
RequestChanLen = 8
DefaultDrainTimeout = 30 * time.Second
LangString = "go"
Version = "1.10.0"
DefaultURL = "nats://127.0.0.1:4222"
DefaultPort = 4222
DefaultMaxReconnect = 60
DefaultReconnectWait = 2 * time.Second
DefaultReconnectJitter = 100 * time.Millisecond
DefaultReconnectJitterTLS = time.Second
DefaultTimeout = 2 * time.Second
DefaultPingInterval = 2 * time.Minute
DefaultMaxPingOut = 2
DefaultMaxChanLen = 8192 // 8k
DefaultReconnectBufSize = 8 * 1024 * 1024 // 8MB
RequestChanLen = 8
DefaultDrainTimeout = 30 * time.Second
LangString = "go"
)
const (
@ -116,6 +118,8 @@ var (
ErrTokenAlreadySet = errors.New("nats: token and token handler both set")
ErrMsgNotBound = errors.New("nats: message is not bound to subscription/connection")
ErrMsgNoReply = errors.New("nats: message does not have a reply")
ErrClientIPNotSupported = errors.New("nats: client IP not supported by this server")
ErrDisconnected = errors.New("nats: server is disconnected")
)
func init() {
@ -125,15 +129,17 @@ func init() {
// GetDefaultOptions returns default configuration options for the client.
func GetDefaultOptions() Options {
return Options{
AllowReconnect: true,
MaxReconnect: DefaultMaxReconnect,
ReconnectWait: DefaultReconnectWait,
Timeout: DefaultTimeout,
PingInterval: DefaultPingInterval,
MaxPingsOut: DefaultMaxPingOut,
SubChanLen: DefaultMaxChanLen,
ReconnectBufSize: DefaultReconnectBufSize,
DrainTimeout: DefaultDrainTimeout,
AllowReconnect: true,
MaxReconnect: DefaultMaxReconnect,
ReconnectWait: DefaultReconnectWait,
ReconnectJitter: DefaultReconnectJitter,
ReconnectJitterTLS: DefaultReconnectJitterTLS,
Timeout: DefaultTimeout,
PingInterval: DefaultPingInterval,
MaxPingsOut: DefaultMaxPingOut,
SubChanLen: DefaultMaxChanLen,
ReconnectBufSize: DefaultReconnectBufSize,
DrainTimeout: DefaultDrainTimeout,
}
}
@ -180,6 +186,12 @@ type SignatureHandler func([]byte) ([]byte, error)
// AuthTokenHandler is used to generate a new token.
type AuthTokenHandler func() string
// ReconnectDelayHandler is used to get from the user the desired
// delay the library should pause before attempting to reconnect
// again. Note that this is invoked after the library tried the
// whole list of URLs and failed to reconnect.
type ReconnectDelayHandler func(attempts int) time.Duration
// asyncCB is used to preserve order for async callbacks.
type asyncCB struct {
f func()
@ -256,6 +268,24 @@ type Options struct {
// to a server that we were already connected to previously.
ReconnectWait time.Duration
// CustomReconnectDelayCB is invoked after the library tried every
// URL in the server list and failed to reconnect. It passes to the
// user the current number of attempts. This function returns the
// amount of time the library will sleep before attempting to reconnect
// again. It is strongly recommended that this value contains some
// jitter to prevent all connections to attempt reconnecting at the same time.
CustomReconnectDelayCB ReconnectDelayHandler
// ReconnectJitter sets the upper bound for a random delay added to
// ReconnectWait during a reconnect when no TLS is used.
// Note that any jitter is capped with ReconnectJitterMax.
ReconnectJitter time.Duration
// ReconnectJitterTLS sets the upper bound for a random delay added to
// ReconnectWait during a reconnect when TLS is used.
// Note that any jitter is capped with ReconnectJitterMax.
ReconnectJitterTLS time.Duration
// Timeout sets the timeout for a Dial operation on a connection.
Timeout time.Duration
@ -409,6 +439,7 @@ type Conn struct {
ptmr *time.Timer
pout int
ar bool // abort reconnect
rqch chan struct{}
// New style response handler
respSub string // The wildcard subject
@ -486,17 +517,16 @@ type Statistics struct {
// Tracks individual backend servers.
type srv struct {
url *url.URL
didConnect bool
reconnects int
lastAttempt time.Time
lastErr error
isImplicit bool
tlsName string
url *url.URL
didConnect bool
reconnects int
lastErr error
isImplicit bool
tlsName string
}
type serverInfo struct {
Id string `json:"server_id"`
ID string `json:"server_id"`
Host string `json:"host"`
Port uint `json:"port"`
Version string `json:"version"`
@ -506,6 +536,7 @@ type serverInfo struct {
ConnectURLs []string `json:"connect_urls,omitempty"`
Proto int `json:"proto,omitempty"`
CID uint64 `json:"client_id,omitempty"`
ClientIP string `json:"client_ip,omitempty"`
Nonce string `json:"nonce,omitempty"`
}
@ -669,6 +700,24 @@ func MaxReconnects(max int) Option {
}
}
// ReconnectJitter is an Option to set the upper bound of a random delay added ReconnectWait.
func ReconnectJitter(jitter, jitterForTLS time.Duration) Option {
return func(o *Options) error {
o.ReconnectJitter = jitter
o.ReconnectJitterTLS = jitterForTLS
return nil
}
}
// CustomReconnectDelay is an Option to set the CustomReconnectDelayCB option.
// See CustomReconnectDelayCB Option for more details.
func CustomReconnectDelay(cb ReconnectDelayHandler) Option {
return func(o *Options) error {
o.CustomReconnectDelayCB = cb
return nil
}
}
// PingInterval is an Option to set the period for client ping commands.
func PingInterval(t time.Duration) Option {
return func(o *Options) error {
@ -1123,7 +1172,7 @@ func (nc *Conn) setupServerPool() error {
// Randomize if allowed to
if !nc.Opts.NoRandomize {
nc.shufflePool()
nc.shufflePool(0)
}
// Normally, if this one is set, Options.Servers should not be,
@ -1220,14 +1269,16 @@ func (nc *Conn) addURLToPool(sURL string, implicit, saveTLSName bool) error {
}
// shufflePool swaps randomly elements in the server pool
func (nc *Conn) shufflePool() {
if len(nc.srvPool) <= 1 {
// The `offset` value indicates that the shuffling should start at
// this offset and leave the elements from [0..offset) intact.
func (nc *Conn) shufflePool(offset int) {
if len(nc.srvPool) <= offset+1 {
return
}
source := rand.NewSource(time.Now().UnixNano())
r := rand.New(source)
for i := range nc.srvPool {
j := r.Intn(i + 1)
for i := offset; i < len(nc.srvPool); i++ {
j := offset + r.Intn(i+1-offset)
nc.srvPool[i], nc.srvPool[j] = nc.srvPool[j], nc.srvPool[i]
}
}
@ -1249,8 +1300,6 @@ func (nc *Conn) createConn() (err error) {
}
if _, cur := nc.currentServer(); cur == nil {
return ErrNoServers
} else {
cur.lastAttempt = time.Now()
}
// We will auto-expand host names if they resolve to multiple IPs
@ -1384,7 +1433,7 @@ func (nc *Conn) ConnectedServerId() string {
if nc.status != CONNECTED {
return _EMPTY_
}
return nc.info.Id
return nc.info.ID
}
// Low level setup for structs, etc
@ -1393,6 +1442,7 @@ func (nc *Conn) setup() {
nc.pongs = make([]chan struct{}, 0, 8)
nc.fch = make(chan struct{}, flushChanSize)
nc.rqch = make(chan struct{})
// Setup scratch outbound buffer for PUB
pub := nc.scratch[:len(_PUB_P_)]
@ -1450,6 +1500,7 @@ func (nc *Conn) connect() error {
// For first connect we walk all servers in the pool and try
// to connect immediately.
nc.mu.Lock()
defer nc.mu.Unlock()
nc.initc = true
// The pool may change inside the loop iteration due to INFO protocol.
for i := 0; i < len(nc.srvPool); i++ {
@ -1463,8 +1514,8 @@ func (nc *Conn) connect() error {
err = nc.processConnectInit()
if err == nil {
nc.srvPool[i].didConnect = true
nc.srvPool[i].reconnects = 0
nc.current.didConnect = true
nc.current.reconnects = 0
nc.current.lastErr = nil
returnedErr = nil
break
@ -1487,7 +1538,7 @@ func (nc *Conn) connect() error {
if returnedErr == nil && nc.status != CONNECTED {
returnedErr = ErrNoServers
}
nc.mu.Unlock()
return returnedErr
}
@ -1814,33 +1865,63 @@ func (nc *Conn) doReconnect(err error) {
// This is used to wait on go routines exit if we start them in the loop
// but an error occurs after that.
waitForGoRoutines := false
var rt *time.Timer
// Channel used to kick routine out of sleep when conn is closed.
rqch := nc.rqch
// Counter that is increased when the whole list of servers has been tried.
var wlf int
for len(nc.srvPool) > 0 {
var jitter time.Duration
var rw time.Duration
// If a custom reconnect delay handler is set, this takes precedence.
crd := nc.Opts.CustomReconnectDelayCB
if crd == nil {
rw = nc.Opts.ReconnectWait
// TODO: since we sleep only after the whole list has been tried, we can't
// rely on individual *srv to know if it is a TLS or non-TLS url.
// We have to pick which type of jitter to use, for now, we use these hints:
jitter = nc.Opts.ReconnectJitter
if nc.Opts.Secure || nc.Opts.TLSConfig != nil {
jitter = nc.Opts.ReconnectJitterTLS
}
}
for i := 0; len(nc.srvPool) > 0; {
cur, err := nc.selectNextServer()
if err != nil {
nc.err = err
break
}
sleepTime := int64(0)
// Sleep appropriate amount of time before the
// connection attempt if connecting to same server
// we just got disconnected from..
if time.Since(cur.lastAttempt) < nc.Opts.ReconnectWait {
sleepTime = int64(nc.Opts.ReconnectWait - time.Since(cur.lastAttempt))
}
// On Windows, createConn() will take more than a second when no
// server is running at that address. So it could be that the
// time elapsed between reconnect attempts is always > than
// the set option. Release the lock to give a chance to a parallel
// nc.Close() to break the loop.
doSleep := i+1 >= len(nc.srvPool)
nc.mu.Unlock()
if sleepTime <= 0 {
if !doSleep {
i++
// Release the lock to give a chance to a concurrent nc.Close() to break the loop.
runtime.Gosched()
} else {
time.Sleep(time.Duration(sleepTime))
i = 0
var st time.Duration
if crd != nil {
wlf++
st = crd(wlf)
} else {
st = rw
if jitter > 0 {
st += time.Duration(rand.Int63n(int64(jitter)))
}
}
if rt == nil {
rt = time.NewTimer(st)
} else {
rt.Reset(st)
}
select {
case <-rqch:
rt.Stop()
case <-rt.C:
}
}
// If the readLoop, etc.. go routines were started, wait for them to complete.
if waitForGoRoutines {
@ -2427,8 +2508,14 @@ func (nc *Conn) processInfo(info string) error {
}
nc.addURLToPool(fmt.Sprintf("%s://%s", nc.connScheme(), curl), true, saveTLS)
}
if hasNew && !nc.initc && nc.Opts.DiscoveredServersCB != nil {
nc.ach.push(func() { nc.Opts.DiscoveredServersCB(nc) })
if hasNew {
// Randomize the pool if allowed but leave the first URL in place.
if !nc.Opts.NoRandomize {
nc.shufflePool(1)
}
if !nc.initc && nc.Opts.DiscoveredServersCB != nil {
nc.ach.push(func() { nc.Opts.DiscoveredServersCB(nc) })
}
}
return nil
@ -2748,7 +2835,7 @@ func (nc *Conn) oldRequest(subj string, data []byte, timeout time.Duration) (*Ms
inbox := NewInbox()
ch := make(chan *Msg, RequestChanLen)
s, err := nc.subscribe(inbox, _EMPTY_, nil, ch, false)
s, err := nc.subscribe(inbox, _EMPTY_, nil, ch, true)
if err != nil {
return nil, err
}
@ -3541,10 +3628,25 @@ func (nc *Conn) FlushTimeout(timeout time.Duration) (err error) {
return
}
// RTT calculates the round trip time between this client and the server.
func (nc *Conn) RTT() (time.Duration, error) {
if nc.IsClosed() {
return 0, ErrConnectionClosed
}
if nc.IsReconnecting() {
return 0, ErrDisconnected
}
start := time.Now()
if err := nc.FlushTimeout(10 * time.Second); err != nil {
return 0, err
}
return time.Since(start), nil
}
// Flush will perform a round trip to the server and return when it
// receives the internal reply.
func (nc *Conn) Flush() error {
return nc.FlushTimeout(60 * time.Second)
return nc.FlushTimeout(10 * time.Second)
}
// Buffered will return the number of bytes buffered to be sent to the server.
@ -3636,9 +3738,13 @@ func (nc *Conn) close(status Status, doCBs bool, err error) {
// Kick the Go routines so they fall out.
nc.kickFlusher()
nc.mu.Unlock()
nc.mu.Lock()
// If the reconnect timer is waiting between a reconnect attempt,
// this will kick it out.
if nc.rqch != nil {
close(nc.rqch)
nc.rqch = nil
}
// Clear any queued pongs, e.g. pending flush calls.
nc.clearPendingFlushCalls()
@ -4005,10 +4111,25 @@ func (nc *Conn) Barrier(f func()) error {
return nil
}
// GetClientIP returns the client IP as known by the server.
// Supported as of server version 2.1.6.
func (nc *Conn) GetClientIP() (net.IP, error) {
nc.mu.RLock()
defer nc.mu.RUnlock()
if nc.isClosed() {
return nil, ErrConnectionClosed
}
if nc.info.ClientIP == "" {
return nil, ErrClientIPNotSupported
}
ip := net.ParseIP(nc.info.ClientIP)
return ip, nil
}
// GetClientID returns the client ID assigned by the server to which
// the client is currently connected to. Note that the value may change if
// the client reconnects.
// This function returns ErrNoClientIDReturned if the server is of a
// This function returns ErrClientIDNotSupported if the server is of a
// version prior to 1.2.0.
func (nc *Conn) GetClientID() (uint64, error) {
nc.mu.RLock()

View File

@ -24,7 +24,7 @@ type msgArg struct {
size int
}
const MAX_CONTROL_LINE_SIZE = 1024
const MAX_CONTROL_LINE_SIZE = 4096
type parseState struct {
state int

View File

@ -1,8 +1,8 @@
language: go
sudo: false
go:
- 1.12.x
- 1.11.x
- 1.14.x
- 1.13.x
install:
- go get -t ./...
@ -28,4 +28,4 @@ script:
# script: curl -sL http://git.io/goreleaser | bash
# on:
# tags: true
# condition: $TRAVIS_OS_NAME = linux
# condition: $TRAVIS_OS_NAME = linux

View File

@ -17,7 +17,7 @@ Ed25519 is fast and resistant to side channel attacks. Generation of a seed key
The NATS system will utilize Ed25519 keys, meaning that NATS systems will never store or even have access to any private keys. Authentication will utilize a random challenge response mechanism.
Dealing with 32 byte and 64 byte raw keys can be challenging. NKEYS is designed to formulate keys in a much friendlier fashion and references work done in cryptocurrencies, specifically [Stellar](https://www.stellar.org/). Bitcoin and others used a form of Base58 (or Base58Check) to endode raw keys. Stellar utilized a more traditonal Base32 with a CRC16 and a version or prefix byte. NKEYS utilizes a similar format where the prefix will be 1 byte for public and private keys and will be 2 bytes for seeds. The base32 encoding of these prefixes will yield friendly human readbable prefixes, e.g. '**N**' = server, '**C**' = cluster, '**O**' = operator, '**A**' = account, and '**U**' = user. '**P**' is used for private keys. For seeds, the first encoded prefix is '**S**', and the second character will be the type for the public key, e.g. "**SU**" is a seed for a user key pair, "**SA**" is a seed for an account key pair.
Dealing with 32 byte and 64 byte raw keys can be challenging. NKEYS is designed to formulate keys in a much friendlier fashion and references work done in cryptocurrencies, specifically [Stellar](https://www.stellar.org/). Bitcoin and others used a form of Base58 (or Base58Check) to encode raw keys. Stellar utilized a more traditional Base32 with a CRC16 and a version or prefix byte. NKEYS utilizes a similar format where the prefix will be 1 byte for public and private keys and will be 2 bytes for seeds. The base32 encoding of these prefixes will yield friendly human readable prefixes, e.g. '**N**' = server, '**C**' = cluster, '**O**' = operator, '**A**' = account, and '**U**' = user. '**P**' is used for private keys. For seeds, the first encoded prefix is '**S**', and the second character will be the type for the public key, e.g. "**SU**" is a seed for a user key pair, "**SA**" is a seed for an account key pair.
## Installation
@ -69,4 +69,4 @@ Unless otherwise noted, the NATS source files are distributed
under the Apache Version 2.0 license found in the LICENSE file.
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fnats-io%2Fnkeys.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fnats-io%2Fnkeys?ref=badge_large)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fnats-io%2Fnkeys.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fnats-io%2Fnkeys?ref=badge_large)

78
gateway/vendor/github.com/nats-io/nkeys/creds_utils.go generated vendored Normal file
View File

@ -0,0 +1,78 @@
package nkeys
import (
"bytes"
"errors"
"regexp"
)
var userConfigRE = regexp.MustCompile(`\s*(?:(?:[-]{3,}.*[-]{3,}\r?\n)([\w\-.=]+)(?:\r?\n[-]{3,}.*[-]{3,}\r?\n))`)
// ParseDecoratedJWT takes a creds file and returns the JWT portion.
func ParseDecoratedJWT(contents []byte) (string, error) {
items := userConfigRE.FindAllSubmatch(contents, -1)
if len(items) == 0 {
return string(contents), nil
}
// First result should be the user JWT.
// We copy here so that if the file contained a seed file too we wipe appropriately.
raw := items[0][1]
tmp := make([]byte, len(raw))
copy(tmp, raw)
return string(tmp), nil
}
// ParseDecoratedNKey takes a creds file, finds the NKey portion and creates a
// key pair from it.
func ParseDecoratedNKey(contents []byte) (KeyPair, error) {
var seed []byte
items := userConfigRE.FindAllSubmatch(contents, -1)
if len(items) > 1 {
seed = items[1][1]
} else {
lines := bytes.Split(contents, []byte("\n"))
for _, line := range lines {
if bytes.HasPrefix(bytes.TrimSpace(line), []byte("SO")) ||
bytes.HasPrefix(bytes.TrimSpace(line), []byte("SA")) ||
bytes.HasPrefix(bytes.TrimSpace(line), []byte("SU")) {
seed = line
break
}
}
}
if seed == nil {
return nil, errors.New("no nkey seed found")
}
if !bytes.HasPrefix(seed, []byte("SO")) &&
!bytes.HasPrefix(seed, []byte("SA")) &&
!bytes.HasPrefix(seed, []byte("SU")) {
return nil, errors.New("doesn't contain a seed nkey")
}
kp, err := FromSeed(seed)
if err != nil {
return nil, err
}
return kp, nil
}
// ParseDecoratedUserNKey takes a creds file, finds the NKey portion and creates a
// key pair from it. Similar to ParseDecoratedNKey but fails for non-user keys.
func ParseDecoratedUserNKey(contents []byte) (KeyPair, error) {
nk, err := ParseDecoratedNKey(contents)
if err != nil {
return nil, err
}
seed, err := nk.Seed()
if err != nil {
return nil, err
}
if !bytes.HasPrefix(seed, []byte("SU")) {
return nil, errors.New("doesn't contain an user seed nkey")
}
kp, err := FromSeed(seed)
if err != nil {
return nil, err
}
return kp, nil
}

View File

@ -1,3 +1,3 @@
module github.com/nats-io/nkeys
require golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
require golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59

View File

@ -1,6 +1,6 @@
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM=
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@ -19,8 +19,8 @@ import (
"errors"
)
// Version
const Version = "0.1.0"
// Version is our current version
const Version = "0.2.0"
// Errors
var (
@ -33,6 +33,7 @@ var (
ErrInvalidSignature = errors.New("nkeys: signature verification failed")
ErrCannotSign = errors.New("nkeys: can not sign, no private key available")
ErrPublicKeyOnly = errors.New("nkeys: no seed or private key available")
ErrIncompatibleKey = errors.New("nkeys: incompatible key")
)
// KeyPair provides the central interface to nkeys.
@ -93,7 +94,7 @@ func FromSeed(seed []byte) (KeyPair, error) {
return &kp{copy}, nil
}
// Create a KeyPair from the raw 32 byte seed for a given type.
// FromRawSeed will create a KeyPair from the raw 32 byte seed for a given type.
func FromRawSeed(prefix PrefixByte, rawSeed []byte) (KeyPair, error) {
seed, err := EncodeSeed(prefix, rawSeed)
if err != nil {

View File

@ -17,7 +17,6 @@ import (
"bytes"
"encoding/base32"
"encoding/binary"
"golang.org/x/crypto/ed25519"
)
@ -47,7 +46,7 @@ const (
PrefixByteUser PrefixByte = 20 << 3 // Base32-encodes to 'U...'
// PrefixByteUnknown is for unknown prefixes.
PrefixByteUknown PrefixByte = 23 << 3 // Base32-encodes to 'X...'
PrefixByteUnknown PrefixByte = 23 << 3 // Base32-encodes to 'X...'
)
// Set our encoding to not include padding '=='
@ -188,10 +187,11 @@ func DecodeSeed(src []byte) (PrefixByte, []byte, error) {
return PrefixByte(b2), raw[2:], nil
}
// Prefix returns PrefixBytes of its input
func Prefix(src string) PrefixByte {
b, err := decode([]byte(src))
if err != nil {
return PrefixByteUknown
return PrefixByteUnknown
}
prefix := PrefixByte(b[0])
err = checkValidPrefixByte(prefix)
@ -203,7 +203,7 @@ func Prefix(src string) PrefixByte {
if PrefixByte(b1) == PrefixByteSeed {
return PrefixByteSeed
}
return PrefixByteUknown
return PrefixByteUnknown
}
// IsValidPublicKey will decode and verify that the string is a valid encoded public key.
@ -288,3 +288,19 @@ func (p PrefixByte) String() string {
}
return "unknown"
}
// CompatibleKeyPair returns an error if the KeyPair doesn't match expected PrefixByte(s)
func CompatibleKeyPair(kp KeyPair, expected ...PrefixByte) error {
pk, err := kp.PublicKey()
if err != nil {
return err
}
pkType := Prefix(pk)
for _, k := range expected {
if pkType == k {
return nil
}
}
return ErrIncompatibleKey
}

View File

@ -1,14 +1,9 @@
language: go
sudo: false
go:
- 1.12.x
- 1.13.x
env:
- GO111MODULE=off
- 1.15.x
- 1.14.x
go_import_path: github.com/nats-io/stan.go
install:
- go get -t -v ./...
- go get github.com/nats-io/nats-streaming-server
- go get -u honnef.co/go/tools/cmd/staticcheck
- go get -u github.com/client9/misspell/cmd/misspell
before_script:
@ -17,7 +12,6 @@ before_script:
- find . -type f -name "*.go" | grep -v "/pb/" | xargs misspell -error -locale US
- staticcheck ./...
script:
- go test -i -v ./...
- go test -v -race ./...
- go test -v -race . -modfile go_tests.mod
after_success:
- if [[ "$TRAVIS_GO_VERSION" =~ 1.13 ]]; then ./scripts/cov.sh TRAVIS; fi
- if [[ "$TRAVIS_GO_VERSION" =~ 1.15 ]]; then ./scripts/cov.sh TRAVIS; fi

View File

@ -2,11 +2,9 @@
Maintainership is on a per project basis.
### Core-maintainers
### Maintainers
- Derek Collison <derek@nats.io> [@derekcollison](https://github.com/derekcollison)
- Ivan Kozlovic <ivan@nats.io> [@kozlovic](https://github.com/kozlovic)
### Maintainers
- Alberto Ricart <alberto@nats.io> [@aricart](https://github.com/aricart)
- Colin Sullivan <colin@nats.io> [@ColinSullivan1](https://github.com/ColinSullivan1)
- Waldemar Quevedo <wally@nats.io> [@wallyqs](https://github.com/wallyqs)

View File

@ -3,7 +3,7 @@
NATS Streaming is an extremely performant, lightweight reliable streaming platform powered by [NATS](https://nats.io).
[![License Apache 2](https://img.shields.io/badge/License-Apache2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
[![Build Status](https://travis-ci.org/nats-io/stan.go.svg?branch=master)](http://travis-ci.org/nats-io/stan.go)
[![Build Status](https://travis-ci.com/nats-io/stan.go.svg?branch=master)](https://travis-ci.com/github/nats-io/stan.go)
[![Coverage Status](https://coveralls.io/repos/nats-io/stan.go/badge.svg?branch=master)](https://coveralls.io/r/nats-io/stan.go?branch=master)
[![GoDoc](https://godoc.org/github.com/nats-io/stan.go?status.svg)](http://godoc.org/github.com/nats-io/stan.go)
@ -30,9 +30,28 @@ When using or transitioning to Go modules support:
```bash
# Go client latest or explicit version
go get github.com/nats-io/stan.go/@latest
go get github.com/nats-io/stan.go/@v0.6.0
go get github.com/nats-io/stan.go/@v0.7.0
```
## Important things to know about reconnections.
A common misunderstanding from users moving from NATS to NATS Streaming has to do with how reconnection works.
It is important to understand how NATS Streaming relates to NATS "core". You can find some information in [NATS Streaming Concepts/Relation to NATS](https://github.com/nats-io/nats.docs/blob/master/nats-streaming-concepts/relation-to-nats.md).
The NATS Streaming library uses the NATS library to connect to a NATS Server and indirectly communicates with the NATS Streaming "server". To better understand the issues, you should assume that the server has no direct connection with the client, and the client may possibly never lose its TCP connection to a NATS Server and yet may not have access to a streaming server (streaming client connected to a NATS Server, that is cluster to another, to which the NATS Streaming "server" is connected to).
When the low-level NATS TCP connection is broken, the reconnection logic triggers in the core NATS library. Once the connection is re-established, the low level NATS subscriptions used by the Streaming library to communicate with the streaming servers will be resent. All of that activity could have happened and the Streaming server would not know (see topology example described above). But from the server that is not a problem, after all, if a message is delivered while the client is disconnected, the server won't receive an ACK and will redeliver that message after the AckWait interval.
At this point, it is worth noting that a frequent mistake made by new users is to run the NATS Streaming server with memory store (the default if no persistence mode is specified) and after the server is restarted, and the client "reconnects" fine, the application stops receiving messages and/or gets errors on publish. The note in [NATS Streaming Concepts/Client Connections](https://docs.nats.io/nats-streaming-concepts/client-connections) will detail what is happening in this case.
To maintain the streaming connection (a better name may have been "session"), both server and clients send heartbeats/PINGs. If the server misses a configured amount of heartbeats from the client, it will close the connection, which also means deleting all non-durable subscriptions. If the client was "network partitioned" from the server when that happened, even after the partition is resolved, the client would not know what happened. Again, to understand how that is possible, see the topology example above: the network partition happened between the two clustered NATS Servers, and no TCP connection between the streaming client and/or streaming server was ever lost.
To solve that, the client sends PINGs to the server, and if missing enough of them, will close the connection and report it as lost through the ConnectionLost handler. See [Connection Status](#connection-status) for more details. In the case of the network partition example above, even if the client's number of PINGs has not reached its maximum count when the partition is resolved, the server will respond with an error to the next PING going through because it will detect that this specific client instance has been closed due to timeouts.
When that point is reached, the connection **and its subscriptions** are no longer valid and need to be recreated by the user.
The client-to-server PINGs are by default set to pretty aggressive values and should likely be increased in a normal setup. That is, with the default values, the client would not tolerate a server being down/not responding for only 15 seconds or so. Users should adjust the `Pings()` option, deciding how long they are willing to have their application not able to communicate with a server without "knowing", versus declaring the connection lost too soon (and having to recreate the state: connection and all subscriptions).
## Basic Usage
```go
@ -294,10 +313,10 @@ Here is how you would specify your own PING values and the callback:
// Send PINGs every 10 seconds, and fail after 5 PINGs without any response.
sc, err := stan.Connect(clusterName, clientName,
stan.Pings(10, 5),
stan.Pings(10, 5),
stan.SetConnectionLostHandler(func(_ stan.Conn, reason error) {
log.Fatalf("Connection lost, reason: %v", reason)
}))
}))
```
Note that the only way to be notified is to set the callback. If the callback is not set, PINGs are still sent and the connection

View File

@ -0,0 +1,24 @@
# External Dependencies
This file lists the dependencies used in this repository.
| Dependency | License |
|-|-|
| Go | BSD 3-Clause "New" or "Revised" License |
| github.com/nats-io/stan.go | Apache License 2.0 |
| github.com/gogo/protobuf v1.3.2 | Go |
| github.com/kisielk/errcheck v1.5.0 | MIT |
| github.com/kisielk/gotool v1.0.0 | MIT |
| github.com/nats-io/jwt v0.3.2 | Apache License 2.0 |
| github.com/nats-io/nats.go v1.10.0 | Apache License 2.0 |
| github.com/nats-io/nkeys v0.1.4 | Apache License 2.0 |
| github.com/nats-io/nuid v1.0.1 | Apache License 2.0 |
| github.com/yuin/goldmark v1.2.1 | MIT |
| golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 | BSD 3-Clause "New" or "Revised" License |
| golang.org/x/mod v0.3.0 | BSD 3-Clause "New" or "Revised" License |
| golang.org/x/net v0.0.0-20201021035429-f5854403a974 | BSD 3-Clause "New" or "Revised" License |
| golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 | BSD 3-Clause "New" or "Revised" License |
| golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f | BSD 3-Clause "New" or "Revised" License |
| golang.org/x/text v0.3.3 | BSD 3-Clause "New" or "Revised" License |
| golang.org/x/tools v0.0.0-20210106214847-113979e3529a | BSD 3-Clause "New" or "Revised" License |
| golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 | BSD 3-Clause "New" or "Revised" License |

View File

@ -1,7 +1,9 @@
module github.com/nats-io/stan.go
go 1.14
require (
github.com/gogo/protobuf v1.2.1
github.com/nats-io/nats.go v1.9.1
github.com/gogo/protobuf v1.3.2
github.com/nats-io/nats.go v1.10.0
github.com/nats-io/nuid v1.0.1
)

View File

@ -1,20 +1,43 @@
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/nats-io/jwt v0.3.0 h1:xdnzwFETV++jNc4W1mw//qFyJGb2ABOombmZJQS4+Qo=
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
github.com/nats-io/nats.go v1.9.1 h1:ik3HbLhZ0YABLto7iX80pZLPw/6dx3T+++MZJwLnMrQ=
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
github.com/nats-io/nkeys v0.1.0 h1:qMd4+pRHgdr1nAClu+2h/2a5F2TmKcCzjCDazVgRoX4=
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/jwt v0.3.2 h1:+RB5hMpXUUA2dfxuhBTEkMOrYmM+gKIZYS1KjSostMI=
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
github.com/nats-io/nats.go v1.10.0 h1:L8qnKaofSfNFbXg0C5F71LdjPRnmQwSsA4ukmkt1TvY=
github.com/nats-io/nats.go v1.10.0/go.mod h1:AjGArbfyR50+afOUotNX2Xs5SYHf+CoOa5HH1eEl2HE=
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.1.4 h1:aEsHIssIk6ETN5m2/MD8Y4B2X7FfXrBAUdkyRvbVYzA=
github.com/nats-io/nkeys v0.1.4/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

11
gateway/vendor/github.com/nats-io/stan.go/go_tests.mod generated vendored Normal file
View File

@ -0,0 +1,11 @@
module github.com/nats-io/stan.go
go 1.14
require (
github.com/gogo/protobuf v1.3.2
github.com/nats-io/nats-server/v2 v2.1.9
github.com/nats-io/nats-streaming-server v0.20.0
github.com/nats-io/nats.go v1.10.0
github.com/nats-io/nuid v1.0.1
)

130
gateway/vendor/github.com/nats-io/stan.go/go_tests.sum generated vendored Normal file
View File

@ -0,0 +1,130 @@
github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878 h1:EFSB7Zo9Eg91v7MJPVsifUysc/wPdN+NOnVe6bWbdBM=
github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-hclog v0.14.1 h1:nQcJDQwIAGnmoUWp8ubocEX40cCml/17YkF6csQLReU=
github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-msgpack v1.1.5 h1:9byZdVjKTe5mce63pRVNP1L7UAmdHOTEMGehn6KvJWs=
github.com/hashicorp/go-msgpack v1.1.5/go.mod h1:gWVc3sv/wbDmR3rQsj1CAktEZzoz1YNK9NfGLXJ69/4=
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/raft v1.2.0 h1:mHzHIrF0S91d3A7RPBvuqkgB4d/7oFJZyvf1Q4m7GA0=
github.com/hashicorp/raft v1.2.0/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8=
github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
github.com/nats-io/jwt v1.1.0 h1:+vOlgtM0ZsF46GbmUoadq0/2rChNS45gtxHEa3H1gqM=
github.com/nats-io/jwt v1.1.0/go.mod h1:n3cvmLfBfnpV4JJRN7lRYCyZnw48ksGsbThGXEk4w9M=
github.com/nats-io/nats-server/v2 v2.1.9 h1:Sxr2zpaapgpBT9ElTxTVe62W+qjnhPcKY/8W5cnA/Qk=
github.com/nats-io/nats-server/v2 v2.1.9/go.mod h1:9qVyoewoYXzG1ME9ox0HwkkzyYvnlBDugfR4Gg/8uHU=
github.com/nats-io/nats-streaming-server v0.20.0 h1:+kHFbUIWsEbjZHRCUsAr0Hq2oKszq4/9B208VycRTwQ=
github.com/nats-io/nats-streaming-server v0.20.0/go.mod h1:yJjUp4TmfYqllCtctAQ6Kz6ZRy5kaLgqHvuU1TGSrCw=
github.com/nats-io/nats.go v1.10.0 h1:L8qnKaofSfNFbXg0C5F71LdjPRnmQwSsA4ukmkt1TvY=
github.com/nats-io/nats.go v1.10.0/go.mod h1:AjGArbfyR50+afOUotNX2Xs5SYHf+CoOa5HH1eEl2HE=
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.1.4 h1:aEsHIssIk6ETN5m2/MD8Y4B2X7FfXrBAUdkyRvbVYzA=
github.com/nats-io/nkeys v0.1.4/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/nats-io/stan.go v0.8.1/go.mod h1:Ci6mUIpGQTjl++MqK2XzkWI/0vF+Bl72uScx7ejSYmU=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4=
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 h1:a/mKvvZr9Jcc8oKfcmgzyp7OwF73JPWsQLvH1z2Kxck=
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190424220101-1e8e1cfdf96b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=

File diff suppressed because it is too large Load Diff

View File

@ -49,7 +49,7 @@ message MsgProto {
string subject = 2; // subject
string reply = 3; // optional reply
bytes data = 4; // payload
int64 timestamp = 5; // received timestamp
int64 timestamp = 5; // received timestamp: Unix time (number of nanoseconds elapsed since January 1, 1970 UTC)
bool redelivered = 6; // Flag specifying if the message is being redelivered
uint32 redeliveryCount = 7; // Number of times the message has been redelivered (count currently not persisted)

View File

@ -1,4 +1,4 @@
// Copyright 2016-2019 The NATS Authors
// Copyright 2016-2020 The NATS Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
@ -26,7 +26,7 @@ import (
)
// Version is the NATS Streaming Go Client version
const Version = "0.6.0"
const Version = "0.8.2"
const (
// DefaultNatsURL is the default URL the client connects to
@ -43,7 +43,7 @@ const (
// DefaultPingInterval is the default interval (in seconds) at which a connection sends a PING to the server
DefaultPingInterval = 5
// DefaultPingMaxOut is the number of PINGs without a response before the connection is considered lost.
DefaultPingMaxOut = 3
DefaultPingMaxOut = 88
)
// Conn represents a connection to the NATS Streaming subsystem. It can Publish and
@ -174,7 +174,18 @@ type Options struct {
}
// GetDefaultOptions returns default configuration options for the client.
//
// Deprecated: do not use this from outside the library.
// This is intended to be used within the library; its visibility to clients is
// a design wart which we can't remove without breaking API compatibility.
// Instead, the Connect() function accepts Option parameters, each singular,
// which are the exposed interface.
func GetDefaultOptions() Options {
return getDefaultOptions()
}
// getDefaultOptions returns default configuration options for the client.
func getDefaultOptions() Options {
return Options{
NatsURL: DefaultNatsURL,
ConnectTimeout: DefaultConnectWait,
@ -186,11 +197,12 @@ func GetDefaultOptions() Options {
}
}
// DEPRECATED: Use GetDefaultOptions() instead.
// DEPRECATED: Use getDefaultOptions() instead in the library, neither in
// clients.
// DefaultOptions is not safe for use by multiple clients.
// For details see https://github.com/nats-io/nats.go/issues/308.
// DefaultOptions are the NATS Streaming client's default options
var DefaultOptions = GetDefaultOptions()
var DefaultOptions = getDefaultOptions()
// Option is a function on the options for a connection.
type Option func(*Options) error
@ -323,11 +335,13 @@ type ack struct {
// Connect will form a connection to the NATS Streaming subsystem.
// Note that clientID can contain only alphanumeric and `-` or `_` characters.
// The default options are those returned by GetDefaultOptions and each option
// specified in a parameter here overrides those defaults.
func Connect(stanClusterID, clientID string, options ...Option) (Conn, error) {
// Process Options
c := conn{
clientID: clientID,
opts: DefaultOptions,
opts: getDefaultOptions(),
connID: []byte(nuid.Next()),
pubNUID: nuid.New(),
pubAckMap: make(map[string]*ack),
@ -686,7 +700,8 @@ func (sc *conn) processAck(m *nats.Msg) {
pa := &pb.PubAck{}
err := pa.Unmarshal(m.Data)
if err != nil {
panic(fmt.Errorf("error during ack unmarshal: %v", err))
fmt.Printf("error during ack unmarshal: %v\n", err)
return
}
// Remove
@ -832,7 +847,8 @@ func (sc *conn) processMsg(raw *nats.Msg) {
msg := &Msg{}
err := msg.Unmarshal(raw.Data)
if err != nil {
panic(fmt.Errorf("error processing unmarshal for msg: %v", err))
fmt.Printf("error during message unmarshal: %v\n", err)
return
}
var sub *subscription
// Lookup the subscription