save flaresolverr solution to use it again
All checks were successful
build / build (push) Successful in 1m1s
All checks were successful
build / build (push) Successful in 1m1s
Signed-off-by: ngn <ngn@ngn.tf>
This commit is contained in:
parent
c9e2cf1a44
commit
d133b45575
10
.dockerignore
Normal file
10
.dockerignore
Normal file
@ -0,0 +1,10 @@
|
||||
.git
|
||||
|
||||
ups.json
|
||||
renovate.json
|
||||
|
||||
README.md
|
||||
LICENSE.txt
|
||||
|
||||
docker-compose.example.yml
|
||||
Dockerfile
|
@ -51,15 +51,15 @@ func GetImage(c *gin.Context) {
|
||||
}
|
||||
|
||||
// download the image
|
||||
body, _, headers, err := utils.GET(claims.ImageURL)
|
||||
res, err := utils.GET(claims.ImageURL)
|
||||
if err != nil {
|
||||
c.AbortWithStatus(500)
|
||||
return
|
||||
}
|
||||
|
||||
// set the content type
|
||||
c.Header("Content-Type", headers.Get("Content-Type"))
|
||||
c.Header("Content-Type", res.Header().Get("Content-Type"))
|
||||
|
||||
// write the image to the response
|
||||
c.Writer.Write(body)
|
||||
c.Writer.Write(res.Body())
|
||||
}
|
||||
|
@ -53,18 +53,25 @@ func ViewQuestion(c *gin.Context) {
|
||||
}
|
||||
|
||||
soLink := fmt.Sprintf("https://%s/questions/%s/%s?answertab=%s", domain, questionId, params.QuestionTitle, params.SoSortValue)
|
||||
body, code, _, err := utils.GET(soLink)
|
||||
res, err := utils.GET(soLink)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("failed to get %s: %s", soLink, err.Error())
|
||||
|
||||
if code != 200 {
|
||||
utils.Render(c, 500, "home", gin.H{
|
||||
"errorMessage": fmt.Sprintf("Received a non-OK status code %d", code),
|
||||
"errorMessage": fmt.Sprintf("Request to server failed"),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
respBodyReader := bytes.NewReader(body)
|
||||
if res.StatusCode() != 200 {
|
||||
utils.Render(c, 500, "home", gin.H{
|
||||
"errorMessage": fmt.Sprintf("Received a non-OK status code: %d", res.StatusCode()),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
doc, err := goquery.NewDocumentFromReader(respBodyReader)
|
||||
doc, err := goquery.NewDocumentFromReader(bytes.NewReader(res.Body()))
|
||||
if err != nil {
|
||||
utils.Render(c, 500, "home", gin.H{
|
||||
"errorMessage": "Unable to parse question data",
|
||||
|
@ -1,70 +1,150 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
)
|
||||
|
||||
// https://github.com/FlareSolverr/FlareSolverr#-requestget
|
||||
type request struct {
|
||||
type Request struct {
|
||||
Cmd string `json:"cmd"`
|
||||
Url string `json:"url"`
|
||||
MaxTimeout int `json:"maxTimeout"`
|
||||
OnlyCookies bool `json:"returnOnlyCookies"`
|
||||
}
|
||||
|
||||
type solution struct {
|
||||
type Cookie struct {
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
Domain string `json:"domain"`
|
||||
Path string `json:"path"`
|
||||
Expires time.Time `json:"expires"`
|
||||
Size uint64 `json:"size"`
|
||||
HttpOnly bool `json:"httpOnly"`
|
||||
Secure bool `json:"secure"`
|
||||
Session bool `json:"session"`
|
||||
SameSite string `json:"sameSite"`
|
||||
}
|
||||
|
||||
type Solution struct {
|
||||
Status int `json:"status"`
|
||||
Response []byte `json:"response"`
|
||||
Headers map[string]string `json:"headers"`
|
||||
Cookies []Cookie `json:"cookies"`
|
||||
Agent string `json:"userAgent"`
|
||||
}
|
||||
|
||||
type response struct {
|
||||
Solution solution `json:"solution"`
|
||||
type Response struct {
|
||||
Solution Solution `json:"solution"`
|
||||
}
|
||||
|
||||
func GET(target string) ([]byte, int, http.Header, error) {
|
||||
var (
|
||||
client *resty.Client = resty.New()
|
||||
frurl string = ""
|
||||
)
|
||||
func (c *Cookie) ToCookie() *http.Cookie {
|
||||
ss := http.SameSiteNoneMode
|
||||
|
||||
if frurl = os.Getenv("FLARESOLVER"); frurl == "" {
|
||||
if res, err := client.R().Get(target); err != nil {
|
||||
return nil, 0, nil, err
|
||||
} else {
|
||||
return res.Body(), res.StatusCode(), res.Header(), nil
|
||||
switch c.SameSite {
|
||||
case "Lax":
|
||||
ss = http.SameSiteLaxMode
|
||||
|
||||
case "Strict":
|
||||
ss = http.SameSiteStrictMode
|
||||
|
||||
case "Default":
|
||||
ss = http.SameSiteDefaultMode
|
||||
}
|
||||
|
||||
return &http.Cookie{
|
||||
Name: c.Name,
|
||||
Value: c.Value,
|
||||
Domain: c.Domain,
|
||||
Path: c.Path,
|
||||
Expires: c.Expires,
|
||||
HttpOnly: c.HttpOnly,
|
||||
Secure: c.Secure,
|
||||
SameSite: ss,
|
||||
}
|
||||
}
|
||||
|
||||
frurl, _ = url.JoinPath(frurl, "/v1")
|
||||
func (s *Solution) HttpCookies() []*http.Cookie {
|
||||
cookies := []*http.Cookie{}
|
||||
|
||||
for i := range s.Cookies {
|
||||
cookies = append(cookies, s.Cookies[i].ToCookie())
|
||||
}
|
||||
|
||||
return cookies
|
||||
}
|
||||
|
||||
const USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.3"
|
||||
|
||||
var solution *Solution = nil
|
||||
|
||||
func Solve(target string) error {
|
||||
fsurl := os.Getenv("FLARESOLVER")
|
||||
|
||||
if fsurl == "" {
|
||||
return fmt.Errorf("flaresolver is not configured")
|
||||
}
|
||||
|
||||
fsurl, _ = url.JoinPath(fsurl, "/v1")
|
||||
response := Response{}
|
||||
client := resty.New()
|
||||
|
||||
res, err := client.R().
|
||||
SetBody(request{
|
||||
SetBody(Request{
|
||||
Cmd: "request.get",
|
||||
Url: target,
|
||||
MaxTimeout: 40_000,
|
||||
OnlyCookies: true,
|
||||
}).
|
||||
SetResult(&response{}).
|
||||
Post(frurl)
|
||||
Post(fsurl)
|
||||
|
||||
if err != nil {
|
||||
return nil, 0, nil, err
|
||||
return fmt.Errorf("request failed: %s", err.Error())
|
||||
}
|
||||
|
||||
if res.StatusCode() != 200 {
|
||||
return nil, 0, nil, fmt.Errorf("flaresolver failure")
|
||||
return fmt.Errorf("bad status code: %d", res.StatusCode())
|
||||
}
|
||||
|
||||
response := res.Result().(*response)
|
||||
headers := http.Header{}
|
||||
|
||||
for k, v := range response.Solution.Headers {
|
||||
headers.Add(k, v)
|
||||
if err := json.Unmarshal(res.Body(), &response); err != nil {
|
||||
return fmt.Errorf("failed to parse body: %s", err.Error())
|
||||
}
|
||||
|
||||
return response.Solution.Response, response.Solution.Status, headers, nil
|
||||
solution = &response.Solution
|
||||
return nil
|
||||
}
|
||||
|
||||
func GET(target string, no_retry ...bool) (*resty.Response, error) {
|
||||
client := resty.New()
|
||||
req := client.R()
|
||||
|
||||
if solution != nil {
|
||||
req.SetCookies(solution.HttpCookies())
|
||||
req.SetHeader("User-Agent", solution.Agent)
|
||||
} else {
|
||||
req.SetHeader("User-Agent", USER_AGENT)
|
||||
}
|
||||
|
||||
res, err := req.Get(target)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if res.StatusCode() != http.StatusForbidden {
|
||||
return res, err
|
||||
}
|
||||
|
||||
if err = Solve(target); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(no_retry) == 0 {
|
||||
return GET(target)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("solution did not work")
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user