feat: add AlwaysIgnoreUrls for URL filtering; update README and release version to 1.3-01
Build and Release / release (push) Successful in 1m43s
Build and Release / release (push) Successful in 1m43s
This commit is contained in:
@@ -23,6 +23,10 @@ var AlwaysIgnoreDomains = []string{
|
|||||||
"autopatchos.starrails.com",
|
"autopatchos.starrails.com",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var AlwaysIgnoreUrls = []string{
|
||||||
|
"/query_security_file",
|
||||||
|
}
|
||||||
|
|
||||||
var BlockUrls = []string{
|
var BlockUrls = []string{
|
||||||
"/data_abtest_api/config/experiment/list",
|
"/data_abtest_api/config/experiment/list",
|
||||||
"/common/hkrpg_global/announcement/api/getAlertPic",
|
"/common/hkrpg_global/announcement/api/getAlertPic",
|
||||||
|
|||||||
@@ -136,6 +136,11 @@ func main() {
|
|||||||
return req, nil
|
return req, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if matchURL(path, AlwaysIgnoreUrls) {
|
||||||
|
zlog.Warn().Str("url", req.URL.String()).Msg("PASS URL")
|
||||||
|
return req, nil
|
||||||
|
}
|
||||||
|
|
||||||
if matchDomain(host, RedirectDomains) {
|
if matchDomain(host, RedirectDomains) {
|
||||||
if matchURL(path, BlockUrls) {
|
if matchURL(path, BlockUrls) {
|
||||||
full := req.URL.String()
|
full := req.URL.String()
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
### UPDATE
|
### UPDATE
|
||||||
- Fix bug in macos
|
- Support linux, macos, window
|
||||||
Binary file not shown.
+149
-69
@@ -9,12 +9,19 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
apiRequestTimeout = 45 * time.Second
|
||||||
|
maxHTTPAttempts = 5
|
||||||
|
)
|
||||||
|
|
||||||
// API responses structures
|
// API responses structures
|
||||||
type CommonResponse struct {
|
type CommonResponse struct {
|
||||||
Status bool `json:"status"`
|
Status bool `json:"status"`
|
||||||
@@ -324,24 +331,93 @@ func getFileInfoAndHash(path string) (int64, string, error) {
|
|||||||
return stat.Size(), hex.EncodeToString(hasher.Sum(nil)), nil
|
return stat.Size(), hex.EncodeToString(hasher.Sum(nil)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func refreshRobotToken(apiURL, robotToken string) (string, error) {
|
func apiEndpoint(apiURL, path string) string {
|
||||||
url := fmt.Sprintf("%s/robot-tokens/refresh", apiURL)
|
return strings.TrimRight(apiURL, "/") + path
|
||||||
req, err := http.NewRequest("POST", url, nil)
|
}
|
||||||
if err != nil {
|
|
||||||
return "", err
|
func retryDelay(attempt int) time.Duration {
|
||||||
}
|
delay := time.Duration(1<<uint(attempt-1)) * time.Second
|
||||||
req.Header.Set("Authorization", "Bearer "+robotToken)
|
if delay > 20*time.Second {
|
||||||
|
return 20 * time.Second
|
||||||
|
}
|
||||||
|
return delay
|
||||||
|
}
|
||||||
|
|
||||||
|
func isRetryableStatus(statusCode int) bool {
|
||||||
|
return statusCode == http.StatusRequestTimeout ||
|
||||||
|
statusCode == http.StatusTooEarly ||
|
||||||
|
statusCode == http.StatusTooManyRequests ||
|
||||||
|
statusCode >= http.StatusInternalServerError
|
||||||
|
}
|
||||||
|
|
||||||
|
func isAccepted(statusCode int, accepted ...int) bool {
|
||||||
|
for _, code := range accepted {
|
||||||
|
if statusCode == code {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func doHTTPWithRetry(label string, client *http.Client, buildRequest func() (*http.Request, error), accepted ...int) ([]byte, int, error) {
|
||||||
|
var lastErr error
|
||||||
|
for attempt := 1; attempt <= maxHTTPAttempts; attempt++ {
|
||||||
|
req, err := buildRequest()
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
client := &http.Client{Timeout: 15 * time.Second}
|
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
lastErr = err
|
||||||
|
if attempt < maxHTTPAttempts {
|
||||||
|
delay := retryDelay(attempt)
|
||||||
|
fmt.Fprintf(os.Stderr, "%s attempt %d/%d failed: %v. Retrying in %s...\n", label, attempt, maxHTTPAttempts, err, delay)
|
||||||
|
time.Sleep(delay)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyBytes, readErr := io.ReadAll(resp.Body)
|
||||||
|
_ = resp.Body.Close()
|
||||||
|
if readErr != nil {
|
||||||
|
return nil, resp.StatusCode, readErr
|
||||||
|
}
|
||||||
|
|
||||||
|
if isAccepted(resp.StatusCode, accepted...) {
|
||||||
|
return bodyBytes, resp.StatusCode, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isRetryableStatus(resp.StatusCode) || attempt == maxHTTPAttempts {
|
||||||
|
return bodyBytes, resp.StatusCode, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
lastErr = fmt.Errorf("status %d: %s", resp.StatusCode, strings.TrimSpace(string(bodyBytes)))
|
||||||
|
delay := retryDelay(attempt)
|
||||||
|
fmt.Fprintf(os.Stderr, "%s attempt %d/%d returned %v. Retrying in %s...\n", label, attempt, maxHTTPAttempts, lastErr, delay)
|
||||||
|
time.Sleep(delay)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, 0, lastErr
|
||||||
|
}
|
||||||
|
|
||||||
|
func refreshRobotToken(apiURL, robotToken string) (string, error) {
|
||||||
|
endpoint := apiEndpoint(apiURL, "/robot-tokens/refresh")
|
||||||
|
client := &http.Client{Timeout: apiRequestTimeout}
|
||||||
|
bodyBytes, statusCode, err := doHTTPWithRetry("refresh robot token", client, func() (*http.Request, error) {
|
||||||
|
req, err := http.NewRequest("POST", endpoint, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header.Set("Authorization", "Bearer "+robotToken)
|
||||||
|
return req, nil
|
||||||
|
}, http.StatusOK)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if statusCode != http.StatusOK {
|
||||||
|
return "", fmt.Errorf("refresh token failed with status %d: %s", statusCode, string(bodyBytes))
|
||||||
bodyBytes, _ := io.ReadAll(resp.Body)
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
return "", fmt.Errorf("refresh token failed with status %d: %s", resp.StatusCode, string(bodyBytes))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var cr CommonResponse
|
var cr CommonResponse
|
||||||
@@ -362,25 +438,30 @@ func refreshRobotToken(apiURL, robotToken string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getPresignedURL(apiURL, accessToken, fileName, contentType string, size int64) (*PreSignedResponse, error) {
|
func getPresignedURL(apiURL, accessToken, fileName, contentType string, size int64) (*PreSignedResponse, error) {
|
||||||
u := fmt.Sprintf("%s/media/presigned?fileName=%s&content_type=%s&size=%d",
|
endpoint, err := url.Parse(apiEndpoint(apiURL, "/media/presigned"))
|
||||||
apiURL, fileName, contentType, size)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
query := endpoint.Query()
|
||||||
|
query.Set("fileName", fileName)
|
||||||
|
query.Set("content_type", contentType)
|
||||||
|
query.Set("size", strconv.FormatInt(size, 10))
|
||||||
|
endpoint.RawQuery = query.Encode()
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", u, nil)
|
client := &http.Client{Timeout: apiRequestTimeout}
|
||||||
|
bodyBytes, statusCode, err := doHTTPWithRetry("get presigned URL", client, func() (*http.Request, error) {
|
||||||
|
req, err := http.NewRequest("GET", endpoint.String(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.Header.Set("Authorization", "Bearer "+accessToken)
|
req.Header.Set("Authorization", "Bearer "+accessToken)
|
||||||
|
return req, nil
|
||||||
client := &http.Client{Timeout: 15 * time.Second}
|
}, http.StatusOK)
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if statusCode != http.StatusOK {
|
||||||
|
return nil, fmt.Errorf("failed to get presigned URL (status %d): %s", statusCode, string(bodyBytes))
|
||||||
bodyBytes, _ := io.ReadAll(resp.Body)
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
return nil, fmt.Errorf("failed to get presigned URL (status %d): %s", resp.StatusCode, string(bodyBytes))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var cr CommonResponse
|
var cr CommonResponse
|
||||||
@@ -443,7 +524,7 @@ func uploadFileToS3(path string, presigned *PreSignedResponse) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func completePreSignedUpload(apiURL, accessToken, tokenID, hash string) (string, error) {
|
func completePreSignedUpload(apiURL, accessToken, tokenID, hash string) (string, error) {
|
||||||
url := fmt.Sprintf("%s/media/presigned/complete", apiURL)
|
endpoint := apiEndpoint(apiURL, "/media/presigned/complete")
|
||||||
|
|
||||||
metaJSON, _ := json.Marshal(map[string]string{"sha256": hash})
|
metaJSON, _ := json.Marshal(map[string]string{"sha256": hash})
|
||||||
dto := PreSignedCompleteDto{
|
dto := PreSignedCompleteDto{
|
||||||
@@ -453,23 +534,21 @@ func completePreSignedUpload(apiURL, accessToken, tokenID, hash string) (string,
|
|||||||
|
|
||||||
payload, _ := json.Marshal(dto)
|
payload, _ := json.Marshal(dto)
|
||||||
|
|
||||||
req, err := http.NewRequest("POST", url, bytes.NewReader(payload))
|
client := &http.Client{Timeout: apiRequestTimeout}
|
||||||
|
bodyBytes, statusCode, err := doHTTPWithRetry("complete presigned upload", client, func() (*http.Request, error) {
|
||||||
|
req, err := http.NewRequest("POST", endpoint, bytes.NewReader(payload))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.Header.Set("Authorization", "Bearer "+accessToken)
|
req.Header.Set("Authorization", "Bearer "+accessToken)
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
return req, nil
|
||||||
client := &http.Client{Timeout: 30 * time.Second}
|
}, http.StatusOK)
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if statusCode != http.StatusOK {
|
||||||
|
return "", fmt.Errorf("complete upload failed (status %d): %s", statusCode, string(bodyBytes))
|
||||||
bodyBytes, _ := io.ReadAll(resp.Body)
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
return "", fmt.Errorf("complete upload failed (status %d): %s", resp.StatusCode, string(bodyBytes))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var cr CommonResponse
|
var cr CommonResponse
|
||||||
@@ -490,27 +569,25 @@ func completePreSignedUpload(apiURL, accessToken, tokenID, hash string) (string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func createComponent(apiURL, accessToken string, dto CreateComponentRequest) (string, error) {
|
func createComponent(apiURL, accessToken string, dto CreateComponentRequest) (string, error) {
|
||||||
url := fmt.Sprintf("%s/components", apiURL)
|
endpoint := apiEndpoint(apiURL, "/components")
|
||||||
|
|
||||||
payload, _ := json.Marshal(dto)
|
payload, _ := json.Marshal(dto)
|
||||||
|
|
||||||
req, err := http.NewRequest("POST", url, bytes.NewReader(payload))
|
client := &http.Client{Timeout: apiRequestTimeout}
|
||||||
|
bodyBytes, statusCode, err := doHTTPWithRetry("create component", client, func() (*http.Request, error) {
|
||||||
|
req, err := http.NewRequest("POST", endpoint, bytes.NewReader(payload))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.Header.Set("Authorization", "Bearer "+accessToken)
|
req.Header.Set("Authorization", "Bearer "+accessToken)
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
return req, nil
|
||||||
client := &http.Client{Timeout: 30 * time.Second}
|
}, http.StatusCreated, http.StatusOK)
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if statusCode != http.StatusCreated && statusCode != http.StatusOK {
|
||||||
|
return "", fmt.Errorf("create component failed (status %d): %s", statusCode, string(bodyBytes))
|
||||||
bodyBytes, _ := io.ReadAll(resp.Body)
|
|
||||||
if resp.StatusCode != http.StatusCreated && resp.StatusCode != http.StatusOK {
|
|
||||||
return "", fmt.Errorf("create component failed (status %d): %s", resp.StatusCode, string(bodyBytes))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var cr CommonResponse
|
var cr CommonResponse
|
||||||
@@ -533,25 +610,30 @@ func createComponent(apiURL, accessToken string, dto CreateComponentRequest) (st
|
|||||||
}
|
}
|
||||||
|
|
||||||
func findExistingComponent(apiURL, accessToken, cType, platform, version string) (string, error) {
|
func findExistingComponent(apiURL, accessToken, cType, platform, version string) (string, error) {
|
||||||
u := fmt.Sprintf("%s/components?type=%s&platform=%s&search=%s",
|
endpoint, err := url.Parse(apiEndpoint(apiURL, "/components"))
|
||||||
apiURL, cType, platform, version)
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", u, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
query := endpoint.Query()
|
||||||
|
query.Set("type", cType)
|
||||||
|
query.Set("platform", platform)
|
||||||
|
query.Set("search", version)
|
||||||
|
endpoint.RawQuery = query.Encode()
|
||||||
|
|
||||||
|
client := &http.Client{Timeout: apiRequestTimeout}
|
||||||
|
bodyBytes, statusCode, err := doHTTPWithRetry("search existing component", client, func() (*http.Request, error) {
|
||||||
|
req, err := http.NewRequest("GET", endpoint.String(), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
req.Header.Set("Authorization", "Bearer "+accessToken)
|
req.Header.Set("Authorization", "Bearer "+accessToken)
|
||||||
|
return req, nil
|
||||||
client := &http.Client{Timeout: 15 * time.Second}
|
}, http.StatusOK)
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if statusCode != http.StatusOK {
|
||||||
|
return "", fmt.Errorf("failed to search components (status %d): %s", statusCode, string(bodyBytes))
|
||||||
bodyBytes, _ := io.ReadAll(resp.Body)
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
return "", fmt.Errorf("failed to search components (status %d): %s", resp.StatusCode, string(bodyBytes))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var pr struct {
|
var pr struct {
|
||||||
@@ -582,27 +664,25 @@ func findExistingComponent(apiURL, accessToken, cType, platform, version string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateComponent(apiURL, accessToken, id string, dto UpdateComponentRequest) (string, error) {
|
func updateComponent(apiURL, accessToken, id string, dto UpdateComponentRequest) (string, error) {
|
||||||
url := fmt.Sprintf("%s/components/%s", apiURL, id)
|
endpoint := apiEndpoint(apiURL, "/components/"+url.PathEscape(id))
|
||||||
|
|
||||||
payload, _ := json.Marshal(dto)
|
payload, _ := json.Marshal(dto)
|
||||||
|
|
||||||
req, err := http.NewRequest("PUT", url, bytes.NewReader(payload))
|
client := &http.Client{Timeout: apiRequestTimeout}
|
||||||
|
bodyBytes, statusCode, err := doHTTPWithRetry("update component", client, func() (*http.Request, error) {
|
||||||
|
req, err := http.NewRequest("PUT", endpoint, bytes.NewReader(payload))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.Header.Set("Authorization", "Bearer "+accessToken)
|
req.Header.Set("Authorization", "Bearer "+accessToken)
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
return req, nil
|
||||||
client := &http.Client{Timeout: 30 * time.Second}
|
}, http.StatusOK)
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if statusCode != http.StatusOK {
|
||||||
|
return "", fmt.Errorf("update component failed (status %d): %s", statusCode, string(bodyBytes))
|
||||||
bodyBytes, _ := io.ReadAll(resp.Body)
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
return "", fmt.Errorf("update component failed (status %d): %s", resp.StatusCode, string(bodyBytes))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var cr CommonResponse
|
var cr CommonResponse
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"tag": "1.2-03",
|
"tag": "1.3-01",
|
||||||
"title": "PreBuild Version 1.2 - 03"
|
"title": "PreBuild Version 1.3 - 01"
|
||||||
}
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user