bump reva

fixes: #1747
This commit is contained in:
Ralf Haferkamp
2025-10-30 15:59:39 +01:00
committed by Ralf Haferkamp
parent e270cdbfd2
commit b5b15f29de
23 changed files with 366 additions and 162 deletions

8
go.mod
View File

@@ -56,7 +56,7 @@ require (
github.com/mna/pigeon v1.3.0
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
github.com/nats-io/nats-server/v2 v2.12.0
github.com/nats-io/nats.go v1.46.1
github.com/nats-io/nats.go v1.47.0
github.com/oklog/run v1.2.0
github.com/olekukonko/tablewriter v1.1.0
github.com/onsi/ginkgo v1.16.5
@@ -65,7 +65,7 @@ require (
github.com/open-policy-agent/opa v1.9.0
github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20250724122329-41ba6b191e76
github.com/opencloud-eu/reva/v2 v2.39.1
github.com/opencloud-eu/reva/v2 v2.39.2-0.20251030154544-cac8a0257da6
github.com/opensearch-project/opensearch-go/v4 v4.5.0
github.com/orcaman/concurrent-map v1.0.0
github.com/pkg/errors v0.9.1
@@ -229,7 +229,7 @@ require (
github.com/gobwas/ws v1.2.1 // indirect
github.com/goccy/go-json v0.10.5 // indirect
github.com/goccy/go-yaml v1.18.0 // indirect
github.com/gofrs/flock v0.12.1 // indirect
github.com/gofrs/flock v0.13.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
@@ -336,7 +336,7 @@ require (
github.com/sergi/go-diff v1.4.0 // indirect
github.com/sethvargo/go-diceware v0.5.0 // indirect
github.com/sethvargo/go-password v0.3.1 // indirect
github.com/shamaton/msgpack/v2 v2.3.1 // indirect
github.com/shamaton/msgpack/v2 v2.4.0 // indirect
github.com/shirou/gopsutil/v4 v4.25.6 // indirect
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect
github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92 // indirect

16
go.sum
View File

@@ -480,8 +480,8 @@ github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PU
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=
github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0=
github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw=
github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0=
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
@@ -901,8 +901,8 @@ github.com/nats-io/jwt/v2 v2.8.0 h1:K7uzyz50+yGZDO5o772eRE7atlcSEENpL7P+b74JV1g=
github.com/nats-io/jwt/v2 v2.8.0/go.mod h1:me11pOkwObtcBNR8AiMrUbtVOUGkqYjMQZ6jnSdVUIA=
github.com/nats-io/nats-server/v2 v2.12.0 h1:OIwe8jZUqJFrh+hhiyKu8snNib66qsx806OslqJuo74=
github.com/nats-io/nats-server/v2 v2.12.0/go.mod h1:nr8dhzqkP5E/lDwmn+A2CvQPMd1yDKXQI7iGg3lAvww=
github.com/nats-io/nats.go v1.46.1 h1:bqQ2ZcxVd2lpYI97xYASeRTY3I5boe/IVmuUDPitHfo=
github.com/nats-io/nats.go v1.46.1/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
github.com/nats-io/nats.go v1.47.0 h1:YQdADw6J/UfGUd2Oy6tn4Hq6YHxCaJrVKayxxFqYrgM=
github.com/nats-io/nats.go v1.47.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
github.com/nats-io/nkeys v0.4.11 h1:q44qGV008kYd9W1b1nEBkNzvnWxtRSQ7A8BoqRrcfa0=
github.com/nats-io/nkeys v0.4.11/go.mod h1:szDimtgmfOi9n25JpfIdGw12tZFYXqhGxjhVxsatHVE=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
@@ -948,8 +948,8 @@ github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89 h1:W1ms+l
github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89/go.mod h1:vigJkNss1N2QEceCuNw/ullDehncuJNFB6mEnzfq9UI=
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20250724122329-41ba6b191e76 h1:vD/EdfDUrv4omSFjrinT8Mvf+8D7f9g4vgQ2oiDrVUI=
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20250724122329-41ba6b191e76/go.mod h1:pzatilMEHZFT3qV7C/X3MqOa3NlRQuYhlRhZTL+hN6Q=
github.com/opencloud-eu/reva/v2 v2.39.1 h1:nJ6he/geQcS7EES6WmyZ5TWOA9EkqgL9MgXU1Nns/to=
github.com/opencloud-eu/reva/v2 v2.39.1/go.mod h1:4CgDhO6Pc+HLdNI7+Rep8N0bc7qP9novdcv764IMpmM=
github.com/opencloud-eu/reva/v2 v2.39.2-0.20251030154544-cac8a0257da6 h1:BUrCUrRqBg04MJuhnIK4H1KNK4aebK6H/AYcHjQ0DM4=
github.com/opencloud-eu/reva/v2 v2.39.2-0.20251030154544-cac8a0257da6/go.mod h1:Qm0CibFYrFc096OhWWL14nsGiFoE6g/4oMFHV5CqU+Q=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
@@ -1101,8 +1101,8 @@ github.com/sethvargo/go-diceware v0.5.0 h1:exrQ7GpaBo00GqRVM1N8ChXSsi3oS7tjQiIeh
github.com/sethvargo/go-diceware v0.5.0/go.mod h1:Lg1SyPS7yQO6BBgTN5r4f2MUDkqGfLWsOjHPY0kA8iw=
github.com/sethvargo/go-password v0.3.1 h1:WqrLTjo7X6AcVYfC6R7GtSyuUQR9hGyAj/f1PYQZCJU=
github.com/sethvargo/go-password v0.3.1/go.mod h1:rXofC1zT54N7R8K/h1WDUdkf9BOx5OptoxrMBcrXzvs=
github.com/shamaton/msgpack/v2 v2.3.1 h1:R3QNLIGA/tbdczNMZ5PCRxrXvy+fnzsIaHG4kKMgWYo=
github.com/shamaton/msgpack/v2 v2.3.1/go.mod h1:6khjYnkx73f7VQU7wjcFS9DFjs+59naVWJv1TB7qdOI=
github.com/shamaton/msgpack/v2 v2.4.0 h1:O5Z08MRmbo0lA9o2xnQ4TXx6teJbPqEurqcCOQ8Oi/4=
github.com/shamaton/msgpack/v2 v2.4.0/go.mod h1:6khjYnkx73f7VQU7wjcFS9DFjs+59naVWJv1TB7qdOI=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil/v4 v4.25.6 h1:kLysI2JsKorfaFPcYmcJqbzROzsBWEOAtw6A7dIfqXs=

View File

@@ -1,5 +1,12 @@
run:
timeout: 10m
version: "2"
formatters:
enable:
- gofumpt
- goimports
settings:
gofumpt:
extra-rules: true
linters:
enable:
@@ -18,9 +25,7 @@ linters:
- gocritic
- godot
- godox
- gofumpt
- goheader
- goimports
- gomoddirectives
- goprintffuncname
- gosec
@@ -31,84 +36,81 @@ linters:
- misspell
- nolintlint
- revive
- stylecheck
- tenv
- staticcheck
- testifylint
- thelper
- unconvert
- unparam
- usestdlibvars
- whitespace
linters-settings:
misspell:
locale: US
godox:
keywords:
- FIXME
goheader:
template: |-
Copyright 2015 Tim Heckman. All rights reserved.
Copyright 2018-{{ YEAR }} The Gofrs. All rights reserved.
Use of this source code is governed by the BSD 3-Clause
license that can be found in the LICENSE file.
gofumpt:
extra-rules: true
gocritic:
enabled-tags:
- diagnostic
- style
- performance
disabled-checks:
- paramTypeCombine # already handle by gofumpt.extra-rules
- whyNoLint # already handle by nonolint
- unnamedResult
- hugeParam
- sloppyReassign
- rangeValCopy
- octalLiteral
- ptrToRefParam
- appendAssign
- ruleguard
- httpNoBody
- exposedSyncMutex
revive:
rules:
- name: struct-tag
- name: blank-imports
- name: context-as-argument
- name: context-keys-type
- name: dot-imports
- name: error-return
- name: error-strings
- name: error-naming
- name: exported
- name: if-return
- name: increment-decrement
- name: var-naming
- name: var-declaration
- name: package-comments
- name: range
- name: receiver-naming
- name: time-naming
- name: unexported-return
- name: indent-error-flow
- name: errorf
- name: empty-block
- name: superfluous-else
- name: unused-parameter
- name: unreachable-code
- name: redefines-builtin-id
- wsl_v5
settings:
gocritic:
disabled-checks:
- paramTypeCombine # already handle by gofumpt.extra-rules
- whyNoLint # already handle by nonolint
- unnamedResult
- hugeParam
- sloppyReassign
- rangeValCopy
- octalLiteral
- ptrToRefParam
- appendAssign
- ruleguard
- httpNoBody
- exposedSyncMutex
enabled-tags:
- diagnostic
- style
- performance
godox:
keywords:
- FIXME
goheader:
template: |-
Copyright 2015 Tim Heckman. All rights reserved.
Copyright 2018-{{ YEAR }} The Gofrs. All rights reserved.
Use of this source code is governed by the BSD 3-Clause
license that can be found in the LICENSE file.
gosec:
excludes:
- G115
misspell:
locale: US
revive:
rules:
- name: struct-tag
- name: blank-imports
- name: context-as-argument
- name: context-keys-type
- name: dot-imports
- name: error-return
- name: error-strings
- name: error-naming
- name: exported
- name: if-return
- name: increment-decrement
- name: var-naming
- name: var-declaration
- name: package-comments
- name: range
- name: receiver-naming
- name: time-naming
- name: unexported-return
- name: indent-error-flow
- name: errorf
- name: empty-block
- name: superfluous-else
- name: unused-parameter
- name: unreachable-code
- name: redefines-builtin-id
exclusions:
presets:
- comments
- common-false-positives
- std-error-handling
issues:
exclude-use-default: true
max-issues-per-linter: 0
max-same-issues: 0
output:
show-stats: true
sort-results: true
sort-order:
- linter
- file

View File

@@ -1,4 +1,4 @@
Copyright (c) 2018-2024, The Gofrs
Copyright (c) 2018-2025, The Gofrs
Copyright (c) 2015-2020, Tim Heckman
All rights reserved.

View File

@@ -1,5 +1,5 @@
// Copyright 2015 Tim Heckman. All rights reserved.
// Copyright 2018-2024 The Gofrs. All rights reserved.
// Copyright 2018-2025 The Gofrs. All rights reserved.
// Use of this source code is governed by the BSD 3-Clause
// license that can be found in the LICENSE file.
@@ -62,6 +62,7 @@ type Flock struct {
func New(path string, opts ...Option) *Flock {
// create it if it doesn't exist, and open the file read-only.
flags := os.O_CREATE
switch runtime.GOOS {
case "aix", "solaris", "illumos":
// AIX cannot preform write-lock (i.e. exclusive) on a read-only file.
@@ -124,6 +125,22 @@ func (f *Flock) RLocked() bool {
return f.r
}
// Stat returns the FileInfo structure describing the lock file.
// If the lock file does not exist or cannot be accessed, an error is returned.
//
// This can be used to check the modification time of the lock file,
// which is useful for detecting stale locks.
func (f *Flock) Stat() (fs.FileInfo, error) {
f.m.RLock()
defer f.m.RUnlock()
if f.fh != nil {
return f.fh.Stat()
}
return os.Stat(f.path)
}
func (f *Flock) String() string {
return f.path
}
@@ -158,7 +175,6 @@ func tryCtx(ctx context.Context, fn func() (bool, error), retryDelay time.Durati
case <-ctx.Done():
return false, ctx.Err()
case <-time.After(retryDelay):
// try again
}
}
}

View File

@@ -1,3 +1,8 @@
// Copyright 2015 Tim Heckman. All rights reserved.
// Copyright 2018-2025 The Gofrs. All rights reserved.
// Use of this source code is governed by the BSD 3-Clause
// license that can be found in the LICENSE file.
//go:build (!unix && !windows) || plan9
package flock

View File

@@ -1,5 +1,5 @@
// Copyright 2015 Tim Heckman. All rights reserved.
// Copyright 2018-2024 The Gofrs. All rights reserved.
// Copyright 2018-2025 The Gofrs. All rights reserved.
// Use of this source code is governed by the BSD 3-Clause
// license that can be found in the LICENSE file.
@@ -155,6 +155,7 @@ func (f *Flock) try(locked *bool, flag int) (bool, error) {
}
var retried bool
retry:
err := unix.Flock(int(f.fh.Fd()), flag|unix.LOCK_NB)

View File

@@ -1,5 +1,5 @@
// Copyright 2015 Tim Heckman. All rights reserved.
// Copyright 2018-2024 The Gofrs. All rights reserved.
// Copyright 2018-2025 The Gofrs. All rights reserved.
// Use of this source code is governed by the BSD 3-Clause
// license that can be found in the LICENSE file.

View File

@@ -1,5 +1,5 @@
// Copyright 2015 Tim Heckman. All rights reserved.
// Copyright 2018-2024 The Gofrs. All rights reserved.
// Copyright 2018-2025 The Gofrs. All rights reserved.
// Use of this source code is governed by the BSD 3-Clause
// license that can be found in the LICENSE file.
@@ -23,6 +23,8 @@ const winLockfileSharedLock = 0x00000000
// ErrorLockViolation is the error code returned from the Windows syscall when a lock would block,
// and you ask to fail immediately.
//
//nolint:errname // It should be renamed to `ErrLockViolation`.
const ErrorLockViolation windows.Errno = 0x21 // 33
// Lock is a blocking call to try and take an exclusive file lock.

View File

@@ -23,7 +23,7 @@ A [Go](http://golang.org) client for the [NATS messaging system](https://nats.io
go get github.com/nats-io/nats.go@latest
# To get a specific version:
go get github.com/nats-io/nats.go@v1.46.1
go get github.com/nats-io/nats.go@v1.47.0
# Note that the latest major version for NATS Server is v2:
go get github.com/nats-io/nats-server/v2@latest

View File

@@ -471,6 +471,7 @@ type (
r io.ReadCloser
err error
ctx context.Context
cancel context.CancelFunc
digest hash.Hash
}
)
@@ -867,7 +868,7 @@ func (obs *obs) Get(ctx context.Context, name string, opts ...GetObjectOpt) (Obj
return lobs.Get(ctx, info.ObjectMeta.Opts.Link.Name)
}
result := &objResult{info: info, ctx: ctx}
result := &objResult{info: info, ctx: ctx, cancel: cancel}
if info.Size == 0 {
return result, nil
}
@@ -934,15 +935,10 @@ func (obs *obs) Get(ctx context.Context, name string, opts ...GetObjectOpt) (Obj
nats.Context(ctx),
nats.BindStream(streamName),
}
sub, err := obs.pushJS.Subscribe(chunkSubj, processChunk, subscribeOpts...)
_, err = obs.pushJS.Subscribe(chunkSubj, processChunk, subscribeOpts...)
if err != nil {
return nil, err
}
sub.SetClosedHandler(func(subject string) {
if cancel != nil {
cancel()
}
})
return result, nil
}
@@ -1500,6 +1496,9 @@ func (o *objResult) Read(p []byte) (n int, err error) {
func (o *objResult) Close() error {
o.Lock()
defer o.Unlock()
if o.cancel != nil {
o.cancel()
}
if o.r == nil {
return nil
}

View File

@@ -33,12 +33,11 @@ type (
// MessagesContext supports iterating over a messages on a stream.
// It is returned by [Consumer.Messages] method.
MessagesContext interface {
// Next retrieves next message on a stream. It will block until the next
// message is available. If the context is canceled, Next will return
// ErrMsgIteratorClosed error. An optional timeout or context can be
// provided using NextOpt options. If none are provided, Next will block
// indefinitely until a message is available, iterator is closed or a
// heartbeat error occurs.
// Next retrieves next message on a stream. If MessagesContext is closed
// (either stopped or drained), Next will return ErrMsgIteratorClosed
// error. An optional timeout or context can be provided using NextOpt
// options. If none are provided, Next will block indefinitely until a
// message is available, iterator is closed or a heartbeat error occurs.
Next(opts ...NextOpt) (Msg, error)
// Stop unsubscribes from the stream and cancels subscription. Calling
@@ -137,6 +136,7 @@ type (
consumer *pullConsumer
subscription *nats.Subscription
msgs chan *nats.Msg
msgsClosed atomic.Uint32
errs chan error
pending pendingMsgs
hbMonitor *hbMonitor
@@ -552,7 +552,7 @@ func (p *pullConsumer) Messages(opts ...PullMessagesOpt) (MessagesContext, error
// in Next
p.subs.Delete(sid)
}
close(msgs)
sub.closeMsgs()
}
}(sub.id))
@@ -588,9 +588,11 @@ var (
errDisconnected = errors.New("disconnected")
)
// Next retrieves next message on a stream. It will block until the next
// message is available. If the context is canceled, Next will return
// ErrMsgIteratorClosed error.
// Next retrieves next message on a stream. If MessagesContext is closed
// (either stopped or drained), Next will return ErrMsgIteratorClosed
// error. An optional timeout or context can be provided using NextOpt
// options. If none are provided, Next will block indefinitely until a
// message is available, iterator is closed or a heartbeat error occurs.
func (s *pullSubscription) Next(opts ...NextOpt) (Msg, error) {
var nextOpts nextOpts
for _, opt := range opts {
@@ -1057,6 +1059,12 @@ func (s *pullSubscription) pullMessages(subject string) {
}
}
func (s *pullSubscription) closeMsgs() {
if s.msgsClosed.CompareAndSwap(0, 1) {
close(s.msgs)
}
}
func (s *pullSubscription) scheduleHeartbeatCheck(dur time.Duration) *hbMonitor {
if dur == 0 {
return nil

View File

@@ -48,7 +48,7 @@ import (
// Default Constants
const (
Version = "1.46.1"
Version = "1.47.0"
DefaultURL = "nats://127.0.0.1:4222"
DefaultPort = 4222
DefaultMaxReconnect = 60
@@ -151,6 +151,7 @@ var (
ErrMaxAccountConnectionsExceeded = errors.New("nats: maximum account active connections exceeded")
ErrConnectionNotTLS = errors.New("nats: connection is not tls")
ErrMaxSubscriptionsExceeded = errors.New("nats: server maximum subscriptions exceeded")
ErrWebSocketHeadersAlreadySet = errors.New("nats: websocket connection headers already set")
)
// GetDefaultOptions returns default configuration options for the client.
@@ -250,6 +251,9 @@ type UserInfoCB func() (string, string)
// whole list of URLs and failed to reconnect.
type ReconnectDelayHandler func(attempts int) time.Duration
// WebSocketHeadersHandler is an optional callback handler for generating token used for WebSocket connections.
type WebSocketHeadersHandler func() (http.Header, error)
// asyncCB is used to preserve order for async callbacks.
type asyncCB struct {
f func()
@@ -524,6 +528,12 @@ type Options struct {
// from SubscribeSync if the server returns a permissions error for a subscription.
// Defaults to false.
PermissionErrOnSubscribe bool
// WebSocketConnectionHeaders is an optional http request headers to be sent with the WebSocket request.
WebSocketConnectionHeaders http.Header
// WebSocketConnectionHeadersHandler is an optional callback handler for generating token used for WebSocket connections.
WebSocketConnectionHeadersHandler WebSocketHeadersHandler
}
const (
@@ -1472,6 +1482,36 @@ func TLSHandshakeFirst() Option {
}
}
// WebSocketConnectionHeaders sets a fixed set of HTTP headers that will be
// sent during the WebSocket connection handshake.
// This option is mutually exclusive with WebSocketConnectionHeadersHandler;
// if a headers handler has already been configured, it returns
// ErrWebSocketHeadersAlreadySet.
func WebSocketConnectionHeaders(headers http.Header) Option {
return func(o *Options) error {
if o.WebSocketConnectionHeadersHandler != nil {
return ErrWebSocketHeadersAlreadySet
}
o.WebSocketConnectionHeaders = headers
return nil
}
}
// WebSocketConnectionHeadersHandler registers a callback used to supply HTTP
// headers for the WebSocket connection handshake.
// This option is mutually exclusive with WebSocketConnectionHeaders; if
// non-empty static headers have already been configured, it returns
// ErrWebSocketHeadersAlreadySet.
func WebSocketConnectionHeadersHandler(cb WebSocketHeadersHandler) Option {
return func(o *Options) error {
if len(o.WebSocketConnectionHeaders) != 0 {
return ErrWebSocketHeadersAlreadySet
}
o.WebSocketConnectionHeadersHandler = cb
return nil
}
}
// Handler processing
// SetDisconnectHandler will set the disconnect event handler.
@@ -1671,8 +1711,10 @@ func (o Options) Connect() (*Conn, error) {
return nil, err
}
if connectionEstablished && nc.Opts.ConnectedCB != nil {
nc.ach.push(func() { nc.Opts.ConnectedCB(nc) })
if connectionEstablished {
if connectedCB := nc.Opts.ConnectedCB; connectedCB != nil {
nc.ach.push(func() { connectedCB(nc) })
}
}
return nc, nil
@@ -2747,8 +2789,10 @@ func (nc *Conn) sendConnect() error {
// Construct the CONNECT protocol string
cProto, err := nc.connectProto()
if err != nil {
if !nc.initc && nc.Opts.AsyncErrorCB != nil {
nc.ach.push(func() { nc.Opts.AsyncErrorCB(nc, nil, err) })
if !nc.initc {
if asyncErrorCB := nc.Opts.AsyncErrorCB; asyncErrorCB != nil {
nc.ach.push(func() { asyncErrorCB(nc, nil, err) })
}
}
return err
}
@@ -2764,8 +2808,10 @@ func (nc *Conn) sendConnect() error {
// reading byte-by-byte here is ok.
proto, err := nc.readProto()
if err != nil {
if !nc.initc && nc.Opts.AsyncErrorCB != nil {
nc.ach.push(func() { nc.Opts.AsyncErrorCB(nc, nil, err) })
if !nc.initc {
if asyncErrorCB := nc.Opts.AsyncErrorCB; asyncErrorCB != nil {
nc.ach.push(func() { asyncErrorCB(nc, nil, err) })
}
}
return err
}
@@ -2775,8 +2821,10 @@ func (nc *Conn) sendConnect() error {
// Read the rest now...
proto, err = nc.readProto()
if err != nil {
if !nc.initc && nc.Opts.AsyncErrorCB != nil {
nc.ach.push(func() { nc.Opts.AsyncErrorCB(nc, nil, err) })
if !nc.initc {
if asyncErrorCB := nc.Opts.AsyncErrorCB; asyncErrorCB != nil {
nc.ach.push(func() { asyncErrorCB(nc, nil, err) })
}
}
return err
}
@@ -2884,10 +2932,10 @@ func (nc *Conn) doReconnect(err error, forceReconnect bool) {
// Perform appropriate callback if needed for a disconnect.
// DisconnectedErrCB has priority over deprecated DisconnectedCB
if !nc.initc {
if nc.Opts.DisconnectedErrCB != nil {
nc.ach.push(func() { nc.Opts.DisconnectedErrCB(nc, err) })
} else if nc.Opts.DisconnectedCB != nil {
nc.ach.push(func() { nc.Opts.DisconnectedCB(nc) })
if disconnectedErrCB := nc.Opts.DisconnectedErrCB; disconnectedErrCB != nil {
nc.ach.push(func() { disconnectedErrCB(nc, err) })
} else if disconnectedCB := nc.Opts.DisconnectedCB; disconnectedCB != nil {
nc.ach.push(func() { disconnectedCB(nc) })
}
} else if nc.Opts.RetryOnFailedConnect && nc.initc && err != nil {
// For initial connection failure with RetryOnFailedConnect,
@@ -2996,8 +3044,8 @@ func (nc *Conn) doReconnect(err error, forceReconnect bool) {
// Continue to hold the lock
if err != nil {
// Perform appropriate callback for a failed connection attempt.
if nc.Opts.ReconnectErrCB != nil {
nc.ach.push(func() { nc.Opts.ReconnectErrCB(nc, err) })
if reconnectErrCB := nc.Opts.ReconnectErrCB; reconnectErrCB != nil {
nc.ach.push(func() { reconnectErrCB(nc, err) })
}
nc.err = nil
continue
@@ -3047,10 +3095,10 @@ func (nc *Conn) doReconnect(err error, forceReconnect bool) {
// Queue up the correct callback. If we are in initial connect state
// (using retry on failed connect), we will call the ConnectedCB,
// otherwise the ReconnectedCB.
if nc.Opts.ReconnectedCB != nil && !nc.initc {
nc.ach.push(func() { nc.Opts.ReconnectedCB(nc) })
} else if nc.Opts.ConnectedCB != nil && nc.initc {
nc.ach.push(func() { nc.Opts.ConnectedCB(nc) })
if reconnectedCB := nc.Opts.ReconnectedCB; reconnectedCB != nil && !nc.initc {
nc.ach.push(func() { reconnectedCB(nc) })
} else if connectedCB := nc.Opts.ConnectedCB; connectedCB != nil && nc.initc {
nc.ach.push(func() { connectedCB(nc) })
}
// If we are here with a retry on failed connect, indicate that the
@@ -3364,8 +3412,8 @@ func (nc *Conn) processMsg(data []byte) {
// We will pass the message through but send async error.
nc.mu.Lock()
nc.err = ErrBadHeaderMsg
if nc.Opts.AsyncErrorCB != nil {
nc.ach.push(func() { nc.Opts.AsyncErrorCB(nc, sub, ErrBadHeaderMsg) })
if asyncErrorCB := nc.Opts.AsyncErrorCB; asyncErrorCB != nil {
nc.ach.push(func() { asyncErrorCB(nc, sub, ErrBadHeaderMsg) })
}
nc.mu.Unlock()
}
@@ -3542,8 +3590,8 @@ slowConsumer:
// is already experiencing client-side slow consumer situation.
nc.mu.Lock()
nc.err = ErrSlowConsumer
if nc.Opts.AsyncErrorCB != nil {
nc.ach.push(func() { nc.Opts.AsyncErrorCB(nc, sub, ErrSlowConsumer) })
if asyncErrorCB := nc.Opts.AsyncErrorCB; asyncErrorCB != nil {
nc.ach.push(func() { asyncErrorCB(nc, sub, ErrSlowConsumer) })
}
nc.mu.Unlock()
} else {
@@ -3586,8 +3634,8 @@ func (nc *Conn) processTransientError(err error) {
}
}
}
if nc.Opts.AsyncErrorCB != nil {
nc.ach.push(func() { nc.Opts.AsyncErrorCB(nc, nil, err) })
if asyncErrorCB := nc.Opts.AsyncErrorCB; asyncErrorCB != nil {
nc.ach.push(func() { asyncErrorCB(nc, nil, err) })
}
nc.mu.Unlock()
}
@@ -3599,8 +3647,10 @@ func (nc *Conn) processTransientError(err error) {
// Connection lock is held on entry
func (nc *Conn) processAuthError(err error) bool {
nc.err = err
if !nc.initc && nc.Opts.AsyncErrorCB != nil {
nc.ach.push(func() { nc.Opts.AsyncErrorCB(nc, nil, err) })
if !nc.initc {
if asyncErrorCB := nc.Opts.AsyncErrorCB; asyncErrorCB != nil {
nc.ach.push(func() { asyncErrorCB(nc, nil, err) })
}
}
// We should give up if we tried twice on this server and got the
// same error. This behavior can be modified using IgnoreAuthErrorAbort.
@@ -3645,8 +3695,8 @@ func (nc *Conn) flusher() {
if nc.err == nil {
nc.err = err
}
if nc.Opts.AsyncErrorCB != nil {
nc.ach.push(func() { nc.Opts.AsyncErrorCB(nc, nil, err) })
if asyncErrorCB := nc.Opts.AsyncErrorCB; asyncErrorCB != nil {
nc.ach.push(func() { asyncErrorCB(nc, nil, err) })
}
}
}
@@ -3760,12 +3810,16 @@ func (nc *Conn) processInfo(info string) error {
if !nc.Opts.NoRandomize {
nc.shufflePool(1)
}
if !nc.initc && nc.Opts.DiscoveredServersCB != nil {
nc.ach.push(func() { nc.Opts.DiscoveredServersCB(nc) })
if !nc.initc {
if discoveredServersCB := nc.Opts.DiscoveredServersCB; discoveredServersCB != nil {
nc.ach.push(func() { discoveredServersCB(nc) })
}
}
}
if !nc.initc && ncInfo.LameDuckMode && nc.Opts.LameDuckModeHandler != nil {
nc.ach.push(func() { nc.Opts.LameDuckModeHandler(nc) })
if !nc.initc && ncInfo.LameDuckMode {
if lameDuckModeHandler := nc.Opts.LameDuckModeHandler; lameDuckModeHandler != nil {
nc.ach.push(func() { lameDuckModeHandler(nc) })
}
}
return nil
}
@@ -5607,8 +5661,8 @@ func (nc *Conn) close(status Status, doCBs bool, err error) {
nc.ach.push(func() { disconnectedCB(nc) })
}
}
if nc.Opts.ClosedCB != nil {
nc.ach.push(func() { nc.Opts.ClosedCB(nc) })
if closedCB := nc.Opts.ClosedCB; closedCB != nil {
nc.ach.push(func() { closedCB(nc) })
}
}
// If this is terminal, then we have to notify the asyncCB handler that

View File

@@ -610,6 +610,9 @@ func (nc *Conn) wsInitHandshake(u *url.URL) error {
if compress {
req.Header.Add("Sec-WebSocket-Extensions", wsPMCReqHeaderValue)
}
if err := nc.wsUpdateConnectionHeaders(req); err != nil {
return err
}
if err := req.Write(nc.conn); err != nil {
return err
}
@@ -728,6 +731,25 @@ func (nc *Conn) wsEnqueueControlMsg(needsLock bool, frameType wsOpCode, payload
nc.bw.flush()
}
func (nc *Conn) wsUpdateConnectionHeaders(req *http.Request) error {
var headers http.Header
var err error
if nc.Opts.WebSocketConnectionHeadersHandler != nil {
headers, err = nc.Opts.WebSocketConnectionHeadersHandler()
if err != nil {
return err
}
} else {
headers = nc.Opts.WebSocketConnectionHeaders
}
for key, values := range headers {
for _, val := range values {
req.Header.Add(key, val)
}
}
return nil
}
func wsPMCExtensionSupport(header http.Header) (bool, bool) {
for _, extensionList := range header["Sec-Websocket-Extensions"] {
extensions := strings.Split(extensionList, ",")

View File

@@ -115,7 +115,7 @@ func (am *mgr) Authenticate(ctx context.Context, clientID, clientSecret string)
}
// Bind as the user to verify their password
la, err := utils.GetLDAPClientForAuth(&am.c.LDAPConn)
la, err := utils.GetLDAPClientForAuth(ctx, &am.c.LDAPConn)
if err != nil {
return nil, nil, err
}

View File

@@ -727,7 +727,7 @@ func (t *Tree) isIndex(path string) bool {
}
func (t *Tree) isTemporary(path string) bool {
return path == blobstore.TMPDir
return path == blobstore.TMPDir || filepath.Dir(path) == blobstore.TMPDir
}
func (t *Tree) isRootPath(path string) bool {

View File

@@ -19,11 +19,13 @@
package utils
import (
"context"
"crypto/tls"
"crypto/x509"
"os"
"github.com/go-ldap/ldap/v3"
"github.com/opencloud-eu/reva/v2/pkg/appctx"
"github.com/opencloud-eu/reva/v2/pkg/logger"
ldapReconnect "github.com/opencloud-eu/reva/v2/pkg/utils/ldap"
"github.com/pkg/errors"
@@ -77,10 +79,10 @@ func GetLDAPClientWithReconnect(c *LDAPConn) (ldap.Client, error) {
// GetLDAPClientForAuth initializes an LDAP connection. The connection is not authenticated
// when returned. The main purpose for GetLDAPClientForAuth is to get and LDAP connection that
// can be used to issue a single bind request to authenticate a user.
func GetLDAPClientForAuth(c *LDAPConn) (ldap.Client, error) {
func GetLDAPClientForAuth(ctx context.Context, c *LDAPConn) (ldap.Client, error) {
var tlsConf *tls.Config
if c.Insecure {
logger.New().Warn().Msg("SSL Certificate verification is disabled. Is is strongly discouraged for production environments.")
appctx.GetLogger(ctx).Warn().Msg("SSL Certificate verification is disabled. Is is strongly discouraged for production environments.")
tlsConf = &tls.Config{
//nolint:gosec // We need the ability to run with "insecure" (dev/testing)
InsecureSkipVerify: true,

View File

@@ -6,6 +6,11 @@
[![codecov](https://codecov.io/gh/shamaton/msgpack/branch/master/graph/badge.svg?token=9PD2JUK5V3)](https://codecov.io/gh/shamaton/msgpack)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fshamaton%2Fmsgpack.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fshamaton%2Fmsgpack?ref=badge_shield)
## 📣 Announcement: `time.Time` decoding defaults to **UTC** in v3
Starting with **v3.0.0**, when decoding MessagePack **Timestamp** into Gos `time.Time`,
the default `Location` will be **UTC** (previously `Local`). The instant is unchanged.
To keep the old behavior, use `SetDecodedTimeAsLocal()`.
## Features
* Supported types : primitive / array / slice / struct / map / interface{} and time.Time
* Renaming fields via `msgpack:"field_name"`
@@ -60,6 +65,51 @@ func handle(w http.ResponseWriter, r *http.Request) {
}
```
## 📣 Announcement: `time.Time` decoding defaults to **UTC** in v3
**TL;DR:** Starting with **v3.0.0**, when decoding MessagePack **Timestamp** into Gos `time.Time`, the default `Location` will be **UTC** (previously `Local`). The **instant** is unchanged—only the display/location changes. This avoids host-dependent differences and aligns with common distributed systems practice.
### What is changing?
* **Before (v2.x):** Decoded `time.Time` defaults to `Local`.
* **After (v3.0.0):** Decoded `time.Time` defaults to **UTC**.
MessagePacks Timestamp encodes an **instant** (epoch seconds + nanoseconds) and does **not** carry timezone info. Your datas point in time is the same; only `time.Time.Location()` differs.
### Why?
* Eliminate environment-dependent behavior (e.g., different hosts showing different local zones).
* Make “UTC by default” the safe, predictable baseline for logs, APIs, and distributed apps.
### Who is affected?
* Apps that **display local time** without explicitly converting from UTC.
* If your code already normalizes to UTC or explicitly sets a location, youre likely unaffected.
### Keep the old behavior (Local)
If you want the v2 behavior on v3:
```go
msgpack.SetDecodedTimeAsLocal()
```
Or convert after the fact:
```go
var t time.Time
_ = msgpack.Unmarshal(data, &t)
t = t.In(time.Local)
```
### Preview the new behavior on v2 (optional)
You can opt into UTC today on v2.x:
```go
msgpack.SetDecodedTimeAsUTC()
```
## Benchmark
This result made from [shamaton/msgpack_bench](https://github.com/shamaton/msgpack_bench)

View File

@@ -10,6 +10,7 @@ import (
"github.com/shamaton/msgpack/v2/internal/encoding"
streamdecoding "github.com/shamaton/msgpack/v2/internal/stream/decoding"
streamencoding "github.com/shamaton/msgpack/v2/internal/stream/encoding"
"github.com/shamaton/msgpack/v2/time"
)
// StructAsArray is encoding option.
@@ -82,3 +83,13 @@ func RemoveExtStreamCoder(e ext.StreamEncoder, d ext.StreamDecoder) error {
func SetComplexTypeCode(code int8) {
def.SetComplexTypeCode(code)
}
// SetDecodedTimeAsUTC sets decoded time.Time values to UTC timezone.
func SetDecodedTimeAsUTC() {
time.SetDecodedAsLocal(false)
}
// SetDecodedTimeAsLocal sets decoded time.Time values to local timezone.
func SetDecodedTimeAsLocal() {
time.SetDecodedAsLocal(true)
}

View File

@@ -48,7 +48,11 @@ func (td *timeDecoder) AsValue(offset int, k reflect.Kind, d *[]byte) (interface
case def.Fixext4:
_, offset = td.ReadSize1(offset, d)
bs, offset := td.ReadSize4(offset, d)
return time.Unix(int64(binary.BigEndian.Uint32(bs)), 0), offset, nil
v := time.Unix(int64(binary.BigEndian.Uint32(bs)), 0)
if decodeAsLocal {
return v, offset, nil
}
return v.UTC(), offset, nil
case def.Fixext8:
_, offset = td.ReadSize1(offset, d)
@@ -56,9 +60,13 @@ func (td *timeDecoder) AsValue(offset int, k reflect.Kind, d *[]byte) (interface
data64 := binary.BigEndian.Uint64(bs)
nano := int64(data64 >> 34)
if nano > 999999999 {
return zero, 0, fmt.Errorf("In timestamp 64 formats, nanoseconds must not be larger than 999999999 : %d", nano)
return zero, 0, fmt.Errorf("in timestamp 64 formats, nanoseconds must not be larger than 999999999 : %d", nano)
}
return time.Unix(int64(data64&0x00000003ffffffff), nano), offset, nil
v := time.Unix(int64(data64&0x00000003ffffffff), nano)
if decodeAsLocal {
return v, offset, nil
}
return v.UTC(), offset, nil
case def.Ext8:
_, offset = td.ReadSize1(offset, d)
@@ -67,10 +75,14 @@ func (td *timeDecoder) AsValue(offset int, k reflect.Kind, d *[]byte) (interface
secbs, offset := td.ReadSize8(offset, d)
nano := binary.BigEndian.Uint32(nanobs)
if nano > 999999999 {
return zero, 0, fmt.Errorf("In timestamp 96 formats, nanoseconds must not be larger than 999999999 : %d", nano)
return zero, 0, fmt.Errorf("in timestamp 96 formats, nanoseconds must not be larger than 999999999 : %d", nano)
}
sec := binary.BigEndian.Uint64(secbs)
return time.Unix(int64(sec), int64(nano)), offset, nil
v := time.Unix(int64(sec), int64(nano))
if decodeAsLocal {
return v, offset, nil
}
return v.UTC(), offset, nil
}
return zero, 0, fmt.Errorf("should not reach this line!! code %x decoding %v", code, k)

View File

@@ -33,7 +33,11 @@ func (td *timeStreamDecoder) IsType(code byte, innerType int8, dataLength int) b
func (td *timeStreamDecoder) ToValue(code byte, data []byte, k reflect.Kind) (interface{}, error) {
switch code {
case def.Fixext4:
return time.Unix(int64(binary.BigEndian.Uint32(data)), 0), nil
v := time.Unix(int64(binary.BigEndian.Uint32(data)), 0)
if decodeAsLocal {
return v, nil
}
return v.UTC(), nil
case def.Fixext8:
data64 := binary.BigEndian.Uint64(data)
@@ -41,7 +45,11 @@ func (td *timeStreamDecoder) ToValue(code byte, data []byte, k reflect.Kind) (in
if nano > 999999999 {
return zero, fmt.Errorf("in timestamp 64 formats, nanoseconds must not be larger than 999999999 : %d", nano)
}
return time.Unix(int64(data64&0x00000003ffffffff), nano), nil
v := time.Unix(int64(data64&0x00000003ffffffff), nano)
if decodeAsLocal {
return v, nil
}
return v.UTC(), nil
case def.Ext8:
nano := binary.BigEndian.Uint32(data[:4])
@@ -49,7 +57,11 @@ func (td *timeStreamDecoder) ToValue(code byte, data []byte, k reflect.Kind) (in
return zero, fmt.Errorf("in timestamp 96 formats, nanoseconds must not be larger than 999999999 : %d", nano)
}
sec := binary.BigEndian.Uint64(data[4:12])
return time.Unix(int64(sec), int64(nano)), nil
v := time.Unix(int64(sec), int64(nano))
if decodeAsLocal {
return v, nil
}
return v.UTC(), nil
}
return zero, fmt.Errorf("should not reach this line!! code %x decoding %v", code, k)

8
vendor/github.com/shamaton/msgpack/v2/time/time.go generated vendored Normal file
View File

@@ -0,0 +1,8 @@
package time
var decodeAsLocal = true
// SetDecodedAsLocal sets the decoded time to local time.
func SetDecodedAsLocal(b bool) {
decodeAsLocal = b
}

10
vendor/modules.txt vendored
View File

@@ -691,8 +691,8 @@ github.com/goccy/go-yaml/parser
github.com/goccy/go-yaml/printer
github.com/goccy/go-yaml/scanner
github.com/goccy/go-yaml/token
# github.com/gofrs/flock v0.12.1
## explicit; go 1.21.0
# github.com/gofrs/flock v0.13.0
## explicit; go 1.24.0
github.com/gofrs/flock
# github.com/gofrs/uuid v4.4.0+incompatible
## explicit
@@ -1142,7 +1142,7 @@ github.com/nats-io/nats-server/v2/server/stree
github.com/nats-io/nats-server/v2/server/sysmem
github.com/nats-io/nats-server/v2/server/thw
github.com/nats-io/nats-server/v2/server/tpm
# github.com/nats-io/nats.go v1.46.1
# github.com/nats-io/nats.go v1.47.0
## explicit; go 1.23.0
github.com/nats-io/nats.go
github.com/nats-io/nats.go/encoders/builtin
@@ -1340,7 +1340,7 @@ github.com/opencloud-eu/icap-client
# github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20250724122329-41ba6b191e76
## explicit; go 1.18
github.com/opencloud-eu/libre-graph-api-go
# github.com/opencloud-eu/reva/v2 v2.39.1
# github.com/opencloud-eu/reva/v2 v2.39.2-0.20251030154544-cac8a0257da6
## explicit; go 1.24.1
github.com/opencloud-eu/reva/v2/cmd/revad/internal/grace
github.com/opencloud-eu/reva/v2/cmd/revad/runtime
@@ -1954,7 +1954,7 @@ github.com/sethvargo/go-diceware/diceware
# github.com/sethvargo/go-password v0.3.1
## explicit; go 1.21
github.com/sethvargo/go-password/password
# github.com/shamaton/msgpack/v2 v2.3.1
# github.com/shamaton/msgpack/v2 v2.4.0
## explicit; go 1.20
github.com/shamaton/msgpack/v2
github.com/shamaton/msgpack/v2/def