add request util to properly use flareresolver
Some checks failed
Build and publish the docker image / build (push) Failing after 1m22s
Some checks failed
Build and publish the docker image / build (push) Failing after 1m22s
Signed-off-by: ngn <ngn@ngn.tf>
This commit is contained in:
parent
4e8606c44a
commit
2f160a8649
@ -2,6 +2,7 @@ package middleware
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"anonymousoverflow/config"
|
"anonymousoverflow/config"
|
||||||
|
"anonymousoverflow/src/utils"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@ -45,9 +46,8 @@ func Ratelimit() gin.HandlerFunc {
|
|||||||
|
|
||||||
// if they exceed 30 requests in 1 minute, return a 429
|
// if they exceed 30 requests in 1 minute, return a 429
|
||||||
if val.(int) > 30 {
|
if val.(int) > 30 {
|
||||||
c.HTML(429, "home.html", gin.H{
|
utils.Render(c, 429, "home", gin.H{
|
||||||
"errorMessage": "You have exceeded the request limit. Please try again in a minute.",
|
"errorMessage": "You have exceeded the request limit. Please try again in a minute.",
|
||||||
"version": config.Version,
|
|
||||||
})
|
})
|
||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package routes
|
package routes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"anonymousoverflow/config"
|
|
||||||
"anonymousoverflow/src/utils"
|
"anonymousoverflow/src/utils"
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
@ -11,11 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func GetHome(c *gin.Context) {
|
func GetHome(c *gin.Context) {
|
||||||
theme := utils.GetThemeFromEnv()
|
utils.Render(c, 200, "home", nil)
|
||||||
c.HTML(200, "home.html", gin.H{
|
|
||||||
"version": config.Version,
|
|
||||||
"theme": theme,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type urlConversionRequest struct {
|
type urlConversionRequest struct {
|
||||||
@ -62,7 +57,7 @@ func PostHome(c *gin.Context) {
|
|||||||
body := urlConversionRequest{}
|
body := urlConversionRequest{}
|
||||||
|
|
||||||
if err := c.ShouldBind(&body); err != nil {
|
if err := c.ShouldBind(&body); err != nil {
|
||||||
c.HTML(400, "home.html", gin.H{
|
utils.Render(c, 400, "home", gin.H{
|
||||||
"errorMessage": "Invalid request body",
|
"errorMessage": "Invalid request body",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@ -71,10 +66,8 @@ func PostHome(c *gin.Context) {
|
|||||||
translated := translateUrl(body.URL)
|
translated := translateUrl(body.URL)
|
||||||
|
|
||||||
if translated == "" {
|
if translated == "" {
|
||||||
theme := utils.GetThemeFromEnv()
|
utils.Render(c, 400, "home", gin.H{
|
||||||
c.HTML(400, "home.html", gin.H{
|
|
||||||
"errorMessage": "Invalid stack overflow/exchange URL",
|
"errorMessage": "Invalid stack overflow/exchange URL",
|
||||||
"theme": theme,
|
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,12 @@ package routes
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"anonymousoverflow/src/types"
|
"anonymousoverflow/src/types"
|
||||||
|
"anonymousoverflow/src/utils"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/go-resty/resty/v2"
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -51,33 +51,15 @@ func GetImage(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// download the image
|
// download the image
|
||||||
var resp *resty.Response = nil
|
body, _, headers, err := utils.GET(claims.ImageURL)
|
||||||
client := resty.New()
|
|
||||||
|
|
||||||
if flareurl := os.Getenv("FLARERESOLVER"); flareurl == "" {
|
|
||||||
resp, err = client.R().Get(claims.ImageURL)
|
|
||||||
} else {
|
|
||||||
client.R().SetHeader("Content-Type", "application/json")
|
|
||||||
client.R().SetBody(struct {
|
|
||||||
Cmd string `json:"cmd"`
|
|
||||||
Url string `json:"url"`
|
|
||||||
MaxTimeout int `json:"maxTimeout"`
|
|
||||||
}{
|
|
||||||
Cmd: "request.get",
|
|
||||||
Url: claims.ImageURL,
|
|
||||||
MaxTimeout: 60000,
|
|
||||||
})
|
|
||||||
resp, err = client.R().Post(claims.ImageURL)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithStatus(500)
|
c.AbortWithStatus(500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the content type
|
// set the content type
|
||||||
c.Header("Content-Type", resp.Header().Get("Content-Type"))
|
c.Header("Content-Type", headers.Get("Content-Type"))
|
||||||
|
|
||||||
// write the image to the response
|
// write the image to the response
|
||||||
c.Writer.Write(resp.Body())
|
c.Writer.Write(body)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package routes
|
package routes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"anonymousoverflow/config"
|
|
||||||
"anonymousoverflow/src/utils"
|
"anonymousoverflow/src/utils"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
@ -14,16 +13,16 @@ func ChangeOptions(c *gin.Context) {
|
|||||||
switch name {
|
switch name {
|
||||||
case "images":
|
case "images":
|
||||||
text := "disabled"
|
text := "disabled"
|
||||||
|
|
||||||
if c.MustGet("disable_images").(bool) {
|
if c.MustGet("disable_images").(bool) {
|
||||||
text = "enabled"
|
text = "enabled"
|
||||||
}
|
}
|
||||||
|
|
||||||
c.SetCookie("disable_images", fmt.Sprintf("%t", !c.MustGet("disable_images").(bool)), 60*60*24*365*10, "/", "", false, true)
|
c.SetCookie("disable_images", fmt.Sprintf("%t", !c.MustGet("disable_images").(bool)), 60*60*24*365*10, "/", "", false, true)
|
||||||
theme := utils.GetThemeFromEnv()
|
utils.Render(c, 200, "home", gin.H{
|
||||||
c.HTML(200, "home.html", gin.H{
|
|
||||||
"successMessage": "Images are now " + text,
|
"successMessage": "Images are now " + text,
|
||||||
"version": config.Version,
|
|
||||||
"theme": theme,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
default:
|
default:
|
||||||
c.String(400, "400 Bad Request")
|
c.String(400, "400 Bad Request")
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package routes
|
|||||||
import (
|
import (
|
||||||
"anonymousoverflow/config"
|
"anonymousoverflow/config"
|
||||||
"anonymousoverflow/src/utils"
|
"anonymousoverflow/src/utils"
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html"
|
"html"
|
||||||
"html/template"
|
"html/template"
|
||||||
@ -15,7 +16,6 @@ import (
|
|||||||
|
|
||||||
"github.com/PuerkitoBio/goquery"
|
"github.com/PuerkitoBio/goquery"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/go-resty/resty/v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var codeBlockRegex = regexp.MustCompile(`(?s)<pre><code>(.+?)<\/code><\/pre>`)
|
var codeBlockRegex = regexp.MustCompile(`(?s)<pre><code>(.+?)<\/code><\/pre>`)
|
||||||
@ -32,7 +32,7 @@ func ViewQuestion(c *gin.Context) {
|
|||||||
|
|
||||||
questionId := c.Param("id")
|
questionId := c.Param("id")
|
||||||
if _, err := strconv.Atoi(questionId); err != nil {
|
if _, err := strconv.Atoi(questionId); err != nil {
|
||||||
c.HTML(400, "home.html", gin.H{
|
utils.Render(c, 400, "home", gin.H{
|
||||||
"errorMessage": "Invalid question ID",
|
"errorMessage": "Invalid question ID",
|
||||||
"version": config.Version,
|
"version": config.Version,
|
||||||
})
|
})
|
||||||
@ -53,44 +53,37 @@ func ViewQuestion(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
soLink := fmt.Sprintf("https://%s/questions/%s/%s?answertab=%s", domain, questionId, params.QuestionTitle, params.SoSortValue)
|
soLink := fmt.Sprintf("https://%s/questions/%s/%s?answertab=%s", domain, questionId, params.QuestionTitle, params.SoSortValue)
|
||||||
|
body, code, _, err := utils.GET(soLink)
|
||||||
|
|
||||||
resp, err := fetchQuestionData(soLink)
|
if code != 200 {
|
||||||
|
utils.Render(c, 500, "home", gin.H{
|
||||||
if resp.StatusCode() != 200 {
|
"errorMessage": fmt.Sprintf("Received a non-OK status code %d", code),
|
||||||
c.HTML(500, "home.html", gin.H{
|
|
||||||
"errorMessage": fmt.Sprintf("Received a non-OK status code %d", resp.StatusCode()),
|
|
||||||
"version": config.Version,
|
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
respBody := resp.String()
|
respBodyReader := bytes.NewReader(body)
|
||||||
|
|
||||||
respBodyReader := strings.NewReader(respBody)
|
|
||||||
|
|
||||||
doc, err := goquery.NewDocumentFromReader(respBodyReader)
|
doc, err := goquery.NewDocumentFromReader(respBodyReader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.HTML(500, "home.html", gin.H{
|
utils.Render(c, 500, "home", gin.H{
|
||||||
"errorMessage": "Unable to parse question data",
|
"errorMessage": "Unable to parse question data",
|
||||||
"version": config.Version,
|
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
newFilteredQuestion, err := extractQuestionData(doc, domain)
|
newFilteredQuestion, err := extractQuestionData(doc, domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.HTML(500, "home.html", gin.H{
|
utils.Render(c, 500, "home", gin.H{
|
||||||
"errorMessage": "Failed to extract question data",
|
"errorMessage": "Failed to extract question data",
|
||||||
"version": config.Version,
|
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
answers, err := extractAnswersData(doc, domain)
|
answers, err := extractAnswersData(doc, domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.HTML(500, "home.html", gin.H{
|
utils.Render(c, 500, "home", gin.H{
|
||||||
"errorMessage": "Failed to extract answer data",
|
"errorMessage": "Failed to extract answer data",
|
||||||
"version": config.Version,
|
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -101,18 +94,14 @@ func ViewQuestion(c *gin.Context) {
|
|||||||
imagePolicy = "'self'"
|
imagePolicy = "'self'"
|
||||||
}
|
}
|
||||||
|
|
||||||
theme := utils.GetThemeFromEnv()
|
utils.Render(c, 200, "question", gin.H{
|
||||||
|
|
||||||
c.HTML(200, "question.html", gin.H{
|
|
||||||
"question": newFilteredQuestion,
|
"question": newFilteredQuestion,
|
||||||
"answers": answers,
|
"answers": answers,
|
||||||
"imagePolicy": imagePolicy,
|
"imagePolicy": imagePolicy,
|
||||||
"currentUrl": fmt.Sprintf("%s%s", os.Getenv("APP_URL"), c.Request.URL.Path),
|
"currentUrl": fmt.Sprintf("%s%s", os.Getenv("APP_URL"), c.Request.URL.Path),
|
||||||
"sortValue": params.SoSortValue,
|
"sortValue": params.SoSortValue,
|
||||||
"domain": domain,
|
"domain": domain,
|
||||||
"theme": theme,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type viewQuestionInputs struct {
|
type viewQuestionInputs struct {
|
||||||
@ -127,9 +116,8 @@ func parseAndValidateParameters(c *gin.Context) (inputs viewQuestionInputs, err
|
|||||||
|
|
||||||
questionId := c.Param("id")
|
questionId := c.Param("id")
|
||||||
if _, err = strconv.Atoi(questionId); err != nil {
|
if _, err = strconv.Atoi(questionId); err != nil {
|
||||||
c.HTML(400, "home.html", gin.H{
|
utils.Render(c, 400, "home", gin.H{
|
||||||
"errorMessage": "Invalid question ID",
|
"errorMessage": "Invalid question ID",
|
||||||
"version": config.Version,
|
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -155,29 +143,6 @@ func parseAndValidateParameters(c *gin.Context) (inputs viewQuestionInputs, err
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetchQuestionData sends the request to StackOverflow.
|
|
||||||
func fetchQuestionData(soLink string) (*resty.Response, error) {
|
|
||||||
flareurl := ""
|
|
||||||
client := resty.New()
|
|
||||||
|
|
||||||
if flareurl = os.Getenv("FLARERESOLVER"); flareurl == "" {
|
|
||||||
return client.R().Get(soLink)
|
|
||||||
}
|
|
||||||
|
|
||||||
client.R().SetHeader("Content-Type", "application/json")
|
|
||||||
client.R().SetBody(struct {
|
|
||||||
Cmd string `json:"cmd"`
|
|
||||||
Url string `json:"url"`
|
|
||||||
MaxTimeout int `json:"maxTimeout"`
|
|
||||||
}{
|
|
||||||
Cmd: "request.get",
|
|
||||||
Url: soLink,
|
|
||||||
MaxTimeout: 60000,
|
|
||||||
})
|
|
||||||
|
|
||||||
return client.R().Post(flareurl)
|
|
||||||
}
|
|
||||||
|
|
||||||
// extractQuestionData parses the HTML document and extracts question data.
|
// extractQuestionData parses the HTML document and extracts question data.
|
||||||
func extractQuestionData(doc *goquery.Document, domain string) (question types.FilteredQuestion, err error) {
|
func extractQuestionData(doc *goquery.Document, domain string) (question types.FilteredQuestion, err error) {
|
||||||
// Extract the question title.
|
// Extract the question title.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package routes
|
package routes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"anonymousoverflow/src/utils"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@ -31,14 +32,14 @@ func RedirectShortenedOverflowURL(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
resp, err := client.R().Get(fmt.Sprintf("https://%s/a/%s/%s", domain, id, answerId))
|
resp, err := client.R().Get(fmt.Sprintf("https://%s/a/%s/%s", domain, id, answerId))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.HTML(400, "home.html", gin.H{
|
utils.Render(c, 400, "home", gin.H{
|
||||||
"errorMessage": "Unable to fetch stack overflow URL",
|
"errorMessage": "Unable to fetch stack overflow URL",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if resp.StatusCode() != 302 {
|
if resp.StatusCode() != 302 {
|
||||||
c.HTML(400, "home.html", gin.H{
|
utils.Render(c, 400, "home", gin.H{
|
||||||
"errorMessage": fmt.Sprintf("Unexpected HTTP status from origin: %d", resp.StatusCode()),
|
"errorMessage": fmt.Sprintf("Unexpected HTTP status from origin: %d", resp.StatusCode()),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
|
24
src/utils/render.go
Normal file
24
src/utils/render.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"anonymousoverflow/config"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Render(c *gin.Context, code int, temp string, _data ...gin.H) {
|
||||||
|
var data gin.H = nil
|
||||||
|
|
||||||
|
if len(_data) > 0 {
|
||||||
|
data = _data[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if data == nil {
|
||||||
|
data = gin.H{}
|
||||||
|
}
|
||||||
|
|
||||||
|
data["version"] = config.Version
|
||||||
|
data["theme"] = GetThemeFromEnv()
|
||||||
|
|
||||||
|
c.HTML(code, temp+".html", data)
|
||||||
|
}
|
63
src/utils/request.go
Normal file
63
src/utils/request.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/go-resty/resty/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// https://github.com/FlareSolverr/FlareSolverr#-requestget
|
||||||
|
type request struct {
|
||||||
|
Cmd string `json:"cmd"`
|
||||||
|
Url string `json:"url"`
|
||||||
|
MaxTimeout int `json:"maxTimeout"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type solution struct {
|
||||||
|
Status int `json:"status"`
|
||||||
|
Response []byte `json:"response"`
|
||||||
|
Headers map[string]string `json:"headers"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type response struct {
|
||||||
|
Solution solution `json:"solution"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func GET(url string) ([]byte, int, http.Header, error) {
|
||||||
|
var (
|
||||||
|
client *resty.Client = resty.New()
|
||||||
|
res *resty.Response = nil
|
||||||
|
frurl string = ""
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if frurl = os.Getenv("FLARERESOLVER"); frurl == "" {
|
||||||
|
if res, err := client.R().Get(url); err != nil {
|
||||||
|
return nil, 0, nil, err
|
||||||
|
} else {
|
||||||
|
return res.Body(), res.StatusCode(), res.Header(), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client.R().SetHeader("Content-Type", "application/json")
|
||||||
|
client.R().SetBody(request{
|
||||||
|
Cmd: "request.get",
|
||||||
|
Url: url,
|
||||||
|
MaxTimeout: 60000,
|
||||||
|
})
|
||||||
|
client.R().SetResult(&response{})
|
||||||
|
|
||||||
|
if res, err = client.R().Post(url); err != nil {
|
||||||
|
return nil, 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
response := res.Result().(*response)
|
||||||
|
headers := http.Header{}
|
||||||
|
|
||||||
|
for k, v := range response.Solution.Headers {
|
||||||
|
headers.Add(k, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.Solution.Response, response.Solution.Status, headers, nil
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user