11package main
22
33import (
4+ "encoding/json"
45 "flag"
56 "fmt"
67 "log"
@@ -9,7 +10,10 @@ import (
910 "net/url"
1011 "os"
1112 "path"
13+ "path/filepath"
1214 "strings"
15+
16+ yaml "gopkg.in/yaml.v3"
1317)
1418
1519// env returns the env var or default
@@ -20,6 +24,41 @@ func env(key, def string) string {
2024 return def
2125}
2226
27+ // configHandler reads and serves the config.yaml file as JSON
28+ func configHandler (configPath string ) http.HandlerFunc {
29+ return func (w http.ResponseWriter , r * http.Request ) {
30+ // Only allow GET requests
31+ if r .Method != http .MethodGet {
32+ http .Error (w , "Method not allowed" , http .StatusMethodNotAllowed )
33+ return
34+ }
35+
36+ // Read the config file
37+ data , err := os .ReadFile (configPath )
38+ if err != nil {
39+ log .Printf ("Error reading config file: %v" , err )
40+ http .Error (w , fmt .Sprintf ("Failed to read config file: %v" , err ), http .StatusInternalServerError )
41+ return
42+ }
43+
44+ // Parse YAML
45+ var config interface {}
46+ if err := yaml .Unmarshal (data , & config ); err != nil {
47+ log .Printf ("Error parsing config YAML: %v" , err )
48+ http .Error (w , fmt .Sprintf ("Failed to parse config: %v" , err ), http .StatusInternalServerError )
49+ return
50+ }
51+
52+ // Convert to JSON and send response
53+ w .Header ().Set ("Content-Type" , "application/json" )
54+ if err := json .NewEncoder (w ).Encode (config ); err != nil {
55+ log .Printf ("Error encoding config to JSON: %v" , err )
56+ http .Error (w , fmt .Sprintf ("Failed to encode config: %v" , err ), http .StatusInternalServerError )
57+ return
58+ }
59+ }
60+ }
61+
2362// newReverseProxy creates a reverse proxy to targetBase and strips the given prefix from the incoming path
2463func newReverseProxy (targetBase , stripPrefix string , forwardAuth bool ) (* httputil.ReverseProxy , error ) {
2564 targetURL , err := url .Parse (targetBase )
@@ -143,6 +182,7 @@ func main() {
143182 // Flags/env for configuration
144183 port := flag .String ("port" , env ("DASHBOARD_PORT" , "8700" ), "dashboard port" )
145184 staticDir := flag .String ("static" , env ("DASHBOARD_STATIC_DIR" , "../frontend" ), "static assets directory" )
185+ configFile := flag .String ("config" , env ("ROUTER_CONFIG_PATH" , "../../config/config.yaml" ), "path to config.yaml" )
146186
147187 // Upstream targets
148188 grafanaURL := flag .String ("grafana" , env ("TARGET_GRAFANA_URL" , "" ), "Grafana base URL" )
@@ -153,6 +193,13 @@ func main() {
153193
154194 flag .Parse ()
155195
196+ // Resolve config file path to absolute path
197+ absConfigPath , err := filepath .Abs (* configFile )
198+ if err != nil {
199+ log .Fatalf ("Failed to resolve config path: %v" , err )
200+ }
201+ log .Printf ("Config file path: %s" , absConfigPath )
202+
156203 mux := http .NewServeMux ()
157204
158205 // Health check endpoint
@@ -162,6 +209,10 @@ func main() {
162209 w .Write ([]byte (`{"status":"healthy","service":"semantic-router-dashboard"}` ))
163210 })
164211
212+ // Config endpoint - serve the config.yaml as JSON
213+ mux .HandleFunc ("/api/router/config/all" , configHandler (absConfigPath ))
214+ log .Printf ("Config API endpoint registered: /api/router/config/all" )
215+
165216 // Router API proxy (forward Authorization) - MUST be registered before Grafana
166217 var routerAPIProxy * httputil.ReverseProxy
167218 if * routerAPI != "" {
0 commit comments