package store import ( "fmt" "io" "net/http" "regexp" "strings" "github.com/go-rod/rod" "github.com/go-rod/rod/lib/launcher" ) type PageState struct { URL string `json:"url"` History []string Index int } var pageState = &PageState{} func browserNavigate(url string) { // 启动浏览器 launch := launcher.New().Headless(false) // 设置为 false 可以看到浏览器界面 browser := rod.New().ControlURL(launch.MustLaunch()).MustConnect() //defer browser.MustClose() // 打开一个页面 // page := browser.MustPage(url) // page.MustWaitLoad() browser.MustPage(url) } func fetchPageContent(url string) (string, error) { resp, err := http.Get(url) if err != nil { return "", err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return "", err } html := string(body) // 插入 标签 baseTag := fmt.Sprintf("", url) html = strings.Replace(html, "", fmt.Sprintf("%s", baseTag), 1) // 过滤掉可能引起弹窗的脚本 re := regexp.MustCompile(`(window\.open)\(.*?\);`) html = re.ReplaceAllString(html, "") // 移除或修改 a 标签的 target="_blank" 属性 reA := regexp.MustCompile(`(]*?)\s*target\s*=\s*"?_blank"?`) html = reA.ReplaceAllString(html, "$1") // 移除 X-Frame-Options 和 Content-Security-Policy 头 resp.Header.Del("X-Frame-Options") resp.Header.Del("Content-Security-Policy") html += `` return html, nil } func HandleNavigate(w http.ResponseWriter, r *http.Request) { url := r.URL.Query().Get("url") if url == "" { http.Error(w, "URL parameter is required", http.StatusBadRequest) return } browserNavigate(url) // html, err := fetchPageContent(url) // if err != nil { // http.Error(w, err.Error(), http.StatusInternalServerError) // return // } // pageState.History = append(pageState.History, url) // pageState.Index = len(pageState.History) - 1 // pageState.URL = url // w.Header().Set("Content-Type", "text/html; charset=utf-8") // fmt.Fprint(w, html) } func HandleBack(w http.ResponseWriter, r *http.Request) { if pageState.Index > 0 { pageState.Index-- url := pageState.History[pageState.Index] html, err := fetchPageContent(url) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } pageState.URL = url w.Header().Set("Content-Type", "text/html; charset=utf-8") fmt.Fprint(w, html) } else { http.Error(w, "No more history to go back", http.StatusForbidden) } } func HandleForward(w http.ResponseWriter, r *http.Request) { if pageState.Index < len(pageState.History)-1 { pageState.Index++ url := pageState.History[pageState.Index] html, err := fetchPageContent(url) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } pageState.URL = url w.Header().Set("Content-Type", "text/html; charset=utf-8") fmt.Fprint(w, html) } else { http.Error(w, "No more history to go forward", http.StatusForbidden) } } func HandleRefresh(w http.ResponseWriter, r *http.Request) { if pageState.URL != "" { html, err := fetchPageContent(pageState.URL) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "text/html; charset=utf-8") fmt.Fprint(w, html) } else { http.Error(w, "No current URL to refresh", http.StatusForbidden) } } // func main() { // http.HandleFunc("/navigate", HandleNavigate) // http.HandleFunc("/back", HandleBack) // http.HandleFunc("/forward", HandleForward) // http.HandleFunc("/refresh", HandleRefresh) // // http.ListenAndServe(":8080", nil) // }