package httpserver import ( "fmt" "io" "log" "net/http" "net/http/cookiejar" "net/url" "strings" "github.com/gin-gonic/gin" "golang.org/x/net/publicsuffix" ) // Implementing a 'set' var NonmutableHeaders = map[string]struct{}{ "Cookie": struct{}{}, "User-Agent": struct{}{}, "Accept-Encoding": struct{}{}, "Referer": struct{}{}, "X-Proxy-Url": struct{}{}, "Host": struct{}{}, } type Controller struct { Config *HttpServerConfig Client *http.Client SiteUrl *url.URL } type ProxyCookies struct { ck map[*url.URL][]*http.Cookie } /* Returns a new Controller struct to register routes to the gin router :param cfg: A pointer to an HttpServerConfig struct */ func NewController(cfg *HttpServerConfig) *Controller { jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List}) if err != nil { log.Fatal(err) } sessCookies := cfg.CookieJar domain, err := url.Parse("https://www.semrush.com") if err != nil { log.Fatal(err) } jar.SetCookies(domain, sessCookies) return &Controller{Config: cfg, Client: &http.Client{Jar: jar}, SiteUrl: domain} } /* This handler will be responsible for proxying out the GET requests that the server recieves */ func (c *Controller) Get(ctx *gin.Context) { var allowedDomain string if ctx.Param("ProxiedPath") == "/siteaudit/i18n/messages_en.fd3cadbc.json" { data, ctype, err := c.RetrieveStaticResource(ctx.Param("ProxiedPath")) if err != nil { log.Fatal(err, "failed to get site config") } ctx.Data(200, ctype, data) return } if strings.Contains(ctx.Param("ProxiedPath"), "/siteaudit/index/") { data, ctype, err := c.RetrieveStaticResource(ctx.Param("ProxiedPath")) if err != nil { log.Fatal(err, "failed to get site config") } ctx.Data(200, ctype, data) return } if strings.Contains(ctx.Param("ProxiedPath"), "/siteaudit/review/") { data, ctype, err := c.RetrieveStaticResource(ctx.Param("ProxiedPath")) if err != nil { log.Fatal(err, "failed to get site config") } ctx.Data(200, ctype, data) return } if strings.Contains(ctx.Param("ProxiedPath"), "/projects/api/") { data, ctype, err := c.SiteauditApiCall(ctx.Request.Method, ctx.Param("ProxiedPath"), ctx.Request.URL.RawQuery, ctx.Request.Body) if err != nil { log.Fatal(err, "failed to get site config") } ctx.Data(200, ctype, data) return } if strings.Contains(ctx.Param("ProxiedPath"), "/siteaudit/api/") { data, ctype, err := c.SiteauditApiCall(ctx.Request.Method, ctx.Param("ProxiedPath"), ctx.Request.URL.RawQuery, ctx.Request.Body) if err != nil { log.Fatal(err, "failed to get site config") } ctx.Data(200, ctype, data) return } allowedDomain = c.Config.AllowedDomain reqUrl := fmt.Sprintf("https://%s%s", allowedDomain, ctx.Param("ProxiedPath")) req, err := http.NewRequest(ctx.Request.Method, reqUrl, ctx.Request.Body) if err != nil { ctx.JSON(500, map[string]string{ "Error": "Error creating the request.", "Msg:": err.Error(), }) return } req.URL.Path = ctx.Param("ProxiedPath") cookie, err := ctx.Cookie("csrftoken") req.Header.Add("User-Agent", c.Config.UserAgent) req.AddCookie(&http.Cookie{Name: "csrftoken", Value: cookie, Path: "/siteaudit", MaxAge: 3600, HttpOnly: true, Secure: true, SameSite: http.SameSiteNoneMode}) req.Header.Set("Referer", c.Config.AllowedDomain) if ctx.Param("ProxiedPath") == "/" { ctx.Header("Location", "https://sem.bunnytools.shop/analytics/overview/") } if ctx.Param("ProxiedPath") == "/_compatibility/traffic/overview/" { ctx.Header("Location", "https://sem.bunnytools.shop/analytics/traffic/overview/ebay.com") } for k, v := range ctx.Request.Header { _, ok := NonmutableHeaders[k] if !ok { req.Header.Add(k, v[0]) } } resp, err := c.Client.Do(req) if err != nil { ctx.JSON(500, map[string]string{ "Error": "Error creating the request.", "Msg:": err.Error(), }) return } defer resp.Body.Close() b, err := io.ReadAll(resp.Body) if err != nil { ctx.JSON(500, map[string]string{ "Error": "Error creating the request.", "Msg:": err.Error(), }) return } for k, v := range resp.Header { _, ok := NonmutableHeaders[k] if !ok { ctx.Header(k, v[0]) } } newBody := strings.ReplaceAll(string(b), "\"srf-browser-unhappy\"", "\"srf-browser-unhappy\" style=\"display:none;\"") newBody = strings.ReplaceAll(newBody, "\"srf-navbar__right\"", "\"srf-navbar__right\" style=\"display:none;\"") newBody = strings.ReplaceAll(newBody, "