This repository has been archived by the owner on Sep 14, 2022. It is now read-only.
/
api.go
115 lines (103 loc) · 3.09 KB
/
api.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
package main
import (
"expvar"
"net/http"
"github.com/CSCfi/qvain-api/pkg/metax"
"github.com/rs/zerolog"
)
// Root configures a http.Handler for routing HTTP requests to the root URL.
func Root(config *Config) http.Handler {
apis := NewApis(config)
apiHandler := http.Handler(apis)
if config.LogRequests {
// wrap apiHandler with request logging middleware
apiHandler = makeLoggingHandler("/api", apiHandler, config.NewLogger("request"))
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch ShiftUrlWithTrailing(r) {
case "api/":
apiHandler.ServeHTTP(w, r)
case "":
ifGet(w, r, welcome)
default:
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
}
})
}
// Apis holds configured API endpoints.
type Apis struct {
config *Config
logger zerolog.Logger
datasets *DatasetApi
sessions *SessionApi
auth *AuthApi
proxy *ApiProxy
lookup *LookupApi
stats *StatsApi
}
// NewApis constructs a collection of APIs with a given configuration.
func NewApis(config *Config) *Apis {
apis := &Apis{
config: config,
logger: config.NewLogger("apis"),
}
metax := metax.NewMetaxService(config.MetaxApiHost,
metax.WithCredentials(config.metaxApiUser, config.metaxApiPass),
metax.WithInsecureCertificates(config.DevMode))
apis.datasets = NewDatasetApi(config.db, config.sessions, metax, config.NewLogger("datasets"))
apis.sessions = NewSessionApi(
config.sessions,
config.NewLogger("sessions"),
config.oidcProviderUrl+config.oidcLogoutPath,
)
apis.auth = NewAuthApi(config, makeOnFairdataLogin(metax, config.db, config.NewLogger("sync")), config.NewLogger("auth"))
apis.proxy = NewApiProxy(
"https://"+config.MetaxApiHost+"/rest/",
config.metaxApiUser,
config.metaxApiPass,
config.sessions,
config.NewLogger("proxy"),
config.DevMode,
)
apis.lookup = NewLookupApi(config.db, config.NewLogger("lookup"), config.qvainLookupApiKey)
apis.stats = NewStatsApi(config.db, config.NewLogger("stats"), config.qvainStatsApiKey)
return apis
}
// ServeHTTP is a http.Handler that delegates to the requested API endpoint.
func (apis *Apis) ServeHTTP(w http.ResponseWriter, r *http.Request) {
head := ShiftUrlWithTrailing(r)
apis.logger.Debug().Str("head", head).Str("path", r.URL.Path).Msg("apis")
switch head {
case "datasets/":
datasetsC.Add(1)
apis.datasets.ServeHTTP(w, r)
case "sessions/":
sessionsC.Add(1)
apis.sessions.ServeHTTP(w, r)
case "auth/":
authC.Add(1)
apis.auth.ServeHTTP(w, r)
case "proxy/":
proxyC.Add(1)
apis.proxy.ServeHTTP(w, r)
case "lookup/":
lookupC.Add(1)
apis.lookup.ServeHTTP(w, r)
case "stats/":
statsC.Add(1)
apis.stats.ServeHTTP(w, r)
case "version":
versionC.Add(1)
ifGet(w, r, apiVersion)
case "vars":
if apis.config.DevMode {
expvar.Handler().ServeHTTP(w, r)
} else {
jsonError(w, "unknown api called: "+TrimSlash(head), http.StatusNotFound)
}
case "":
ifGet(w, r, welcome)
default:
loggedJSONError(w, "unknown api called: "+TrimSlash(head), http.StatusNotFound, &apis.logger).Str("head", head).Str("path", r.URL.Path).Msg("Error in api.serveHTTP()")
}
}