diff --git a/lib/router/router.go b/lib/router/router.go index 1e058524..ed82ff79 100644 --- a/lib/router/router.go +++ b/lib/router/router.go @@ -64,7 +64,7 @@ func (router *Router) addRoute(method string, pattern string, handler http.Handl if substring == "*" { return "(.*)" } else { - return "([^/]+)" + return "([^/]+)/?" } }) diff --git a/src/http-proxy-service/config/proxyConfig.yaml b/src/http-proxy-service/config/proxyConfig.yaml index 42115578..b4a10faf 100644 --- a/src/http-proxy-service/config/proxyConfig.yaml +++ b/src/http-proxy-service/config/proxyConfig.yaml @@ -5,7 +5,7 @@ proxy: context: /api/v1/user target: http://localhost:3001/api/v1/user - name: Shoppinglist Service (Lists) - context: /api/v1/shoppinglist (Lists) + context: /api/v1/shoppinglist target: http://localhost:3002/api/v1/shoppinglist - name: Shoppinglist Service (Entries) context: /api/v1/shoppinglistentries @@ -14,7 +14,7 @@ proxy: context: /api/v1/product target: http://localhost:3003/api/v1/product - name: Data Processing Service - context: /api/v1//processing + context: /api/v1/processing target: http://localhost:3004/api/v1/processing - name: Web Service context: diff --git a/src/http-proxy-service/go.mod b/src/http-proxy-service/go.mod index 3afbee88..156228d1 100644 --- a/src/http-proxy-service/go.mod +++ b/src/http-proxy-service/go.mod @@ -1,6 +1,6 @@ module hsfl.de/group6/hsfl-master-ai-cloud-engineering/http-proxy-service -go 1.21.2 +go 1.21 require ( github.com/fsnotify/fsnotify v1.7.0 // indirect diff --git a/src/http-proxy-service/main.go b/src/http-proxy-service/main.go index 32901e11..5ae2866d 100644 --- a/src/http-proxy-service/main.go +++ b/src/http-proxy-service/main.go @@ -1,89 +1,16 @@ package main import ( - "github.com/spf13/viper" - "hsfl.de/group6/hsfl-master-ai-cloud-engineering/lib/router" + "hsfl.de/group6/hsfl-master-ai-cloud-engineering/http-proxy-service/proxy" + "hsfl.de/group6/hsfl-master-ai-cloud-engineering/http-proxy-service/proxy/proxyutils" "log" "net/http" - "net/http/httputil" - "net/url" ) -type ProxyRoute struct { - Name string `mapstructure:"name"` - Context string `mapstructure:"context"` - Target string `mapstructure:"target"` -} - -type ProxyConfig struct { - ListenAddress string `mapstructure:"listenAddress"` - ProxyRoutes []ProxyRoute `mapstructure:"proxyRoutes"` -} - func main() { - // Load config - proxyConfig := readProxyConfiguration() - - // Prepare routing - routing := router.New() - - for _, route := range proxyConfig.ProxyRoutes { - proxy, err := newProxy(route.Target) - if err != nil { - panic(err) - } - - log.Printf("Mapping '%v' | %v ---> %v", route.Name, route.Context, route.Target) - - routing.ALL(route.Context+"/*", newHandler(proxy)) - } + proxyConfig := proxyutils.ReadDefaultProxyManagerConfiguration("./config", "proxyConfig") + proxyManager := proxy.NewDefaultManager(proxyConfig) log.Printf("Listening on %v", proxyConfig.ListenAddress) - log.Fatal(http.ListenAndServe(proxyConfig.ListenAddress, routing)) -} - -func readProxyConfiguration() *ProxyConfig { - viper.AddConfigPath("./config") - viper.SetConfigType("yaml") - viper.SetConfigName("proxyConfig") - - err := viper.ReadInConfig() - if err != nil { - log.Fatalf("Error while loading proxy configuration: %v", err) - } - viper.AutomaticEnv() - - proxyConfig := &ProxyConfig{} - - err = viper.UnmarshalKey("proxy", proxyConfig) - if err != nil { - panic(err) - } - - return proxyConfig -} - -func newProxy(targetUrl string) (*httputil.ReverseProxy, error) { - target, err := url.Parse(targetUrl) - if err != nil { - return nil, err - } - proxy := httputil.NewSingleHostReverseProxy(target) - proxy.ModifyResponse = func(response *http.Response) error { - dumpResponse, err := httputil.DumpResponse(response, false) - if err != nil { - return err - } - log.Println("Response: \r\n", string(dumpResponse)) - return nil - } - return proxy, nil -} - -func newHandler(p *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { - r.URL.Path = r.Context().Value("wildcard0").(string) - log.Println("Request URL: ", r.URL.String()) - p.ServeHTTP(w, r) - } + log.Fatal(http.ListenAndServe(proxyConfig.ListenAddress, proxyManager.GetProxyRouter())) } diff --git a/src/http-proxy-service/proxy/default_manager.go b/src/http-proxy-service/proxy/default_manager.go new file mode 100644 index 00000000..31aa963c --- /dev/null +++ b/src/http-proxy-service/proxy/default_manager.go @@ -0,0 +1,80 @@ +package proxy + +import ( + "hsfl.de/group6/hsfl-master-ai-cloud-engineering/lib/router" + "log" + "net/http" + "net/http/httputil" + "net/url" +) + +type Route struct { + Name string `mapstructure:"name"` + Context string `mapstructure:"context"` + Target string `mapstructure:"target"` +} + +type Config struct { + ListenAddress string `mapstructure:"listenAddress"` + ProxyRoutes []Route `mapstructure:"proxyRoutes"` +} + +type defaultManager struct { + proxies []*httputil.ReverseProxy + routing *router.Router +} + +func NewDefaultManager(config *Config) *defaultManager { + proxyManager := defaultManager{} + + // Prepare routing + proxyManager.routing = router.New() + + for _, route := range config.ProxyRoutes { + proxy, err := proxyManager.newProxy(route.Target) + if err != nil { + panic(err) + } + + proxyManager.newHandler(proxy) + proxyManager.proxies = append(proxyManager.proxies, proxy) + + proxyManager.routing.ALL(route.Context+"/*", proxyManager.newHandler(proxy)) + + log.Printf("Mapping '%v' | %v ---> %v", route.Name, route.Context, route.Target) + } + + return &proxyManager +} + +func (dp defaultManager) GetProxyRouter() *router.Router { + return dp.routing +} + +func (dp defaultManager) newProxy(targetUrl string) (*httputil.ReverseProxy, error) { + target, err := url.Parse(targetUrl) + if err != nil { + return nil, err + } + proxy := httputil.NewSingleHostReverseProxy(target) + proxy.ModifyResponse = func(response *http.Response) error { + dumpResponse, err := httputil.DumpResponse(response, false) + if err != nil { + return err + } + log.Println("Response: \r\n", string(dumpResponse)) + return nil + } + + dp.proxies = append(dp.proxies, proxy) + + return proxy, nil +} + +func (dp defaultManager) newHandler(p *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + r.URL.Path = r.Context().Value("wildcard0").(string) + log.Println("Request URL: ", r.URL.String()) + p.ServeHTTP(w, r) + } +} diff --git a/src/http-proxy-service/proxy/manager.go b/src/http-proxy-service/proxy/manager.go new file mode 100644 index 00000000..5c1e7074 --- /dev/null +++ b/src/http-proxy-service/proxy/manager.go @@ -0,0 +1,13 @@ +package proxy + +import ( + "hsfl.de/group6/hsfl-master-ai-cloud-engineering/lib/router" + "net/http" + "net/http/httputil" +) + +type Manager interface { + GetProxyRouter() *router.Router + newProxy(targetUrl string) (*httputil.ReverseProxy, error) + newHandler(p *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) +} diff --git a/src/http-proxy-service/proxy/proxyutils/ReadDefaultProxyManagerConfiguration.go b/src/http-proxy-service/proxy/proxyutils/ReadDefaultProxyManagerConfiguration.go new file mode 100644 index 00000000..0e2726bb --- /dev/null +++ b/src/http-proxy-service/proxy/proxyutils/ReadDefaultProxyManagerConfiguration.go @@ -0,0 +1,28 @@ +package proxyutils + +import ( + "github.com/spf13/viper" + "hsfl.de/group6/hsfl-master-ai-cloud-engineering/http-proxy-service/proxy" + "log" +) + +func ReadDefaultProxyManagerConfiguration(path string, filename string) *proxy.Config { + viper.AddConfigPath(path) + viper.SetConfigType("yaml") + viper.SetConfigName(filename) + + err := viper.ReadInConfig() + if err != nil { + log.Fatalf("Error while loading proxy configuration: %v", err) + } + viper.AutomaticEnv() + + proxyConfig := &proxy.Config{} + + err = viper.UnmarshalKey("proxy", proxyConfig) + if err != nil { + panic(err) + } + + return proxyConfig +}