Files
public/Tools/quickly/backend/swagger.go

233 lines
5.4 KiB
Go

package backend
import (
"fmt"
"net"
"net/http"
"os"
"path/filepath"
"strings"
"sync"
"time"
)
type SwaggerFile struct {
Name string `json:"name"`
Path string `json:"path"`
Size int64 `json:"size"`
ModifiedTime string `json:"modifiedTime"`
}
type SwaggerServer struct {
server *http.Server
port int
running bool
mu sync.Mutex
}
var swaggerServer *SwaggerServer
var swaggerServerMu sync.Mutex
func (a *App) GetSwaggerFiles(dirPath string) ([]SwaggerFile, error) {
if dirPath == "" {
return nil, fmt.Errorf("directory path is empty")
}
var files []SwaggerFile
err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
if strings.HasSuffix(strings.ToLower(info.Name()), ".swagger.json") {
files = append(files, SwaggerFile{
Name: info.Name(),
Path: path,
Size: info.Size(),
ModifiedTime: info.ModTime().Format("2006-01-02 15:04:05"),
})
}
return nil
})
if err != nil {
return nil, fmt.Errorf("failed to walk directory: %w", err)
}
return files, nil
}
func (a *App) GetSwaggerFileInfo(filePath string) (SwaggerFile, error) {
if filePath == "" {
return SwaggerFile{}, fmt.Errorf("file path is empty")
}
info, err := os.Stat(filePath)
if err != nil {
return SwaggerFile{}, fmt.Errorf("failed to get file info: %w", err)
}
return SwaggerFile{
Name: info.Name(),
Path: filePath,
Size: info.Size(),
ModifiedTime: info.ModTime().Format("2006-01-02 15:04:05"),
}, nil
}
func (a *App) ReadSwaggerFile(filePath string) (string, error) {
if filePath == "" {
return "", fmt.Errorf("file path is empty")
}
content, err := os.ReadFile(filePath)
if err != nil {
return "", fmt.Errorf("failed to read file: %w", err)
}
return string(content), nil
}
func (a *App) StartSwaggerServer(filePath string) (string, error) {
if filePath == "" {
return "", fmt.Errorf("file path is empty")
}
swaggerServerMu.Lock()
defer swaggerServerMu.Unlock()
if swaggerServer != nil && swaggerServer.running {
return fmt.Sprintf("http://localhost:%d", swaggerServer.port), nil
}
port := 8080
for i := 0; i < 100; i++ {
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err == nil {
listener.Close()
break
}
port++
}
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
swaggerHTML := `<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Swagger UI</title>
<link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@5.10.5/swagger-ui.css">
<style>
html { box-sizing: border-box; overflow: -moz-scrollbars-vertical; overflow-y: scroll; }
*, *:before, *:after { box-sizing: inherit; }
body { margin: 0; background: #fafafa; }
.topbar { display: none; }
.swagger-ui .topbar { display: none; }
</style>
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://unpkg.com/swagger-ui-dist@5.10.5/swagger-ui-bundle.js"></script>
<script>
window.onload = function() {
const ui = SwaggerUIBundle({
url: '/swagger.json',
dom_id: '#swagger-ui',
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIBundle.SwaggerUIStandalonePreset
],
layout: "BaseLayout",
deepLinking: true,
showExtensions: true,
showCommonExtensions: true,
docExpansion: "list",
filter: true,
tryItOutEnabled: true
});
};
</script>
</body>
</html>`
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Write([]byte(swaggerHTML))
})
mux.HandleFunc("/swagger.json", func(w http.ResponseWriter, r *http.Request) {
content, err := os.ReadFile(filePath)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.Write(content)
})
server := &http.Server{
Addr: fmt.Sprintf(":%d", port),
Handler: mux,
ReadTimeout: 15 * time.Second,
WriteTimeout: 15 * time.Second,
}
swaggerServer = &SwaggerServer{
server: server,
port: port,
running: true,
}
go func() {
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
fmt.Printf("Swagger server error: %v\n", err)
}
}()
return fmt.Sprintf("http://localhost:%d", port), nil
}
func (a *App) StopSwaggerServer() error {
swaggerServerMu.Lock()
defer swaggerServerMu.Unlock()
if swaggerServer == nil || !swaggerServer.running {
return nil
}
if err := swaggerServer.server.Close(); err != nil {
return fmt.Errorf("failed to stop server: %w", err)
}
swaggerServer.running = false
return nil
}
func (a *App) IsSwaggerServerRunning() bool {
swaggerServerMu.Lock()
defer swaggerServerMu.Unlock()
if swaggerServer == nil {
return false
}
return swaggerServer.running
}
func (a *App) GetSwaggerServerURL() string {
swaggerServerMu.Lock()
defer swaggerServerMu.Unlock()
if swaggerServer == nil || !swaggerServer.running {
return ""
}
return fmt.Sprintf("http://localhost:%d", swaggerServer.port)
}