Compare commits

...
16 Commits
Author SHA1 Message Date
renovate[bot] efdaa784b9 chore(deps): update golang.org/x/crypto/x509roots/fallback digest to 7d0074c 2026-01-18 08:34:19 +01:00
renovate[bot] 7662d629e3 chore(deps): update all non-major dependencies 2026-01-17 22:45:01 +01:00
renovate[bot] 010ca576fb chore(deps): update golang.org/x/crypto/x509roots/fallback digest to 7dacc38 2025-12-13 09:10:00 +01:00
renovate[bot] 7b8aa1c422 chore(deps): update all non-major dependencies 2025-12-13 09:05:43 +01:00
Henrique Dias 2f98af7d1e ci: run renovate on weekends 2025-12-05 15:10:32 +01:00
renovate[bot] 50e1828b60 chore(deps): update golang.org/x/crypto/x509roots/fallback digest to 3a1c6b4 2025-12-05 14:34:40 +01:00
renovate[bot] e78d59e374 chore(deps): update module github.com/spf13/cobra to v1.10.2 2025-12-05 14:31:30 +01:00
renovate[bot] de0a102ed8 chore(deps): update golang.org/x/crypto/x509roots/fallback digest to f4602e4 2025-12-03 08:46:31 +01:00
Henrique Dias bdfa98d00d feat: use golang.org/x/crypto/x509roots/fallback 2025-11-20 19:12:12 +01:00
renovate[bot] f0e7e23ea8 chore(deps): update actions/checkout action to v6 2025-11-20 18:55:14 +01:00
renovate[bot] 065991a195 chore(deps): update all non-major dependencies 2025-11-20 08:09:56 +01:00
Henrique Dias bb85514c8f chore: use 'chore' in all commits from renovate 2025-11-13 14:11:51 +01:00
renovate[bot] c0af549a1f fix(deps): update all non-major dependencies 2025-11-12 07:19:53 +01:00
Emmanuel Ferdman 685d89162a chore: update GoReleaser configurations
Signed-off-by: Emmanuel Ferdman <[email protected]>
2025-11-10 17:17:48 +01:00
renovate[bot]andrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com> a5496c9516 chore(deps): update golangci/golangci-lint-action action to v9 (#276)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-08 07:36:01 +01:00
Michael Bruns 24abd52e23 feat: enhanced logging 2025-10-30 07:55:50 +01:00
12 changed files with 62 additions and 42 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version: "1.25.x"
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
id-token: write
steps:
- name: Check out the repo
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
+2 -2
View File
@@ -12,10 +12,10 @@ jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version: "1.25.x"
- uses: golangci/golangci-lint-action@v8
- uses: golangci/golangci-lint-action@v9
with:
version: "latest"
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: actions/setup-go@v6
+1 -1
View File
@@ -13,7 +13,7 @@ jobs:
name: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version: "1.25.x"
+4 -2
View File
@@ -44,10 +44,12 @@ builds:
archives:
- name_template: "{{.Os}}-{{.Arch}}{{if .Arm}}v{{.Arm}}{{end}}-{{ .ProjectName }}"
format: tar.gz
formats:
- tar.gz
format_overrides:
- goos: windows
format: zip
formats:
- zip
release:
github:
-3
View File
@@ -2,8 +2,6 @@ FROM golang:1.25-alpine3.22 AS build
ARG VERSION="untracked"
RUN apk --update add ca-certificates
WORKDIR /webdav/
COPY ./go.mod ./
@@ -15,7 +13,6 @@ RUN go build -o main -trimpath -ldflags="-s -w -X 'github.com/hacdias/webdav/v5/
FROM scratch
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=build /webdav/main /bin/webdav
EXPOSE 6065
+8 -7
View File
@@ -4,16 +4,17 @@ go 1.25.0
require (
github.com/coreos/go-systemd/v22 v22.6.0
github.com/go-viper/mapstructure/v2 v2.4.0
github.com/go-viper/mapstructure/v2 v2.5.0
github.com/rs/cors v1.11.1
github.com/spf13/cobra v1.10.1
github.com/spf13/cobra v1.10.2
github.com/spf13/pflag v1.0.10
github.com/spf13/viper v1.21.0
github.com/stretchr/testify v1.11.1
github.com/studio-b12/gowebdav v0.11.0
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.43.0
golang.org/x/net v0.46.0
go.uber.org/zap v1.27.1
golang.org/x/crypto v0.47.0
golang.org/x/crypto/x509roots/fallback v0.0.0-20260113154411-7d0074ccc6f1
golang.org/x/net v0.49.0
)
require (
@@ -29,7 +30,7 @@ require (
github.com/subosito/gotenv v1.6.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/sys v0.37.0 // indirect
golang.org/x/text v0.30.0 // indirect
golang.org/x/sys v0.40.0 // indirect
golang.org/x/text v0.33.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
+16 -14
View File
@@ -7,8 +7,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
@@ -34,8 +34,8 @@ github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
@@ -51,18 +51,20 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
golang.org/x/crypto/x509roots/fallback v0.0.0-20260113154411-7d0074ccc6f1 h1:EBHQuS9qI8xJ96+YRgVV2ahFLUYbWpt1rf3wPfXN2wQ=
golang.org/x/crypto/x509roots/fallback v0.0.0-20260113154411-7d0074ccc6f1/go.mod h1:MEIPiCnxvQEjA4astfaKItNwEVZA5Ki+3+nyGbJ5N18=
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+22 -8
View File
@@ -25,6 +25,11 @@ type Handler struct {
func NewHandler(c *Config) (http.Handler, error) {
ls := webdav.NewMemLS()
logFunc := func(r *http.Request, err error) {
lZap := getRequestLogger(r, c.BehindProxy)
lZap.Debug("handle webdav request", zap.String("method", r.Method), zap.String("path", r.URL.Path), zap.Error(err))
}
h := &Handler{
noPassword: c.NoPassword,
behindProxy: c.BehindProxy,
@@ -42,6 +47,7 @@ func NewHandler(c *Config) (http.Handler, error) {
LockSystem: ls,
directory: c.Directory,
},
Logger: logFunc,
},
},
users: map[string]*handlerUser{},
@@ -60,6 +66,7 @@ func NewHandler(c *Config) (http.Handler, error) {
LockSystem: ls,
directory: u.Directory,
},
Logger: logFunc,
},
}
}
@@ -90,13 +97,12 @@ func NewHandler(c *Config) (http.Handler, error) {
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
user := h.user
lZap := getRequestLogger(r, h.behindProxy)
// Authentication
if len(h.users) > 0 {
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
// Retrieve the real client IP address using the updated helper function
remoteAddr := getRealRemoteIP(r, h.behindProxy)
// Gets the correct user for this request.
username, password, ok := r.BasicAuth()
if !ok {
@@ -107,26 +113,26 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
user, ok = h.users[username]
if !ok {
// Log invalid username
zap.L().Info("invalid username", zap.String("username", username), zap.String("remote_address", remoteAddr))
lZap.Info("invalid username", zap.String("username", username))
http.Error(w, "Not authorized", http.StatusUnauthorized)
return
}
if !h.noPassword && !user.checkPassword(password) {
// Log invalid password
zap.L().Info("invalid password", zap.String("username", username), zap.String("remote_address", remoteAddr))
lZap.Info("invalid password", zap.String("username", username))
http.Error(w, "Not authorized", http.StatusUnauthorized)
return
}
// Log successful authorization
zap.L().Info("user authorized", zap.String("username", username), zap.String("remote_address", remoteAddr))
lZap.Info("user authorized", zap.String("username", username))
}
// Convert the HTTP request into an internal request type
req, err := newRequest(r, h.user.Prefix)
if err != nil {
zap.L().Info("invalid request path or destination", zap.Error(err))
lZap.Info("invalid request path or destination", zap.Error(err))
http.Error(w, "Invalid request path or destination", http.StatusBadRequest)
return
}
@@ -137,7 +143,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return !os.IsNotExist(err)
})
zap.L().Debug("allowed & method & path", zap.Bool("allowed", allowed), zap.String("method", r.Method), zap.String("path", r.URL.Path))
lZap.Debug("allowed & method & path", zap.Bool("allowed", allowed), zap.String("method", r.Method), zap.String("path", r.URL.Path))
if !allowed {
w.WriteHeader(http.StatusForbidden)
@@ -174,6 +180,14 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
user.ServeHTTP(w, r)
}
// getRequestLogger creates a zap.Logger using the request remote ip.
func getRequestLogger(r *http.Request, behindProxy bool) *zap.Logger {
// Retrieve the real client IP address using the updated helper function
remoteAddr := getRealRemoteIP(r, behindProxy)
return zap.L().With(zap.String("remote_address", remoteAddr))
}
// getRealRemoteIP retrieves the client's actual IP address, considering reverse proxies.
func getRealRemoteIP(r *http.Request, behindProxy bool) string {
if behindProxy {
+2
View File
@@ -2,6 +2,8 @@ package main
import (
"github.com/hacdias/webdav/v5/cmd"
_ "golang.org/x/crypto/x509roots/fallback"
)
func main() {
+4 -2
View File
@@ -4,10 +4,12 @@
"config:recommended",
"group:allNonMajor",
"group:allDigest",
":disableDependencyDashboard"
":disableDependencyDashboard",
":semanticCommitTypeAll(chore)"
],
"postUpdateOptions": [
"gomodUpdateImportPaths",
"gomodTidy"
]
],
"schedule": "* * * * 0,6"
}