Files
urldb/common/base_pan.go
2025-07-13 09:57:36 +08:00

286 lines
6.0 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package pan
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"time"
)
// BasePanService 基础网盘服务
type BasePanService struct {
config *PanConfig
httpClient *http.Client
headers map[string]string
}
// NewBasePanService 创建基础网盘服务
func NewBasePanService(config *PanConfig) *BasePanService {
return &BasePanService{
config: config,
httpClient: &http.Client{
Timeout: 30 * time.Second,
},
headers: make(map[string]string),
}
}
// SetHeader 设置请求头
func (b *BasePanService) SetHeader(key, value string) {
b.headers[key] = value
}
// SetHeaders 批量设置请求头
func (b *BasePanService) SetHeaders(headers map[string]string) {
for key, value := range headers {
b.headers[key] = value
}
}
// GetHeader 获取请求头
func (b *BasePanService) GetHeader(key string) string {
return b.headers[key]
}
// GetConfig 获取配置
func (b *BasePanService) GetConfig() *PanConfig {
return b.config
}
// HTTPGet 发送GET请求
func (b *BasePanService) HTTPGet(requestURL string, queryParams map[string]string) ([]byte, error) {
// 构建查询参数
if len(queryParams) > 0 {
u, err := url.Parse(requestURL)
if err != nil {
return nil, err
}
q := u.Query()
for key, value := range queryParams {
q.Set(key, value)
}
u.RawQuery = q.Encode()
requestURL = u.String()
}
req, err := http.NewRequest("GET", requestURL, nil)
if err != nil {
return nil, err
}
// 设置请求头
for key, value := range b.headers {
req.Header.Set(key, value)
}
resp, err := b.httpClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("HTTP请求失败: %d, %s", resp.StatusCode, string(body))
}
return body, nil
}
// HTTPPost 发送POST请求
func (b *BasePanService) HTTPPost(requestURL string, data interface{}, queryParams map[string]string) ([]byte, error) {
var body io.Reader
if data != nil {
jsonData, err := json.Marshal(data)
if err != nil {
return nil, err
}
body = bytes.NewBuffer(jsonData)
}
// 构建查询参数
if len(queryParams) > 0 {
u, err := url.Parse(requestURL)
if err != nil {
return nil, err
}
q := u.Query()
for key, value := range queryParams {
q.Set(key, value)
}
u.RawQuery = q.Encode()
requestURL = u.String()
}
req, err := http.NewRequest("POST", requestURL, body)
if err != nil {
return nil, err
}
// 设置请求头
for key, value := range b.headers {
req.Header.Set(key, value)
}
// 如果没有设置Content-Type默认设置为application/json
if _, exists := b.headers["Content-Type"]; !exists && data != nil {
req.Header.Set("Content-Type", "application/json")
}
resp, err := b.httpClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("HTTP请求失败: %d, %s", resp.StatusCode, string(respBody))
}
return respBody, nil
}
// HTTPPut 发送PUT请求
func (b *BasePanService) HTTPPut(requestURL string, data interface{}) ([]byte, error) {
var body io.Reader
if data != nil {
jsonData, err := json.Marshal(data)
if err != nil {
return nil, err
}
body = bytes.NewBuffer(jsonData)
}
req, err := http.NewRequest("PUT", requestURL, body)
if err != nil {
return nil, err
}
// 设置请求头
for key, value := range b.headers {
req.Header.Set(key, value)
}
// 如果没有设置Content-Type默认设置为application/json
if _, exists := b.headers["Content-Type"]; !exists && data != nil {
req.Header.Set("Content-Type", "application/json")
}
resp, err := b.httpClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("HTTP请求失败: %d, %s", resp.StatusCode, string(respBody))
}
return respBody, nil
}
// HTTPDelete 发送DELETE请求
func (b *BasePanService) HTTPDelete(requestURL string) ([]byte, error) {
req, err := http.NewRequest("DELETE", requestURL, nil)
if err != nil {
return nil, err
}
// 设置请求头
for key, value := range b.headers {
req.Header.Set(key, value)
}
resp, err := b.httpClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("HTTP请求失败: %d, %s", resp.StatusCode, string(respBody))
}
return respBody, nil
}
// ExecuteWithRetry 带重试的请求执行
func (b *BasePanService) ExecuteWithRetry(executeFunc func() ([]byte, error), maxRetries int, retryDelay time.Duration) ([]byte, error) {
var lastErr error
for attempt := 0; attempt <= maxRetries; attempt++ {
if attempt > 0 {
time.Sleep(retryDelay)
}
data, err := executeFunc()
if err == nil {
return data, nil
}
lastErr = err
}
return nil, fmt.Errorf("重试%d次后仍然失败: %v", maxRetries, lastErr)
}
// ParseJSONResponse 解析JSON响应
func (b *BasePanService) ParseJSONResponse(data []byte, v interface{}) error {
return json.Unmarshal(data, v)
}
// IsValidURL 验证URL格式
func (b *BasePanService) IsValidURL(urlStr string) bool {
_, err := url.Parse(urlStr)
return err == nil
}
// ExtractFileName 从URL中提取文件名
func (b *BasePanService) ExtractFileName(urlStr string) string {
parts := strings.Split(urlStr, "/")
if len(parts) > 0 {
return parts[len(parts)-1]
}
return ""
}
// SanitizeFileName 清理文件名
func (b *BasePanService) SanitizeFileName(fileName string) string {
// 移除或替换不合法的字符
invalidChars := []string{"<", ">", ":", "\"", "/", "\\", "|", "?", "*"}
result := fileName
for _, char := range invalidChars {
result = strings.ReplaceAll(result, char, "_")
}
return result
}