🚧 Improve HTTP language parser
This commit is contained in:
164
internal/services/httpclient_service.go
Normal file
164
internal/services/httpclient_service.go
Normal file
@@ -0,0 +1,164 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/wailsapp/wails/v3/pkg/services/log"
|
||||
"resty.dev/v3"
|
||||
)
|
||||
|
||||
// HttpClientService HTTP客户端服务
|
||||
type HttpClientService struct {
|
||||
logger *log.LogService
|
||||
client *resty.Client
|
||||
}
|
||||
|
||||
// HttpRequest HTTP请求结构
|
||||
type HttpRequest struct {
|
||||
Method string `json:"method"`
|
||||
URL string `json:"url"`
|
||||
Headers map[string]string `json:"headers"`
|
||||
BodyType string `json:"bodyType,omitempty"` // json, formdata, urlencoded, text
|
||||
Body interface{} `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// HttpResponse HTTP响应结构
|
||||
type HttpResponse struct {
|
||||
Status string `json:"status"` // 使用resp.Status()返回完整状态如"200 OK"
|
||||
Time int64 `json:"time"` // 响应时间(毫秒)
|
||||
RequestSize string `json:"requestSize"` // 请求大小
|
||||
Body interface{} `json:"body"`
|
||||
Headers http.Header `json:"headers"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Error interface{} `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// NewHttpClientService 创建新的HTTP客户端服务实例
|
||||
func NewHttpClientService(logger *log.LogService) *HttpClientService {
|
||||
client := resty.New().
|
||||
SetTimeout(30 * time.Second).
|
||||
SetRetryCount(0).
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
"Access-Control-Allow-Methods": "*",
|
||||
"Access-Control-Allow-Headers": "*",
|
||||
"Access-Control-Allow-Credentials": "true",
|
||||
})
|
||||
|
||||
return &HttpClientService{
|
||||
logger: logger,
|
||||
client: client,
|
||||
}
|
||||
}
|
||||
|
||||
// ExecuteRequest 执行HTTP请求
|
||||
func (hcs *HttpClientService) ExecuteRequest(ctx context.Context, request *HttpRequest) (*HttpResponse, error) {
|
||||
// 创建请求
|
||||
req := hcs.client.R().SetContext(ctx)
|
||||
|
||||
// 设置请求头
|
||||
if request.Headers != nil {
|
||||
req.SetHeaders(request.Headers)
|
||||
}
|
||||
|
||||
// 设置请求体
|
||||
if err := hcs.setRequestBody(req, request); err != nil {
|
||||
return nil, fmt.Errorf("set request body failed: %w", err)
|
||||
}
|
||||
|
||||
// 执行请求
|
||||
resp, err := req.Execute(strings.ToUpper(request.Method), request.URL)
|
||||
|
||||
// 构建响应对象
|
||||
return hcs.buildResponse(resp, err)
|
||||
}
|
||||
|
||||
// setRequestBody 设置请求体
|
||||
func (hcs *HttpClientService) setRequestBody(req *resty.Request, request *HttpRequest) error {
|
||||
if request.Body == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch strings.ToLower(request.BodyType) {
|
||||
case "json":
|
||||
req.SetHeader("Content-Type", "application/json")
|
||||
req.SetBody(request.Body)
|
||||
case "formdata":
|
||||
if formData, ok := request.Body.(map[string]interface{}); ok {
|
||||
for key, value := range formData {
|
||||
req.SetFormData(map[string]string{key: fmt.Sprintf("%v", value)})
|
||||
}
|
||||
}
|
||||
case "urlencoded":
|
||||
req.SetHeader("Content-Type", "application/x-www-form-urlencoded")
|
||||
if formData, ok := request.Body.(map[string]interface{}); ok {
|
||||
values := url.Values{}
|
||||
for key, value := range formData {
|
||||
values.Set(key, fmt.Sprintf("%v", value))
|
||||
}
|
||||
req.SetBody(values.Encode())
|
||||
}
|
||||
case "text":
|
||||
req.SetHeader("Content-Type", "text/plain")
|
||||
req.SetBody(fmt.Sprintf("%v", request.Body))
|
||||
default:
|
||||
return fmt.Errorf("unsupported body type: %s", request.BodyType)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// buildResponse 构建响应对象
|
||||
func (hcs *HttpClientService) buildResponse(resp *resty.Response, err error) (*HttpResponse, error) {
|
||||
httpResp := &HttpResponse{
|
||||
Timestamp: time.Now(),
|
||||
}
|
||||
|
||||
// 如果有错误,设置错误状态并返回
|
||||
if err != nil {
|
||||
httpResp.Status = "Request Failed"
|
||||
httpResp.Error = err.Error()
|
||||
return httpResp, nil
|
||||
}
|
||||
|
||||
// 设置基本响应信息
|
||||
httpResp.Status = resp.Status()
|
||||
httpResp.Time = resp.Duration().Milliseconds()
|
||||
httpResp.RequestSize = hcs.formatBytes(resp.Size())
|
||||
|
||||
if errorData := resp.Error(); errorData != nil {
|
||||
httpResp.Error = errorData
|
||||
}
|
||||
|
||||
// 设置响应头
|
||||
httpResp.Headers = resp.Header()
|
||||
httpResp.Body = resp.String()
|
||||
|
||||
return httpResp, nil
|
||||
}
|
||||
|
||||
// formatBytes 格式化字节大小
|
||||
func (hcs *HttpClientService) formatBytes(bytes int64) string {
|
||||
if bytes < 0 {
|
||||
return "0 B"
|
||||
}
|
||||
|
||||
const unit = 1024
|
||||
if bytes < unit {
|
||||
return fmt.Sprintf("%d B", bytes)
|
||||
}
|
||||
|
||||
div, exp := int64(unit), 0
|
||||
for n := bytes / unit; n >= unit; n /= unit {
|
||||
div *= unit
|
||||
exp++
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%.1f %cB", float64(bytes)/float64(div), "KMGTPE"[exp])
|
||||
}
|
||||
Reference in New Issue
Block a user