-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathversion.go
More file actions
91 lines (72 loc) · 2.08 KB
/
Copy pathversion.go
File metadata and controls
91 lines (72 loc) · 2.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package sprites
import (
"net/http"
"regexp"
"strings"
"sync/atomic"
"github.com/Masterminds/semver/v3"
)
// Minimum RC version that supports path-based attach endpoint
var attachPathMinRC = semver.MustParse("0.0.1-rc30")
// extractChannel returns the release channel from a version string.
// Returns "dev", "rc", or "release".
func extractChannel(version string) string {
version = strings.TrimPrefix(version, "v")
// Handle X.Y.Z-dev-<sha> format
if strings.Contains(version, "-dev-") || strings.HasSuffix(version, "-dev") {
return "dev"
}
// Match pattern like -rc1, -dev1, etc.
re := regexp.MustCompile(`-([a-zA-Z]+)\d*$`)
matches := re.FindStringSubmatch(version)
if len(matches) > 1 {
suffix := matches[1]
if strings.HasPrefix(suffix, "dev") {
return "dev"
}
if strings.HasPrefix(suffix, "rc") {
return "rc"
}
return suffix
}
return "release"
}
// supportsPathAttach returns true if the server version supports
// the path-based attach endpoint (/exec/:id).
// Returns false for unknown versions or versions <= rc29.
func supportsPathAttach(version string) bool {
if version == "" {
return false
}
channel := extractChannel(version)
// Dev versions always support path attach
if channel == "dev" {
return true
}
// Parse version for comparison
v, err := semver.NewVersion(strings.TrimPrefix(version, "v"))
if err != nil {
return false // Cannot parse, use safe default
}
// RC versions: support path attach if >= rc30
if channel == "rc" {
return v.GreaterThan(attachPathMinRC) || v.Equal(attachPathMinRC)
}
// Release versions: support path attach
return true
}
// versionCapturingTransport wraps an http.RoundTripper to capture Sprite-Version headers.
type versionCapturingTransport struct {
wrapped http.RoundTripper
versionHolder *atomic.Value
}
func (t *versionCapturingTransport) RoundTrip(req *http.Request) (*http.Response, error) {
resp, err := t.wrapped.RoundTrip(req)
if err != nil {
return resp, err
}
if version := resp.Header.Get("Sprite-Version"); version != "" {
t.versionHolder.Store(version)
}
return resp, err
}