Files
golib/nats/client.go
Nicolas JUHEL 22b364593e Package certificates:
- rework package to allow convert config to model and retrive config from model
- add sub package to manage cipher, curves, auth client, tls version, certificates, root ca...
- add some small test (can be expande to having more coverage)
- optimize some code

Package httpcli:
- update code following change in certificates

Package httpserver:
- update code following change in certificates

Package Config/Components:
- update code following change in certificates

Package FTPClient:
- update code following change in certificates

Package Nats:
- update code following change in certificates
2024-12-04 17:30:22 +01:00

289 lines
7.7 KiB
Go

/***********************************************************************************************************************
*
* MIT License
*
* Copyright (c) 2021 Nicolas JUHEL
*
* 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.
*
*
**********************************************************************************************************************/
package nats
import (
"fmt"
"time"
libval "github.com/go-playground/validator/v10"
libtls "github.com/nabbar/golib/certificates"
natcli "github.com/nats-io/nats.go"
)
type Client struct {
// Url represents a single NATS server url to which the client
// will be connecting. If the Servers option is also set, it
// then becomes the first server in the Servers array.
Url string
// Servers is a configured set of servers which this client
// will use when attempting to connect.
Servers []string
// NoRandomize configures whether we will randomize the
// server pool.
NoRandomize bool
// NoEcho configures whether the server will echo back messages
// that are sent on this connection if we also have matching subscriptions.
// Note this is supported on servers >= version 1.2. Proto 1 or greater.
NoEcho bool
// Name is an optional name label which will be sent to the server
// on CONNECT to identify the client.
Name string
// Verbose signals the server to send an OK ack for commands
// successfully processed by the server.
Verbose bool
// Pedantic signals the server whether it should be doing further
// validation of subjects.
Pedantic bool
// AllowReconnect enables reconnection logic to be used when we
// encounter a disconnect from the current server.
AllowReconnect bool
// MaxReconnect sets the number of reconnect attempts that will be
// tried before giving up. If negative, then it will never give up
// trying to reconnect.
MaxReconnect int
// ReconnectWait sets the time to backoff after attempting a reconnect
// to a server that we were already connected to previously.
ReconnectWait time.Duration
// 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
// DrainTimeout sets the timeout for a Drain Operation to complete.
DrainTimeout time.Duration
// FlusherTimeout is the maximum time to wait for write operations
// to the underlying connection to complete (including the flusher loop).
FlusherTimeout time.Duration
// PingInterval is the period at which the client will be sending ping
// commands to the server, disabled if 0 or negative.
PingInterval time.Duration
// MaxPingsOut is the maximum number of pending ping commands that can
// be awaiting a response before raising an ErrStaleConnection error.
MaxPingsOut int
// ReconnectBufSize is the size of the backing bufio during reconnect.
// Once this has been exhausted publish operations will return an error.
ReconnectBufSize int
// SubChanLen is the size of the buffered channel used between the socket
// Go routine and the message delivery for SyncSubscriptions.
// NOTE: This does not affect AsyncSubscriptions which are
// dictated by PendingLimits()
SubChanLen int
// User sets the username to be used when connecting to the server.
User string
// Password sets the password to be used when connecting to a server.
Password string
// Token sets the token to be used when connecting to a server.
Token string
// UseOldRequestStyle forces the old method of Requests that utilize
// a new Inbox and a new Subscription for each request.
UseOldRequestStyle bool
// NoCallbacksAfterClientClose allows preventing the invocation of
// callbacks after Close() is called. Client won't receive notifications
// when Close is invoked by user code. Default is to invoke the callbacks.
NoCallbacksAfterClientClose bool
// Secure enables TLS secure connections that skip server
// verification by default. NOT RECOMMENDED.
Secure bool
// TLSConfig is a custom TLS configuration to use for secure
// transports.
TLSConfig libtls.Config
}
func (c Client) Validate() error {
err := ErrorConfigValidation.Error(nil)
if er := libval.New().Struct(c); er != nil {
if e, ok := er.(*libval.InvalidValidationError); ok {
err.Add(e)
}
for _, e := range er.(libval.ValidationErrors) {
//nolint goerr113
err.Add(fmt.Errorf("config field '%s' is not validated by constraint '%s'", e.Namespace(), e.ActualTag()))
}
}
if err.HasParent() {
return err
}
return nil
}
func (c Client) NewClient(defTls libtls.TLSConfig) (*natcli.Conn, error) {
opts := natcli.GetDefaultOptions()
if c.Url != "" {
opts.Url = c.Url
}
if len(c.Servers) > 0 {
opts.Servers = make([]string, 0)
for _, s := range c.Servers {
if s != "" {
opts.Servers = append(opts.Servers, s)
}
}
}
if c.NoRandomize {
opts.NoRandomize = true
}
if c.NoEcho {
opts.NoEcho = true
}
if c.Name != "" {
opts.Name = c.Name
}
if c.Verbose {
opts.Verbose = true
}
if c.Pedantic {
opts.Pedantic = true
}
if c.AllowReconnect {
opts.AllowReconnect = true
}
if c.MaxReconnect > 0 {
opts.MaxReconnect = c.MaxReconnect
}
if c.ReconnectWait > 0 {
opts.ReconnectWait = c.ReconnectWait
}
if c.ReconnectJitter > 0 {
opts.ReconnectJitter = c.ReconnectJitter
}
if c.ReconnectJitterTLS > 0 {
opts.ReconnectJitterTLS = c.ReconnectJitterTLS
}
if c.Timeout > 0 {
opts.Timeout = c.Timeout
}
if c.DrainTimeout > 0 {
opts.DrainTimeout = c.DrainTimeout
}
if c.FlusherTimeout > 0 {
opts.FlusherTimeout = c.FlusherTimeout
}
if c.PingInterval > 0 {
opts.PingInterval = c.PingInterval
}
if c.MaxPingsOut > 0 {
opts.MaxPingsOut = c.MaxPingsOut
}
if c.ReconnectBufSize > 0 {
opts.ReconnectBufSize = c.ReconnectBufSize
}
if c.SubChanLen > 0 {
opts.SubChanLen = c.SubChanLen
}
if c.User != "" {
opts.User = c.User
}
if c.Password != "" {
opts.Password = c.Password
}
if c.Token != "" {
opts.Token = c.Token
}
if c.UseOldRequestStyle {
opts.UseOldRequestStyle = true
}
if c.NoCallbacksAfterClientClose {
opts.NoCallbacksAfterClientClose = true
}
if c.Secure {
if t := c.TLSConfig.NewFrom(defTls); t == nil {
return nil, fmt.Errorf("no valid tls configuration")
} else {
opts.TLSConfig = t.TlsConfig("")
}
opts.Secure = true
}
if n, e := opts.Connect(); e != nil {
return nil, ErrorClientConnect.Error(e)
} else {
return n, nil
}
}