Server: Export WebDAV response helper for PROPFIND content type #5472

Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
Michael Mayer 2026-03-04 16:03:33 +01:00
parent 7b96a768d5
commit 0ae82d3683
2 changed files with 71 additions and 52 deletions

View file

@ -22,58 +22,7 @@ import (
// WebDAVHandler wraps the http request handler so that it can be customized.
var WebDAVHandler = func(c *gin.Context, router *gin.RouterGroup, srv *webdav.Handler) {
w := &webDAVResponseWriter{
ResponseWriter: c.Writer,
method: c.Request.Method,
}
srv.ServeHTTP(w, c.Request)
}
// webDAVResponseWriter adjusts selected WebDAV response headers.
type webDAVResponseWriter struct {
gin.ResponseWriter
method string
wroteHeader bool
}
// WriteHeader writes the status code after normalizing headers.
func (w *webDAVResponseWriter) WriteHeader(statusCode int) {
w.applyWebDAVHeaders(statusCode)
w.wroteHeader = true
w.ResponseWriter.WriteHeader(statusCode)
}
// Write writes response bytes after normalizing headers for implicit 200 responses.
func (w *webDAVResponseWriter) Write(data []byte) (int, error) {
if !w.wroteHeader {
w.applyWebDAVHeaders(http.StatusOK)
w.wroteHeader = true
}
return w.ResponseWriter.Write(data)
}
// WriteString writes string data after normalizing headers for implicit 200 responses.
func (w *webDAVResponseWriter) WriteString(s string) (int, error) {
if !w.wroteHeader {
w.applyWebDAVHeaders(http.StatusOK)
w.wroteHeader = true
}
return w.ResponseWriter.WriteString(s)
}
// applyWebDAVHeaders adjusts the XML content type for PROPFIND multi-status responses.
func (w *webDAVResponseWriter) applyWebDAVHeaders(statusCode int) {
if w.method != header.MethodPropfind || statusCode != http.StatusMultiStatus {
return
}
contentType := strings.ToLower(w.ResponseWriter.Header().Get(header.ContentType))
if strings.HasPrefix(contentType, header.ContentTypeXml) {
w.ResponseWriter.Header().Set(header.ContentType, "application/xml; charset=utf-8")
}
ServeWebDAV(c.Writer, c.Request, srv)
}
// WebDAVWriteMethod returns true for methods that modify WebDAV state.

View file

@ -0,0 +1,70 @@
package server
import (
"net/http"
"strings"
"github.com/gin-gonic/gin"
"golang.org/x/net/webdav"
"github.com/photoprism/photoprism/pkg/http/header"
)
// ServeWebDAV serves the request using a response writer that normalizes
// selected WebDAV response headers.
func ServeWebDAV(w gin.ResponseWriter, r *http.Request, srv *webdav.Handler) {
if w == nil || r == nil || srv == nil {
return
}
srv.ServeHTTP(&webDAVResponseWriter{
ResponseWriter: w,
method: r.Method,
}, r)
}
// webDAVResponseWriter adjusts selected WebDAV response headers.
type webDAVResponseWriter struct {
gin.ResponseWriter
method string
wroteHeader bool
}
// WriteHeader writes the status code after normalizing headers.
func (w *webDAVResponseWriter) WriteHeader(statusCode int) {
w.applyWebDAVHeaders(statusCode)
w.wroteHeader = true
w.ResponseWriter.WriteHeader(statusCode)
}
// Write writes response bytes after normalizing headers for implicit 200 responses.
func (w *webDAVResponseWriter) Write(data []byte) (int, error) {
if !w.wroteHeader {
w.applyWebDAVHeaders(http.StatusOK)
w.wroteHeader = true
}
return w.ResponseWriter.Write(data)
}
// WriteString writes string data after normalizing headers for implicit 200 responses.
func (w *webDAVResponseWriter) WriteString(s string) (int, error) {
if !w.wroteHeader {
w.applyWebDAVHeaders(http.StatusOK)
w.wroteHeader = true
}
return w.ResponseWriter.WriteString(s)
}
// applyWebDAVHeaders adjusts the XML content type for PROPFIND multi-status responses.
func (w *webDAVResponseWriter) applyWebDAVHeaders(statusCode int) {
if w.method != header.MethodPropfind || statusCode != http.StatusMultiStatus {
return
}
contentType := strings.ToLower(w.ResponseWriter.Header().Get(header.ContentType))
if strings.HasPrefix(contentType, header.ContentTypeXml) {
w.ResponseWriter.Header().Set(header.ContentType, "application/xml; charset=utf-8")
}
}