cleanup code
This commit is contained in:
parent
12ad427baf
commit
e1f424b948
9 changed files with 138 additions and 95 deletions
|
@ -73,7 +73,7 @@ var ShareURLExtractor = &models.Extractor{
|
||||||
IsRedirect: true,
|
IsRedirect: true,
|
||||||
|
|
||||||
Run: func(ctx *models.DownloadContext) (*models.ExtractorResponse, error) {
|
Run: func(ctx *models.DownloadContext) (*models.ExtractorResponse, error) {
|
||||||
client := util.GetHTTPSession(ctx.Extractor.CodeName)
|
client := util.GetHTTPClient(ctx.Extractor.CodeName)
|
||||||
req, err := http.NewRequest(
|
req, err := http.NewRequest(
|
||||||
http.MethodGet,
|
http.MethodGet,
|
||||||
ctx.MatchedContentURL,
|
ctx.MatchedContentURL,
|
||||||
|
@ -98,7 +98,7 @@ func MediaListFromAPI(
|
||||||
ctx *models.DownloadContext,
|
ctx *models.DownloadContext,
|
||||||
stories bool,
|
stories bool,
|
||||||
) ([]*models.Media, error) {
|
) ([]*models.Media, error) {
|
||||||
client := util.GetHTTPSession(ctx.Extractor.CodeName)
|
client := util.GetHTTPClient(ctx.Extractor.CodeName)
|
||||||
|
|
||||||
var mediaList []*models.Media
|
var mediaList []*models.Media
|
||||||
postURL := ctx.MatchedContentURL
|
postURL := ctx.MatchedContentURL
|
||||||
|
|
|
@ -86,7 +86,7 @@ var Extractor = &models.Extractor{
|
||||||
func ExtractPinMedia(ctx *models.DownloadContext) ([]*models.Media, error) {
|
func ExtractPinMedia(ctx *models.DownloadContext) ([]*models.Media, error) {
|
||||||
pinID := ctx.MatchedContentID
|
pinID := ctx.MatchedContentID
|
||||||
contentURL := ctx.MatchedContentURL
|
contentURL := ctx.MatchedContentURL
|
||||||
client := util.GetHTTPSession(ctx.Extractor.CodeName)
|
client := util.GetHTTPClient(ctx.Extractor.CodeName)
|
||||||
|
|
||||||
pinData, err := GetPinData(client, pinID)
|
pinData, err := GetPinData(client, pinID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -31,7 +31,7 @@ var ShortExtractor = &models.Extractor{
|
||||||
IsRedirect: true,
|
IsRedirect: true,
|
||||||
|
|
||||||
Run: func(ctx *models.DownloadContext) (*models.ExtractorResponse, error) {
|
Run: func(ctx *models.DownloadContext) (*models.ExtractorResponse, error) {
|
||||||
client := util.GetHTTPSession(ctx.Extractor.CodeName)
|
client := util.GetHTTPClient(ctx.Extractor.CodeName)
|
||||||
req, err := http.NewRequest(http.MethodGet, ctx.MatchedContentURL, nil)
|
req, err := http.NewRequest(http.MethodGet, ctx.MatchedContentURL, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create request: %w", err)
|
return nil, fmt.Errorf("failed to create request: %w", err)
|
||||||
|
@ -80,7 +80,7 @@ var Extractor = &models.Extractor{
|
||||||
}
|
}
|
||||||
|
|
||||||
func MediaListFromAPI(ctx *models.DownloadContext) ([]*models.Media, error) {
|
func MediaListFromAPI(ctx *models.DownloadContext) ([]*models.Media, error) {
|
||||||
client := util.GetHTTPSession(ctx.Extractor.CodeName)
|
client := util.GetHTTPClient(ctx.Extractor.CodeName)
|
||||||
|
|
||||||
host := ctx.MatchedGroups["host"]
|
host := ctx.MatchedGroups["host"]
|
||||||
slug := ctx.MatchedGroups["slug"]
|
slug := ctx.MatchedGroups["slug"]
|
||||||
|
|
|
@ -49,7 +49,7 @@ var Extractor = &models.Extractor{
|
||||||
|
|
||||||
func MediaListFromAPI(ctx *models.DownloadContext) ([]*models.Media, error) {
|
func MediaListFromAPI(ctx *models.DownloadContext) ([]*models.Media, error) {
|
||||||
var mediaList []*models.Media
|
var mediaList []*models.Media
|
||||||
client := util.GetHTTPSession(ctx.Extractor.CodeName)
|
client := util.GetHTTPClient(ctx.Extractor.CodeName)
|
||||||
|
|
||||||
response, err := GetVideo(
|
response, err := GetVideo(
|
||||||
client, ctx.MatchedContentID)
|
client, ctx.MatchedContentID)
|
||||||
|
|
|
@ -76,7 +76,7 @@ var Extractor = &models.Extractor{
|
||||||
}
|
}
|
||||||
|
|
||||||
func MediaListFromAPI(ctx *models.DownloadContext) ([]*models.Media, error) {
|
func MediaListFromAPI(ctx *models.DownloadContext) ([]*models.Media, error) {
|
||||||
client := util.GetHTTPSession(ctx.Extractor.CodeName)
|
client := util.GetHTTPClient(ctx.Extractor.CodeName)
|
||||||
var mediaList []*models.Media
|
var mediaList []*models.Media
|
||||||
|
|
||||||
details, err := GetVideoAPI(
|
details, err := GetVideoAPI(
|
||||||
|
|
|
@ -28,7 +28,7 @@ var ShortExtractor = &models.Extractor{
|
||||||
IsRedirect: true,
|
IsRedirect: true,
|
||||||
|
|
||||||
Run: func(ctx *models.DownloadContext) (*models.ExtractorResponse, error) {
|
Run: func(ctx *models.DownloadContext) (*models.ExtractorResponse, error) {
|
||||||
client := util.GetHTTPSession(ctx.Extractor.CodeName)
|
client := util.GetHTTPClient(ctx.Extractor.CodeName)
|
||||||
req, err := http.NewRequest(http.MethodGet, ctx.MatchedContentURL, nil)
|
req, err := http.NewRequest(http.MethodGet, ctx.MatchedContentURL, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create req: %w", err)
|
return nil, fmt.Errorf("failed to create req: %w", err)
|
||||||
|
@ -79,7 +79,7 @@ var Extractor = &models.Extractor{
|
||||||
|
|
||||||
func MediaListFromAPI(ctx *models.DownloadContext) ([]*models.Media, error) {
|
func MediaListFromAPI(ctx *models.DownloadContext) ([]*models.Media, error) {
|
||||||
var mediaList []*models.Media
|
var mediaList []*models.Media
|
||||||
client := util.GetHTTPSession(ctx.Extractor.CodeName)
|
client := util.GetHTTPClient(ctx.Extractor.CodeName)
|
||||||
|
|
||||||
tweetData, err := GetTweetAPI(
|
tweetData, err := GetTweetAPI(
|
||||||
client, ctx.MatchedContentID)
|
client, ctx.MatchedContentID)
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
var downloadHTTPSession = GetDefaultHTTPSession()
|
var downloadHTTPSession = GetDefaultHTTPClient()
|
||||||
|
|
||||||
func DefaultConfig() *models.DownloadConfig {
|
func DefaultConfig() *models.DownloadConfig {
|
||||||
downloadsDir := os.Getenv("DOWNLOADS_DIR")
|
downloadsDir := os.Getenv("DOWNLOADS_DIR")
|
||||||
|
|
181
util/http.go
181
util/http.go
|
@ -16,30 +16,23 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EdgeProxyClient struct {
|
|
||||||
*http.Client
|
|
||||||
|
|
||||||
proxyURL string
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
httpSession *http.Client
|
defaultClient *http.Client
|
||||||
httpSessionOnce sync.Once
|
defaultClientOnce sync.Once
|
||||||
|
extractorClients = make(map[string]models.HTTPClient)
|
||||||
extractorsHttpSession = make(map[string]models.HTTPClient)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetDefaultHTTPSession() *http.Client {
|
func GetDefaultHTTPClient() *http.Client {
|
||||||
httpSessionOnce.Do(func() {
|
defaultClientOnce.Do(func() {
|
||||||
httpSession = &http.Client{
|
defaultClient = &http.Client{
|
||||||
Transport: GetBaseTransport(),
|
Transport: createBaseTransport(),
|
||||||
Timeout: 60 * time.Second,
|
Timeout: 60 * time.Second,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return httpSession
|
return defaultClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetBaseTransport() *http.Transport {
|
func createBaseTransport() *http.Transport {
|
||||||
return &http.Transport{
|
return &http.Transport{
|
||||||
Proxy: http.ProxyFromEnvironment,
|
Proxy: http.ProxyFromEnvironment,
|
||||||
DialContext: (&net.Dialer{
|
DialContext: (&net.Dialer{
|
||||||
|
@ -58,66 +51,73 @@ func GetBaseTransport() *http.Transport {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetHTTPSession(extractor string) models.HTTPClient {
|
func GetHTTPClient(extractor string) models.HTTPClient {
|
||||||
if client, ok := extractorsHttpSession[extractor]; ok {
|
if client, exists := extractorClients[extractor]; exists {
|
||||||
return client
|
return client
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg := config.GetExtractorConfig(extractor)
|
cfg := config.GetExtractorConfig(extractor)
|
||||||
if cfg == nil {
|
if cfg == nil {
|
||||||
return GetDefaultHTTPSession()
|
return GetDefaultHTTPClient()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var client models.HTTPClient
|
||||||
|
|
||||||
if cfg.EdgeProxyURL != "" {
|
if cfg.EdgeProxyURL != "" {
|
||||||
client := GetEdgeProxyClient(cfg.EdgeProxyURL)
|
client = NewEdgeProxyClient(cfg.EdgeProxyURL)
|
||||||
extractorsHttpSession[extractor] = client
|
} else {
|
||||||
return client
|
client = createClientWithProxy(cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
transport := GetBaseTransport()
|
extractorClients[extractor] = client
|
||||||
client := &http.Client{
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
func createClientWithProxy(cfg *models.ExtractorConfig) *http.Client {
|
||||||
|
transport := createBaseTransport()
|
||||||
|
|
||||||
|
if cfg.HTTPProxy != "" || cfg.HTTPSProxy != "" {
|
||||||
|
configureProxyTransport(transport, cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &http.Client{
|
||||||
Transport: transport,
|
Transport: transport,
|
||||||
Timeout: 60 * time.Second,
|
Timeout: 60 * time.Second,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if cfg.HTTPProxy == "" && cfg.HTTPSProxy == "" {
|
func configureProxyTransport(
|
||||||
extractorsHttpSession[extractor] = client
|
transport *http.Transport,
|
||||||
return client
|
cfg *models.ExtractorConfig,
|
||||||
}
|
) {
|
||||||
|
|
||||||
var httpProxyURL, httpsProxyURL *url.URL
|
var httpProxyURL, httpsProxyURL *url.URL
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if cfg.HTTPProxy != "" {
|
if cfg.HTTPProxy != "" {
|
||||||
if httpProxyURL, err = url.Parse(cfg.HTTPProxy); err != nil {
|
httpProxyURL, err = url.Parse(cfg.HTTPProxy)
|
||||||
|
if err != nil {
|
||||||
log.Printf("warning: invalid HTTP proxy URL '%s': %v\n", cfg.HTTPProxy, err)
|
log.Printf("warning: invalid HTTP proxy URL '%s': %v\n", cfg.HTTPProxy, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.HTTPSProxy != "" {
|
if cfg.HTTPSProxy != "" {
|
||||||
if httpsProxyURL, err = url.Parse(cfg.HTTPSProxy); err != nil {
|
httpsProxyURL, err = url.Parse(cfg.HTTPSProxy)
|
||||||
|
if err != nil {
|
||||||
log.Printf("warning: invalid HTTPS proxy URL '%s': %v\n", cfg.HTTPSProxy, err)
|
log.Printf("warning: invalid HTTPS proxy URL '%s': %v\n", cfg.HTTPSProxy, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if httpProxyURL != nil || httpsProxyURL != nil {
|
if httpProxyURL == nil && httpsProxyURL == nil {
|
||||||
noProxyList := strings.Split(cfg.NoProxy, ",")
|
return
|
||||||
for i := range noProxyList {
|
|
||||||
noProxyList[i] = strings.TrimSpace(noProxyList[i])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
noProxyList := parseNoProxyList(cfg.NoProxy)
|
||||||
|
|
||||||
transport.Proxy = func(req *http.Request) (*url.URL, error) {
|
transport.Proxy = func(req *http.Request) (*url.URL, error) {
|
||||||
if cfg.NoProxy != "" {
|
if shouldBypassProxy(req.URL.Hostname(), noProxyList) {
|
||||||
host := req.URL.Hostname()
|
|
||||||
for _, p := range noProxyList {
|
|
||||||
if p == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if p == host || (strings.HasPrefix(p, ".") && strings.HasSuffix(host, p)) {
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
if req.URL.Scheme == "https" && httpsProxyURL != nil {
|
if req.URL.Scheme == "https" && httpsProxyURL != nil {
|
||||||
return httpsProxyURL, nil
|
return httpsProxyURL, nil
|
||||||
}
|
}
|
||||||
|
@ -129,41 +129,59 @@ func GetHTTPSession(extractor string) models.HTTPClient {
|
||||||
}
|
}
|
||||||
return httpProxyURL, nil
|
return httpProxyURL, nil
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
extractorsHttpSession[extractor] = client
|
|
||||||
return client
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetEdgeProxyClient(proxyURL string) *EdgeProxyClient {
|
func parseNoProxyList(noProxy string) []string {
|
||||||
edgeProxyClient := &EdgeProxyClient{
|
if noProxy == "" {
|
||||||
Client: &http.Client{
|
return nil
|
||||||
Transport: GetBaseTransport(),
|
}
|
||||||
|
|
||||||
|
list := strings.Split(noProxy, ",")
|
||||||
|
for i := range list {
|
||||||
|
list[i] = strings.TrimSpace(list[i])
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
func shouldBypassProxy(host string, noProxyList []string) bool {
|
||||||
|
for _, p := range noProxyList {
|
||||||
|
if p == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if p == host || (strings.HasPrefix(p, ".") && strings.HasSuffix(host, p)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type EdgeProxyClient struct {
|
||||||
|
client *http.Client
|
||||||
|
proxyURL string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEdgeProxyClient(proxyURL string) *EdgeProxyClient {
|
||||||
|
return &EdgeProxyClient{
|
||||||
|
client: &http.Client{
|
||||||
|
Transport: createBaseTransport(),
|
||||||
Timeout: 60 * time.Second,
|
Timeout: 60 * time.Second,
|
||||||
},
|
},
|
||||||
proxyURL: proxyURL,
|
proxyURL: proxyURL,
|
||||||
}
|
}
|
||||||
return edgeProxyClient
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *EdgeProxyClient) Do(req *http.Request) (*http.Response, error) {
|
func (c *EdgeProxyClient) Do(req *http.Request) (*http.Response, error) {
|
||||||
if c.proxyURL == "" {
|
if c.proxyURL == "" {
|
||||||
return nil, fmt.Errorf("proxy URL is not set")
|
return nil, fmt.Errorf("proxy URL is not set")
|
||||||
}
|
}
|
||||||
|
|
||||||
targetURL := req.URL.String()
|
targetURL := req.URL.String()
|
||||||
encodedURL := url.QueryEscape(targetURL)
|
encodedURL := url.QueryEscape(targetURL)
|
||||||
proxyURLWithParam := c.proxyURL + "?url=" + encodedURL
|
proxyURLWithParam := c.proxyURL + "?url=" + encodedURL
|
||||||
|
|
||||||
var bodyBytes []byte
|
bodyBytes, err := readRequestBody(req)
|
||||||
var err error
|
|
||||||
|
|
||||||
if req.Body != nil {
|
|
||||||
bodyBytes, err = io.ReadAll(req.Body)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error reading request body: %w", err)
|
return nil, err
|
||||||
}
|
|
||||||
req.Body.Close()
|
|
||||||
req.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
proxyReq, err := http.NewRequest(
|
proxyReq, err := http.NewRequest(
|
||||||
|
@ -175,18 +193,42 @@ func (c *EdgeProxyClient) Do(req *http.Request) (*http.Response, error) {
|
||||||
return nil, fmt.Errorf("error creating proxy request: %w", err)
|
return nil, fmt.Errorf("error creating proxy request: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, values := range req.Header {
|
copyHeaders(req.Header, proxyReq.Header)
|
||||||
for _, value := range values {
|
|
||||||
proxyReq.Header.Add(name, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
proxyResp, err := c.Client.Do(proxyReq)
|
proxyResp, err := c.client.Do(proxyReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("proxy request failed: %w", err)
|
return nil, fmt.Errorf("proxy request failed: %w", err)
|
||||||
}
|
}
|
||||||
defer proxyResp.Body.Close()
|
defer proxyResp.Body.Close()
|
||||||
|
|
||||||
|
return parseProxyResponse(proxyResp, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func readRequestBody(req *http.Request) ([]byte, error) {
|
||||||
|
if req.Body == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyBytes, err := io.ReadAll(req.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error reading request body: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Body.Close()
|
||||||
|
req.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
|
||||||
|
|
||||||
|
return bodyBytes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyHeaders(source, destination http.Header) {
|
||||||
|
for name, values := range source {
|
||||||
|
for _, value := range values {
|
||||||
|
destination.Add(name, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseProxyResponse(proxyResp *http.Response, originalReq *http.Request) (*http.Response, error) {
|
||||||
body, err := io.ReadAll(proxyResp.Body)
|
body, err := io.ReadAll(proxyResp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error reading proxy response: %w", err)
|
return nil, fmt.Errorf("error reading proxy response: %w", err)
|
||||||
|
@ -202,8 +244,9 @@ func (c *EdgeProxyClient) Do(req *http.Request) (*http.Response, error) {
|
||||||
Status: fmt.Sprintf("%d %s", response.StatusCode, http.StatusText(response.StatusCode)),
|
Status: fmt.Sprintf("%d %s", response.StatusCode, http.StatusText(response.StatusCode)),
|
||||||
Body: io.NopCloser(bytes.NewBufferString(response.Text)),
|
Body: io.NopCloser(bytes.NewBufferString(response.Text)),
|
||||||
Header: make(http.Header),
|
Header: make(http.Header),
|
||||||
Request: req,
|
Request: originalReq,
|
||||||
}
|
}
|
||||||
|
|
||||||
parsedResponseURL, err := url.Parse(response.URL)
|
parsedResponseURL, err := url.Parse(response.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error parsing response URL: %w", err)
|
return nil, fmt.Errorf("error parsing response URL: %w", err)
|
||||||
|
|
|
@ -29,7 +29,7 @@ func GetLocationURL(
|
||||||
userAgent = ChromeUA
|
userAgent = ChromeUA
|
||||||
}
|
}
|
||||||
req.Header.Set("User-Agent", userAgent)
|
req.Header.Set("User-Agent", userAgent)
|
||||||
session := GetDefaultHTTPSession()
|
session := GetDefaultHTTPClient()
|
||||||
resp, err := session.Do(req)
|
resp, err := session.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("failed to send request: %w", err)
|
return "", fmt.Errorf("failed to send request: %w", err)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue