From 6de0c7b0360325dd7c19ef76405927da4009f539 Mon Sep 17 00:00:00 2001 From: Pascal Bleser Date: Mon, 17 Nov 2025 12:35:00 +0100 Subject: [PATCH] groupware: fix blob uploading metadata and add 'POST /blobs' route --- pkg/jmap/jmap_api_blob.go | 5 ++- pkg/jmap/jmap_http.go | 36 ++++++++++++++++--- .../pkg/groupware/groupware_api_blob.go | 2 +- .../pkg/groupware/groupware_route.go | 1 + 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/pkg/jmap/jmap_api_blob.go b/pkg/jmap/jmap_api_blob.go index f3561992d..b83129fba 100644 --- a/pkg/jmap/jmap_api_blob.go +++ b/pkg/jmap/jmap_api_blob.go @@ -40,9 +40,8 @@ func (j *Client) GetBlobMetadata(accountId string, session *Session, ctx context type UploadedBlob struct { BlobId string `json:"blobId"` - Size int `json:"size"` - Type string `json:"type"` - Sha512 string `json:"sha:512"` + Size int `json:"size,omitzero"` + Type string `json:"type,omitempty"` } func (j *Client) UploadBlobStream(accountId string, session *Session, ctx context.Context, logger *log.Logger, acceptLanguage string, contentType string, body io.Reader) (UploadedBlob, Language, Error) { diff --git a/pkg/jmap/jmap_http.go b/pkg/jmap/jmap_http.go index 9c5bb08ae..630725bcb 100644 --- a/pkg/jmap/jmap_http.go +++ b/pkg/jmap/jmap_http.go @@ -219,9 +219,9 @@ func (h *HttpJmapClient) Command(ctx context.Context, logger *log.Logger, sessio } if logger.Trace().Enabled() { - requestBytes, err := httputil.DumpResponse(res, true) + responseBytes, err := httputil.DumpResponse(res, true) if err == nil { - logger.Trace().Str(logEndpoint, endpoint).Str("proto", "jmap").Str("type", "response").Msg(string(requestBytes)) + logger.Trace().Str(logEndpoint, endpoint).Str("proto", "jmap").Str("type", "response").Msg(string(responseBytes)) } } @@ -261,10 +261,17 @@ func (h *HttpJmapClient) UploadBinary(ctx context.Context, logger *log.Logger, s } req.Header.Add("Content-Type", contentType) req.Header.Add("User-Agent", h.userAgent) - h.auth(session.Username, logger, req) if acceptLanguage != "" { req.Header.Add("Accept-Language", acceptLanguage) } + if logger.Trace().Enabled() { + requestBytes, err := httputil.DumpRequestOut(req, false) + if err == nil { + logger.Trace().Str(logEndpoint, endpoint).Str("proto", "jmap").Str("type", "request").Msg(string(requestBytes)) + } + } + + h.auth(session.Username, logger, req) res, err := h.client.Do(req) if err != nil { @@ -272,6 +279,13 @@ func (h *HttpJmapClient) UploadBinary(ctx context.Context, logger *log.Logger, s logger.Error().Err(err).Msgf("failed to perform POST %v", uploadUrl) return UploadedBlob{}, "", SimpleError{code: JmapErrorSendingRequest, err: err} } + if logger.Trace().Enabled() { + responseBytes, err := httputil.DumpResponse(res, true) + if err == nil { + logger.Trace().Str(logEndpoint, endpoint).Str("proto", "jmap").Str("type", "response").Msg(string(responseBytes)) + } + } + language := Language(res.Header.Get("Content-Language")) if res.StatusCode < 200 || res.StatusCode > 299 { h.listener.OnFailedRequestWithStatus(endpoint, res.StatusCode) @@ -295,6 +309,8 @@ func (h *HttpJmapClient) UploadBinary(ctx context.Context, logger *log.Logger, s return UploadedBlob{}, language, SimpleError{code: JmapErrorServerResponse, err: err} } + logger.Trace() + var result UploadedBlob err = json.Unmarshal(responseBody, &result) if err != nil { @@ -315,10 +331,16 @@ func (h *HttpJmapClient) DownloadBinary(ctx context.Context, logger *log.Logger, return nil, "", SimpleError{code: JmapErrorCreatingRequest, err: err} } req.Header.Add("User-Agent", h.userAgent) - h.auth(session.Username, logger, req) if acceptLanguage != "" { req.Header.Add("Accept-Language", acceptLanguage) } + if logger.Trace().Enabled() { + requestBytes, err := httputil.DumpRequestOut(req, true) + if err == nil { + logger.Trace().Str(logEndpoint, endpoint).Str("proto", "jmap").Str("type", "request").Msg(string(requestBytes)) + } + } + h.auth(session.Username, logger, req) res, err := h.client.Do(req) if err != nil { @@ -326,6 +348,12 @@ func (h *HttpJmapClient) DownloadBinary(ctx context.Context, logger *log.Logger, logger.Error().Err(err).Msgf("failed to perform GET %v", downloadUrl) return nil, "", SimpleError{code: JmapErrorSendingRequest, err: err} } + if logger.Trace().Enabled() { + responseBytes, err := httputil.DumpResponse(res, false) + if err == nil { + logger.Trace().Str(logEndpoint, endpoint).Str("proto", "jmap").Str("type", "response").Msg(string(responseBytes)) + } + } language := Language(res.Header.Get("Content-Language")) if res.StatusCode == http.StatusNotFound { return nil, language, nil diff --git a/services/groupware/pkg/groupware/groupware_api_blob.go b/services/groupware/pkg/groupware/groupware_api_blob.go index 4cf220fe4..1e38f57ec 100644 --- a/services/groupware/pkg/groupware/groupware_api_blob.go +++ b/services/groupware/pkg/groupware/groupware_api_blob.go @@ -59,7 +59,7 @@ func (g *Groupware) UploadBlob(w http.ResponseWriter, r *http.Request) { } logger := log.From(req.logger.With().Str(logAccountId, accountId)) - resp, lang, jerr := g.jmap.UploadBlobStream(accountId, req.session, req.ctx, logger, contentType, req.language(), body) + resp, lang, jerr := g.jmap.UploadBlobStream(accountId, req.session, req.ctx, logger, req.language(), contentType, body) if jerr != nil { return req.errorResponseFromJmap(jerr) } diff --git a/services/groupware/pkg/groupware/groupware_route.go b/services/groupware/pkg/groupware/groupware_route.go index 97bc25687..d31a63f68 100644 --- a/services/groupware/pkg/groupware/groupware_route.go +++ b/services/groupware/pkg/groupware/groupware_route.go @@ -134,6 +134,7 @@ func (g *Groupware) Route(r chi.Router) { r.Route("/blobs", func(r chi.Router) { r.Get("/{blobid}", g.GetBlobMeta) r.Get("/{blobid}/{blobname}", g.DownloadBlob) // ?type= + r.Post("/", g.UploadBlob) }) r.Route("/ical", func(r chi.Router) { r.Get("/{blobid}", g.ParseIcalBlob)