Skip to content

Commit fb62bf0

Browse files
committed
fix: detect buggy apt versions
1 parent 5458513 commit fb62bf0

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

.github/workflows/build-publish.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,6 @@ jobs:
3535

3636
- name: Build containers
3737
run: |
38-
ko build --bare --sbom=none --platform linux/amd64,linux/arm64 -t latest .
38+
ko build --bare --sbom=none --platform linux/amd64,linux/arm64 -t latest,$GITHUB_RUN_NUMBER .
3939
env:
4040
KO_DOCKER_REPO: ghcr.io/syncthing/infra/apt-web

main.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"net/url"
1414
"os"
1515
"path"
16+
"strconv"
1617
"strings"
1718
"sync"
1819
"time"
@@ -160,6 +161,12 @@ func (r *githubRedirector) Serve(ctx context.Context) error {
160161
}
161162

162163
func (r *githubRedirector) ServeHTTP(w http.ResponseWriter, req *http.Request) {
164+
if r.buggyAPTVersion(req) {
165+
slog.Info("serving proxied for buggy APT", "ua", req.Header.Get("User-Agent"))
166+
r.next.ServeHTTP(w, req)
167+
return
168+
}
169+
163170
file := path.Base(req.URL.Path)
164171
if unesc, err := url.PathUnescape(file); err == nil {
165172
file = unesc
@@ -210,6 +217,45 @@ func (r *githubRedirector) fetchGithubReleaseAssets(ctx context.Context, url str
210217
return assets, nil
211218
}
212219

220+
// buggyAPTVersion returns true for APT versions that can't properly handle
221+
// a redirect to a signed object storage URL.
222+
func (r *githubRedirector) buggyAPTVersion(req *http.Request) bool {
223+
// "Debian APT-HTTP/1.3 (1.6.18)"
224+
// "Debian APT-HTTP/1.3 (2.2.4)"
225+
// "Debian APT-HTTP/1.3 (2.4.13)"
226+
// "Debian APT-HTTP/1.3 (2.7.14)"
227+
fields := strings.Fields(req.Header.Get("User-Agent"))
228+
if len(fields) < 3 {
229+
return false
230+
}
231+
if fields[0] != "Debian" || !strings.HasPrefix(fields[1], "APT") {
232+
return false
233+
}
234+
parts := strings.Split(strings.Trim(fields[2], "()"), ".")
235+
if len(parts) < 2 {
236+
return false
237+
}
238+
239+
// Major versions lower than 2 are guaranteed buggy, higher should be
240+
// fine. Precisely equals two requires further investigation.
241+
if maj, err := strconv.ParseInt(parts[0], 10, 32); err != nil {
242+
return false
243+
} else if maj < 2 {
244+
return true
245+
} else if maj > 2 {
246+
return false
247+
}
248+
249+
// Minor versions lower than 2 are buggy.
250+
if min, err := strconv.ParseInt(parts[1], 10, 32); err != nil {
251+
return false
252+
} else if min < 2 {
253+
return true
254+
}
255+
256+
return false
257+
}
258+
213259
type asService func(ctx context.Context) error
214260

215261
func (fn asService) Serve(ctx context.Context) error {

0 commit comments

Comments
 (0)