Skip to content

Commit a6eb876

Browse files
committed
add web-ui
1 parent 42ea05f commit a6eb876

13 files changed

Lines changed: 18313 additions & 16 deletions

File tree

.gitignore

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,44 @@ Thumbs.db
3939
dist/
4040

4141
# Analyzer
42-
analyzer.json
42+
analyzer.json
43+
internal/analyzer/ui/
44+
45+
# Node.js
46+
node_modules/
47+
npm-debug.log*
48+
yarn-debug.log*
49+
yarn-error.log*
50+
.pnpm-debug.log*
51+
52+
# React / UI
53+
ui/build/
54+
ui/.env.local
55+
ui/.env.development.local
56+
ui/.env.test.local
57+
ui/.env.production.local
58+
ui/coverage/
59+
ui/.pnp
60+
ui/.pnp.js
61+
62+
# TypeScript
63+
*.tsbuildinfo
64+
next-env.d.ts
65+
66+
# Testing
67+
ui/coverage/
68+
ui/.nyc_output/
69+
70+
# Production
71+
ui/build/
72+
ui/dist/
73+
74+
# Misc
75+
ui/.DS_Store
76+
ui/.env.local
77+
ui/.env.development.local
78+
ui/.env.test.local
79+
ui/.env.production.local
80+
ui/npm-debug.log*
81+
ui/yarn-debug.log*
82+
ui/yarn-error.log*

examples/shop/shop_test.go

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,6 @@ func doPost(t *testing.T, path string, body any) *http.Response {
4040
return resp
4141
}
4242

43-
func doDelete(t *testing.T, path string) *http.Response {
44-
req, _ := http.NewRequest(http.MethodDelete, baseURL+path, nil)
45-
resp, err := http.DefaultClient.Do(req)
46-
if err != nil {
47-
t.Fatalf("DELETE %s failed: %v", path, err)
48-
}
49-
return resp
50-
}
51-
5243
// --- Test Cases ---
5344

5445
func TestGetProducts(t *testing.T) {

internal/analyzer/server.go

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import (
44
"encoding/json"
55
"log"
66
"net/http"
7+
"os"
8+
"path/filepath"
9+
"strings"
710
)
811

912
// Server represents the analyzer HTTP server
@@ -20,11 +23,44 @@ func NewServer(analyzer *Analyzer) *Server {
2023

2124
// Start starts the analyzer server
2225
func (s *Server) Start(addr string) error {
23-
http.HandleFunc("/health", s.handleHealth)
24-
http.HandleFunc("/analyzer", s.handleAnalyzer)
25-
http.HandleFunc("/openapi.json", s.handleOpenAPI)
26-
http.HandleFunc("/postman.json", s.handlePostman)
27-
http.HandleFunc("/", s.handleSwaggerUI)
26+
// API endpoints
27+
http.HandleFunc("/api/health", s.handleHealth)
28+
http.HandleFunc("/api/analyzer", s.handleAnalyzer)
29+
http.HandleFunc("/api/openapi.json", s.handleOpenAPI)
30+
http.HandleFunc("/api/postman.json", s.handlePostman)
31+
http.HandleFunc("/swagger", s.handleSwaggerUI)
32+
33+
// Handle OPTIONS requests for CORS
34+
http.HandleFunc("/api/", func(w http.ResponseWriter, r *http.Request) {
35+
if r.Method == http.MethodOptions {
36+
w.Header().Set("Access-Control-Allow-Origin", "*")
37+
w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
38+
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
39+
w.WriteHeader(http.StatusOK)
40+
return
41+
}
42+
http.NotFound(w, r)
43+
})
44+
45+
// Serve static UI files
46+
fs := http.FileServer(http.Dir("internal/analyzer/ui"))
47+
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
48+
// If the request is for an API endpoint, return 404
49+
if strings.HasPrefix(r.URL.Path, "/api/") {
50+
http.NotFound(w, r)
51+
return
52+
}
53+
54+
// For all other requests, serve the UI
55+
// If the path doesn't exist, serve index.html for client-side routing
56+
path := filepath.Join("internal/analyzer/ui", r.URL.Path)
57+
if _, err := os.Stat(path); err != nil {
58+
http.ServeFile(w, r, "internal/analyzer/ui/index.html")
59+
return
60+
}
61+
fs.ServeHTTP(w, r)
62+
})
63+
2864
log.Printf("Analyzer server listening on %s", addr)
2965
return http.ListenAndServe(addr, nil)
3066
}
@@ -36,6 +72,11 @@ func (s *Server) handleAnalyzer(w http.ResponseWriter, r *http.Request) {
3672
return
3773
}
3874

75+
// Add CORS headers
76+
w.Header().Set("Access-Control-Allow-Origin", "*")
77+
w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
78+
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
79+
3980
data := s.analyzer.GetData()
4081
w.Header().Set("Content-Type", "application/json")
4182
json.NewEncoder(w).Encode(data)
@@ -48,6 +89,11 @@ func (s *Server) handleOpenAPI(w http.ResponseWriter, r *http.Request) {
4889
return
4990
}
5091

92+
// Add CORS headers
93+
w.Header().Set("Access-Control-Allow-Origin", "*")
94+
w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
95+
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
96+
5197
openAPI := s.analyzer.GenerateOpenAPI()
5298
w.Header().Set("Content-Type", "application/json")
5399
json.NewEncoder(w).Encode(openAPI)
@@ -60,6 +106,11 @@ func (s *Server) handlePostman(w http.ResponseWriter, r *http.Request) {
60106
return
61107
}
62108

109+
// Add CORS headers
110+
w.Header().Set("Access-Control-Allow-Origin", "*")
111+
w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
112+
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
113+
63114
collection := s.analyzer.GeneratePostmanCollection()
64115
w.Header().Set("Content-Type", "application/json")
65116
w.Header().Set("Content-Disposition", "attachment; filename=api-collection.json")
@@ -72,6 +123,12 @@ func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) {
72123
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
73124
return
74125
}
126+
127+
// Add CORS headers
128+
w.Header().Set("Access-Control-Allow-Origin", "*")
129+
w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
130+
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
131+
75132
w.Header().Set("Content-Type", "application/json")
76133
json.NewEncoder(w).Encode(map[string]string{"status": "healthy"})
77134
}

internal/analyzer/swagger_ui.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const swaggerUITemplate = `<!DOCTYPE html>
2121
<script>
2222
window.onload = () => {
2323
window.ui = SwaggerUIBundle({
24-
url: "/openapi.json",
24+
url: "/api/openapi.json",
2525
dom_id: '#swagger-ui',
2626
deepLinking: true,
2727
presets: [

0 commit comments

Comments
 (0)