84 lines
2.8 KiB
Python
84 lines
2.8 KiB
Python
with open(r"E:\GitHub\blog\write-go\cmd\writeserver\main.go", "r", encoding="utf-8", errors="replace") as f:
|
|||
|
|
content = f.read()
|
||
|
|
|
||
|
|
# Find the root handler and replace it with a reverse proxy to Next.js
|
||
|
|
# Remove the embedded HTML page approach, replace with reverse proxy
|
||
|
|
|
||
|
|
# 1. Remove the embed directive
|
||
|
|
content = content.replace('\n//go:embed admin_page.html\nvar adminPageHTML string\n', '\n')
|
||
|
|
content = content.replace('//go:embed admin_page.html\nvar adminPageHTML string\n', '\n')
|
||
|
|
|
||
|
|
# 2. Remove _ "embed" from imports
|
||
|
|
content = content.replace('\t_ "embed"\n\t"net"\n', '\t"net"\n')
|
||
|
|
content = content.replace('\t_ "embed"\n\t"log/slog"\n', '\t"log/slog"\n')
|
||
|
|
|
||
|
|
# 3. Add net/http/httputil and net/url for reverse proxy
|
||
|
|
content = content.replace(
|
||
|
|
'\t"net/http"\n',
|
||
|
|
'\t"net/http"\n\t"net/http/httputil"\n\t"net/url"\n'
|
||
|
|
)
|
||
|
|
|
||
|
|
# 4. Replace the root handler with reverse proxy
|
||
|
|
old_root = ''' // Root page - admin dashboard
|
||
|
|
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
if r.URL.Path != "/" {
|
||
|
|
w.Header().Set("Content-Type", "application/json")
|
||
|
|
w.WriteHeader(404)
|
||
|
|
w.Write([]byte("{\"error\":\"not found\"}"))
|
||
|
|
return
|
||
|
|
}
|
||
|
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||
|
|
w.Write([]byte(adminPageHTML))
|
||
|
|
})'''
|
||
|
|
|
||
|
|
new_root = ''' // Root and non-API routes -> reverse proxy to Next.js (localhost:3000)
|
||
|
|
nextURL, _ := url.Parse("http://localhost:3000")
|
||
|
|
proxy := httputil.NewSingleHostReverseProxy(nextURL)
|
||
|
|
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
if strings.HasPrefix(r.URL.Path, "/api/") {
|
||
|
|
// Let API handlers deal with it
|
||
|
|
http.NotFound(w, r)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
proxy.ServeHTTP(w, r)
|
||
|
|
})'''
|
||
|
|
|
||
|
|
content = content.replace(old_root, new_root)
|
||
|
|
|
||
|
|
# 5. Add Next.js auto-start goroutine
|
||
|
|
old_goroutine = 'go autoStartBot()'
|
||
|
|
new_goroutine = '''go autoStartBot()
|
||
|
|
go autoStartNextJS()'''
|
||
|
|
|
||
|
|
content = content.replace(old_goroutine, new_goroutine)
|
||
|
|
|
||
|
|
# 6. Add the autoStartNextJS function before the last }
|
||
|
|
old_end = '\n\taddr := fmt.Sprintf("0.0.0.0:%d", port)'
|
||
|
|
new_end = '''
|
||
|
|
// autoStartNextJS starts Next.js if not running
|
||
|
|
func autoStartNextJS() {
|
||
|
|
time.Sleep(1 * time.Second)
|
||
|
|
// Check if Next.js is already running
|
||
|
|
if _, err := net.DialTimeout("tcp", "127.0.0.1:3000", 2*time.Second); err == nil {
|
||
|
|
lg.Info("Next.js already running on :3000")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
lg.Info("starting Next.js frontend")
|
||
|
|
cmd := exec.Command("npx.cmd", "next", "start", "-p", "3000")
|
||
|
|
cmd.Dir = filepath.Join(config.BLOG_ROOT, "write")
|
||
|
|
cmd.Stdout = os.Stdout
|
||
|
|
cmd.Stderr = os.Stderr
|
||
|
|
if err := cmd.Start(); err != nil {
|
||
|
|
lg.Warn("failed to start Next.js", "err", err)
|
||
|
|
} else {
|
||
|
|
lg.Info("Next.js started", "pid", cmd.Process.Pid)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
addr := fmt.Sprintf("0.0.0.0:%d", port)'
|
||
|
|
|
||
|
|
content = content.replace(old_end, new_end)
|
||
|
|
|
||
|
|
with open(r"E:\GitHub\blog\write-go\cmd\writeserver\main.go", "w", encoding="utf-8", errors="replace") as f:
|
||
|
|
f.write(content)
|
||
|
|
print("Done")
|