-
Notifications
You must be signed in to change notification settings - Fork 13
/
gateway.go
131 lines (108 loc) · 3.36 KB
/
gateway.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
package frontman
import (
"context"
"log"
"net/http"
"os"
"strings"
"github.com/go-redis/redis/v9"
"github.com/gorilla/mux"
)
// Gateway contains the backend services and the router
type Gateway struct {
router *mux.Router
service *mux.Router
backendServices *BackendServices
}
func NewRedisClient(ctx context.Context, uri string) (*redis.Client, error) {
opt, err := redis.ParseURL(uri)
if err != nil {
return nil, err
}
client := redis.NewClient(opt)
_, err = client.Ping(ctx).Result()
if err != nil {
return nil, err
}
return client, nil
}
func NewServicesRouter(backendServices *BackendServices) *mux.Router {
router := mux.NewRouter()
router.HandleFunc("/api/services", getServicesHandler(backendServices)).Methods("GET")
router.HandleFunc("/api/services", addServiceHandler(backendServices)).Methods("POST")
router.HandleFunc("/api/services/{name}", removeServiceHandler(backendServices)).Methods("DELETE")
router.HandleFunc("/api/services/{name}", updateServiceHandler(backendServices)).Methods("PUT")
router.HandleFunc("/api/health", getHealthHandler(backendServices)).Methods("GET")
return router
}
// NewGateway creates a new Gateway instance with a Redis client connection factory
func NewGateway(redisFactory func(ctx context.Context, uri string) (*redis.Client, error)) (*Gateway, error) {
// Retrieve the Redis client connection from the factory
ctx := context.Background()
// Retrieve the database URI from the environment variables
uri := os.Getenv("FRONTMAN_REDIS_URL")
if uri == "" {
log.Fatal("FRONTMAN_REDIS_URL environment variable is not set")
}
redisClient, err := redisFactory(ctx, uri)
if err != nil {
return nil, err
}
// Create a new BackendServices instance
backendServices, err := NewBackendServices(ctx, redisClient)
if err != nil {
return nil, err
}
servicesRouter := NewServicesRouter(backendServices)
// Create a new router instance
proxyRouter := mux.NewRouter()
proxyRouter.HandleFunc("/{proxyPath:.+}", gatewayHandler(backendServices)).Methods("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS").MatcherFunc(func(r *http.Request, rm *mux.RouteMatch) bool {
vars := mux.Vars(r)
proxyPath := vars["proxyPath"]
for _, prefix := range []string{"/api/"} {
if strings.HasPrefix(proxyPath, prefix) {
return false
}
}
return true
})
// Create the Gateway instance
return &Gateway{
router: proxyRouter,
service: servicesRouter,
backendServices: backendServices,
}, nil
}
// Start starts the server
func (gw *Gateway) Start() error {
// Create a new HTTP server instance for the /api/services endpoint
apiAddr := os.Getenv("FRONTMAN_API_ADDR")
if apiAddr == "" {
apiAddr = "0.0.0.0:8080"
}
gatewayAddr := os.Getenv("FRONTMAN_GATEWAY_ADDR")
if gatewayAddr == "" {
gatewayAddr = "0.0.0.0:8000"
}
api := &http.Server{
Addr: apiAddr,
Handler: gw.service,
}
gateway := &http.Server{
Addr: gatewayAddr,
Handler: gw.router,
}
// Start the main HTTP server
log.Println("Starting Frontman Gateway...")
go func() {
if err := gateway.ListenAndServe(); err != nil {
log.Fatalf("Failed to start Frontman Gateway: %v", err)
}
}()
// Start the /api/services HTTP server
log.Println("Starting /api/services endpoint...")
if err := api.ListenAndServe(); err != nil {
log.Fatalf("Failed to start /api/services endpoint: %v", err)
}
return nil
}