Files
opencloud/pkg/jmap/jmap_client.go
Pascal Bleser 5fa9e57eb7 groupware: Etag handling
* implement correct Etag and If-None-Match handling, responding with
   304 Not Modified if they match

 * introduce SessionState and State string type aliases to ensure we are
   using the correct fields for those, respectively

 * extract the SessionState from the JMAP response bodies in the
   groupware framework instead of having to do that in every single
   groupware API

 * use uint instead of int in some places to clarify that the values are
   >= 0

 * trace-log how long a Session was held in cache before being evicted

 * add Trace-Id header handling: add to response when specified in
   request, and implement a custom request logger to include it as a
   field

 * implement a more compact trace-logging of all the methods and URIs
   that are served, to put them into a single log entry instead of
   creating one log entry for every URI
2026-02-10 17:03:58 +01:00

68 lines
1.9 KiB
Go

package jmap
import (
"io"
"github.com/opencloud-eu/opencloud/pkg/log"
"github.com/rs/zerolog"
)
type Client struct {
wellKnown SessionClient
api ApiClient
blob BlobClient
sessionEventListeners *eventListeners[SessionEventListener]
io.Closer
}
func (j *Client) Close() error {
return j.api.Close()
}
func NewClient(wellKnown SessionClient, api ApiClient, blob BlobClient) Client {
return Client{
wellKnown: wellKnown,
api: api,
blob: blob,
sessionEventListeners: newEventListeners[SessionEventListener](),
}
}
func (j *Client) AddSessionEventListener(listener SessionEventListener) {
j.sessionEventListeners.add(listener)
}
func (j *Client) onSessionOutdated(session *Session, newSessionState SessionState) {
j.sessionEventListeners.signal(func(listener SessionEventListener) {
listener.OnSessionOutdated(session, newSessionState)
})
}
// Retrieve JMAP well-known data from the Stalwart server and create a Session from that.
func (j *Client) FetchSession(username string, logger *log.Logger) (Session, Error) {
wk, err := j.wellKnown.GetSession(username, logger)
if err != nil {
return Session{}, err
}
return newSession(wk)
}
func (j *Client) logger(accountId string, operation string, session *Session, logger *log.Logger) *log.Logger {
l := logger.With().Str(logOperation, operation).Str(logUsername, session.Username)
if accountId != "" {
l = l.Str(logAccountId, accountId)
}
return log.From(l)
}
func (j *Client) loggerParams(accountId string, operation string, session *Session, logger *log.Logger, params func(zerolog.Context) zerolog.Context) *log.Logger {
l := logger.With().Str(logOperation, operation).Str(logUsername, session.Username)
if accountId != "" {
l = l.Str(logAccountId, accountId)
}
if params != nil {
l = params(l)
}
return log.From(l)
}