Some checks failed
CI/CD Pipeline / Test (push) Failing after 22m19s
CI/CD Pipeline / Security Scan (push) Failing after 5m57s
CI/CD Pipeline / Build (amd64, darwin) (push) Has been skipped
CI/CD Pipeline / Build (amd64, linux) (push) Has been skipped
CI/CD Pipeline / Build (amd64, windows) (push) Has been skipped
CI/CD Pipeline / Build (arm64, darwin) (push) Has been skipped
CI/CD Pipeline / Build (arm64, linux) (push) Has been skipped
CI/CD Pipeline / Build Docker Image (push) Has been skipped
CI/CD Pipeline / Create Release (push) Has been skipped
174 lines
4.0 KiB
Go
174 lines
4.0 KiB
Go
package parser
|
||
|
||
import (
|
||
"fmt"
|
||
"net/url"
|
||
"strconv"
|
||
"strings"
|
||
|
||
"github.com/subconverter-go/internal/logging"
|
||
)
|
||
|
||
// HTTPParser HTTP协议解析器
|
||
// 实现HTTP代理配置的解析功能
|
||
type HTTPParser struct {
|
||
logger *logging.Logger
|
||
}
|
||
|
||
// NewHTTPParser 创建新的HTTP解析器
|
||
// 返回初始化好的HTTPParser实例
|
||
func NewHTTPParser(logger *logging.Logger) *HTTPParser {
|
||
return &HTTPParser{
|
||
logger: logger,
|
||
}
|
||
}
|
||
|
||
// Parse 解析HTTP配置
|
||
// 支持http://和https://格式
|
||
func (p *HTTPParser) Parse(input string) (*ProxyConfig, error) {
|
||
p.logger.Debugf("Parsing HTTP configuration")
|
||
|
||
// 检查是否已经是URL格式
|
||
var parsedURL *url.URL
|
||
var err error
|
||
|
||
if strings.HasPrefix(input, "http://") || strings.HasPrefix(input, "https://") {
|
||
parsedURL, err = url.Parse(input)
|
||
} else {
|
||
// 尝试添加http://前缀
|
||
parsedURL, err = url.Parse("http://" + input)
|
||
}
|
||
|
||
if err != nil {
|
||
return nil, fmt.Errorf("failed to parse HTTP URL: %v", err)
|
||
}
|
||
|
||
config := &ProxyConfig{
|
||
Type: "http",
|
||
Protocol: "http",
|
||
Server: parsedURL.Hostname(),
|
||
}
|
||
|
||
// 解析端口
|
||
port, err := strconv.Atoi(parsedURL.Port())
|
||
if err != nil {
|
||
// 如果没有指定端口,使用默认端口
|
||
if parsedURL.Scheme == "https" {
|
||
config.Port = 443
|
||
} else {
|
||
config.Port = 80
|
||
}
|
||
} else {
|
||
config.Port = port
|
||
}
|
||
|
||
// 解析用户名和密码
|
||
var username, password string
|
||
if parsedURL.User != nil {
|
||
username = parsedURL.User.Username()
|
||
password, _ = parsedURL.User.Password()
|
||
}
|
||
|
||
// 解析备注
|
||
if parsedURL.Fragment != "" {
|
||
config.Name = parsedURL.Fragment
|
||
} else {
|
||
config.Name = fmt.Sprintf("http-%s:%d", config.Server, config.Port)
|
||
}
|
||
|
||
// 创建设置映射
|
||
settings := map[string]interface{}{
|
||
"udp": false, // HTTP代理不支持UDP
|
||
}
|
||
|
||
// 添加认证信息
|
||
if username != "" {
|
||
settings["username"] = username
|
||
if password != "" {
|
||
settings["password"] = password
|
||
}
|
||
}
|
||
|
||
// 如果是HTTPS,添加TLS配置
|
||
if parsedURL.Scheme == "https" {
|
||
settings["tls"] = true
|
||
}
|
||
|
||
config.Settings = settings
|
||
config.UDP = false
|
||
|
||
p.logger.Infof("Successfully parsed HTTP configuration for server: %s:%d", config.Server, config.Port)
|
||
return config, nil
|
||
}
|
||
|
||
// Validate 验证HTTP配置
|
||
func (p *HTTPParser) Validate(config *ProxyConfig) error {
|
||
p.logger.Debugf("Validating HTTP configuration")
|
||
|
||
// 检查必要字段
|
||
if config.Server == "" {
|
||
return fmt.Errorf("server address is required")
|
||
}
|
||
|
||
if config.Port <= 0 || config.Port > 65535 {
|
||
return fmt.Errorf("invalid port number: %d", config.Port)
|
||
}
|
||
|
||
// 验证认证信息
|
||
username := p.getUsername(config)
|
||
password := p.getPassword(config)
|
||
|
||
// 如果提供了用户名,验证密码是否也提供
|
||
if username != "" && password == "" {
|
||
p.logger.Warn("Username provided but password is empty")
|
||
}
|
||
|
||
// 如果没有提供用户名,确保也没有密码
|
||
if username == "" && password != "" {
|
||
return fmt.Errorf("password provided without username")
|
||
}
|
||
|
||
// 验证TLS配置
|
||
tlsEnabled := p.getTLS(config)
|
||
if tlsEnabled && config.Port != 443 {
|
||
p.logger.Warnf("HTTPS proxy detected but port is not 443: %d", config.Port)
|
||
}
|
||
|
||
p.logger.Debug("HTTP configuration validation passed")
|
||
return nil
|
||
}
|
||
|
||
// getUsername 从配置中获取用户名
|
||
func (p *HTTPParser) getUsername(config *ProxyConfig) string {
|
||
if username, exists := config.Settings["username"]; exists {
|
||
if usernameStr, ok := username.(string); ok {
|
||
return usernameStr
|
||
}
|
||
}
|
||
return ""
|
||
}
|
||
|
||
// getPassword 从配置中获取密码
|
||
func (p *HTTPParser) getPassword(config *ProxyConfig) string {
|
||
if password, exists := config.Settings["password"]; exists {
|
||
if passwordStr, ok := password.(string); ok {
|
||
return passwordStr
|
||
}
|
||
}
|
||
return ""
|
||
}
|
||
|
||
// getTLS 从配置中获取TLS设置
|
||
func (p *HTTPParser) getTLS(config *ProxyConfig) bool {
|
||
if tls, exists := config.Settings["tls"]; exists {
|
||
if tlsBool, ok := tls.(bool); ok {
|
||
return tlsBool
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
// GetSupportedProtocols 获取支持的协议
|
||
func (p *HTTPParser) GetSupportedProtocols() []string {
|
||
return []string{"http", "https"}
|
||
} |