forked from gomods/athens
/
app.go
148 lines (130 loc) · 4.55 KB
/
app.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package actions
import (
"github.com/gobuffalo/buffalo"
"github.com/gobuffalo/buffalo/middleware"
"github.com/gobuffalo/buffalo/middleware/csrf"
"github.com/gobuffalo/buffalo/middleware/i18n"
"github.com/gobuffalo/buffalo/middleware/ssl"
"github.com/gobuffalo/buffalo/worker"
"github.com/gobuffalo/gocraft-work-adapter"
"github.com/gobuffalo/packr"
"github.com/gocraft/work"
"github.com/gomods/athens/pkg/cdn/metadata/azurecdn"
"github.com/gomods/athens/pkg/config/env"
"github.com/gomods/athens/pkg/download"
"github.com/gomods/athens/pkg/download/goget"
"github.com/gomods/athens/pkg/eventlog"
"github.com/gomods/athens/pkg/log"
"github.com/gomods/athens/pkg/storage"
"github.com/gomodule/redigo/redis"
"github.com/rs/cors"
"github.com/unrolled/secure"
)
// AppConfig contains dependencies used in App
type AppConfig struct {
Storage storage.Backend
EventLog eventlog.Eventlog
CacheMissesLog eventlog.Appender
}
const (
// OlympusWorkerName is the name of the Olympus worker
OlympusWorkerName = "olympus-worker"
// DownloadHandlerName is name of the handler downloading packages from VCS
DownloadHandlerName = "download-handler"
// PushNotificationHandlerName is the name of the handler processing push notifications
PushNotificationHandlerName = "push-notification-worker"
)
var (
workerQueue = "default"
workerModuleKey = "module"
workerVersionKey = "version"
workerPushNotificationKey = "push-notification"
// ENV is used to help switch settings based on where the
// application is being run. Default is "development".
ENV = env.GoEnvironmentWithDefault("development")
// T is buffalo Translator
T *i18n.Translator
)
// App is where all routes and middleware for buffalo should be defined.
// This is the nerve center of your application.
func App(config *AppConfig) (*buffalo.App, error) {
port := env.Port(":3001")
w, err := getWorker(config.Storage, config.EventLog)
if err != nil {
return nil, err
}
lggr := log.New(env.CloudRuntime(), env.LogLevel())
app := buffalo.New(buffalo.Options{
Addr: port,
Env: ENV,
PreWares: []buffalo.PreWare{
cors.Default().Handler,
},
SessionName: "_olympus_session",
Worker: w,
Logger: log.Buffalo(),
})
// Automatically redirect to SSL
app.Use(ssl.ForceSSL(secure.Options{
SSLRedirect: ENV == "production",
SSLProxyHeaders: map[string]string{"X-Forwarded-Proto": "https"},
}))
if ENV == "development" {
app.Use(middleware.ParameterLogger)
}
initializeTracing(app)
// Protect against CSRF attacks. https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)
// Remove to disable this.
if env.EnableCSRFProtection() {
csrfMiddleware := csrf.New
app.Use(csrfMiddleware)
}
// TODO: parameterize the GoGet getter here.
//
// Defaulting to Azure for now
app.Use(GoGet(azurecdn.Metadata{
// TODO: initialize the azurecdn.Storage struct here
}))
// Wraps each request in a transaction.
// c.Value("tx").(*pop.PopTransaction)
// Remove to disable this.
// app.Use(middleware.PopTransaction(models.DB))
// Setup and use translations:
if T, err = i18n.New(packr.NewBox("../locales"), "en-US"); err != nil {
app.Stop(err)
}
app.Use(T.Middleware())
app.GET("/diff/{lastID}", diffHandler(config.Storage, config.EventLog))
app.GET("/feed/{lastID}", feedHandler(config.Storage))
app.GET("/eventlog/{sequence_id}", eventlogHandler(config.EventLog))
app.POST("/cachemiss", cachemissHandler(w))
app.POST("/push", pushNotificationHandler(w))
// Download Protocol
dp := download.New(goget.New(), config.Storage)
app.GET(download.PathList, download.ListHandler(dp, lggr, renderEng))
app.GET(download.PathVersionInfo, download.VersionInfoHandler(dp, lggr, renderEng))
app.GET(download.PathVersionModule, download.VersionModuleHandler(dp, lggr, renderEng))
app.GET(download.PathVersionZip, download.VersionZipHandler(dp, lggr, renderEng))
app.ServeFiles("/", assetsBox) // serve files from the public directory
return app, nil
}
func getWorker(store storage.Backend, eLog eventlog.Eventlog) (worker.Worker, error) {
port := env.OlympusRedisQueuePortWithDefault(":6379")
w := gwa.New(gwa.Options{
Pool: &redis.Pool{
MaxActive: 5,
MaxIdle: 5,
Wait: true,
Dial: func() (redis.Conn, error) {
return redis.Dial("tcp", port)
},
},
Name: OlympusWorkerName,
MaxConcurrency: env.AthensMaxConcurrency(),
})
opts := work.JobOptions{
SkipDead: true,
MaxFails: env.WorkerMaxFails(),
}
return w, w.RegisterWithOptions(PushNotificationHandlerName, opts, GetProcessPushNotificationJob(store, eLog))
}