-
Notifications
You must be signed in to change notification settings - Fork 1
/
middleware.go
134 lines (124 loc) · 4.11 KB
/
middleware.go
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package goproxy
import (
"encoding/json"
"io"
"log"
"net/http"
"strings"
"github.com/rs/zerolog"
"github.com/sirkon/goproxy/router"
"github.com/sirkon/goproxy/source"
)
// Middleware acts as go proxy with given router.
// transportPrefix is a head part of URL path which refers to address of go proxy before the module info. For example,
// if we serving go proxy at https://0.0.0.0:8081/goproxy/..., transportPrefix will be "/goproxy"
func Middleware(r *router.Router, transportPrefix string, logger *zerolog.Logger) http.Handler {
return middleware{
prefix: transportPrefix,
router: r,
logger: logger,
}
}
// middleware
type middleware struct {
prefix string
router *router.Router
logger *zerolog.Logger
}
func (m middleware) ServeHTTP(w http.ResponseWriter, req *http.Request) {
path, suffix, err := source.GetModInfo(req, m.prefix)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
logger := m.logger.With().Timestamp().Str("request", req.URL.Path).Str("module", path)
factory := m.router.Factory(path)
if factory == nil {
tmpLogger := logger.Logger()
(&tmpLogger).Error().Msgf("no proxy handlers registered for %s", path)
w.WriteHeader(http.StatusBadRequest)
return
}
src, err := factory.Source(req, m.prefix)
if err != nil {
tmpLogger := logger.Logger()
(&tmpLogger).Error().Err(err)
w.WriteHeader(http.StatusBadRequest)
return
}
switch {
case suffix == "list":
tmpLogger := logger.Logger()
ctx := (&tmpLogger).WithContext(req.Context())
(&tmpLogger).Debug().Msg("version list requested")
version, err := src.Versions(ctx, "")
if err != nil {
zerolog.Ctx(ctx).Error().Err(err).Msg("failed to get version list")
w.WriteHeader(http.StatusBadRequest)
return
}
w.WriteHeader(http.StatusOK)
if _, err := io.WriteString(w, strings.Join(version, "\n")); err != nil {
zerolog.Ctx(ctx).Error().Err(err).Msg("failed to write list response")
}
case strings.HasSuffix(suffix, ".info"):
version := getVersion(suffix)
tmpLogger := logger.Str("version", version).Logger()
ctx := (&tmpLogger).WithContext(req.Context())
(&tmpLogger).Debug().Msg("version info requested")
info, err := src.Stat(ctx, version)
if err != nil {
zerolog.Ctx(ctx).Error().Err(err).Msg("failed to get revision info from source beneath")
w.WriteHeader(http.StatusBadRequest)
return
}
je := json.NewEncoder(w)
if err := je.Encode(info); err != nil {
zerolog.Ctx(ctx).Error().Err(err).Msg("failed to write version info response")
}
case strings.HasSuffix(suffix, ".mod"):
version := getVersion(suffix)
tmpLogger := logger.Str("version", version).Logger()
ctx := (&tmpLogger).WithContext(req.Context())
(&tmpLogger).Debug().Msg("go.mod requested")
gomod, err := src.GoMod(ctx, version)
if err != nil {
zerolog.Ctx(ctx).Error().Err(err).Msg("failed to get go.mod from a source beneath")
w.WriteHeader(http.StatusBadRequest)
return
}
if _, err := w.Write(gomod); err != nil {
zerolog.Ctx(ctx).Error().Err(err).Msg("failed to return go.mod")
log.Printf("failed to write go.mod response: %s", err)
}
case strings.HasSuffix(suffix, ".zip"):
version := getVersion(suffix)
tmpLogger := logger.Str("version", version).Logger()
ctx := (&tmpLogger).WithContext(req.Context())
(&tmpLogger).Debug().Msg("zip archive requested")
archiveReader, err := src.Zip(ctx, version)
if err != nil {
zerolog.Ctx(ctx).Error().Err(err).Msg("failed to get zip archive")
w.WriteHeader(http.StatusBadRequest)
return
}
defer func() {
if err := archiveReader.Close(); err != nil {
zerolog.Ctx(ctx).Error().Err(err).Msgf("failed to close zip reachive reader")
}
}()
if _, err := io.Copy(w, archiveReader); err != nil {
zerolog.Ctx(ctx).Error().Err(err).Msg("failed to return zip archive")
}
default:
tmpLogger := logger.Logger()
(&tmpLogger).Error().Msgf("unsupported suffix %s", suffix)
w.WriteHeader(http.StatusBadRequest)
return
}
}
// getVersion we have something like v0.1.2.zip or v0.1.2.info or v0.1.2.zip in the suffix and need to cut the
func getVersion(suffix string) string {
off := strings.LastIndex(suffix, ".")
return suffix[:off]
}