Files
Go-Web-Template/server/utils/request/http.go
2026-04-07 09:03:48 +08:00

128 lines
2.7 KiB
Go
Raw 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 request
import (
"bytes"
"context"
"encoding/json"
"net/http"
"net/url"
"time"
)
func HttpRequest(
urlStr string,
method string,
headers map[string]string,
params map[string]string,
data any) (*http.Response, error) {
return doJSONRequest(context.Background(), 0, urlStr, method, headers, params, data)
}
// HttpRequestWithTimeout 发送HTTP请求支持自定义超时时间
// timeout 参数可选,单位为时间.Duration默认值为 10 分钟
func HttpRequestWithTimeout(
urlStr string,
method string,
headers map[string]string,
params map[string]string,
data any,
timeout ...time.Duration) (*http.Response, error) {
t := 10 * time.Minute
if len(timeout) > 0 && timeout[0] > 0 {
t = timeout[0]
}
return doJSONRequest(context.Background(), t, urlStr, method, headers, params, data)
}
// HttpRequestWithContextAndTimeout 发送HTTP请求支持自定义超时时间和上下文
func HttpRequestWithContextAndTimeout(
ctx context.Context,
urlStr string,
method string,
headers map[string]string,
params map[string]string,
data any,
timeout ...time.Duration) (*http.Response, error) {
t := 10 * time.Minute
if len(timeout) > 0 {
if timeout[0] < 0 {
t = 0 // 负值表示不设置超时(用于 SSE 等流式场景)
} else if timeout[0] > 0 {
t = timeout[0]
}
}
return doJSONRequest(ctx, t, urlStr, method, headers, params, data)
}
func doJSONRequest(
ctx context.Context,
timeout time.Duration,
urlStr string,
method string,
headers map[string]string,
params map[string]string,
data any) (*http.Response, error) {
if ctx == nil {
ctx = context.Background()
}
// URL
u, err := url.Parse(urlStr)
if err != nil {
return nil, err
}
// 添加查询参数
query := u.Query()
for k, v := range params {
query.Set(k, v)
}
u.RawQuery = query.Encode()
// 将数据编码为JSON
buf := new(bytes.Buffer)
if data != nil {
b, err := json.Marshal(data)
if err != nil {
return nil, err
}
buf = bytes.NewBuffer(b)
}
// 创建请求
req, err := http.NewRequestWithContext(ctx, method, u.String(), buf)
if err != nil {
return nil, err
}
for k, v := range headers {
req.Header.Set(k, v)
}
if data != nil {
req.Header.Set("Content-Type", "application/json")
}
client := &http.Client{}
if timeout > 0 {
client.Timeout = timeout
}
// 当请求 SSE 流时,禁用 Transport 层的自动 gzip 压缩
// 避免 gzip 解压缓冲导致 SSE 事件无法实时到达
if req.Header.Get("Accept") == "text/event-stream" {
client.Transport = &http.Transport{
DisableCompression: true,
}
}
// 发送请求
resp, err := client.Do(req)
if err != nil {
return nil, err
}
// 返回响应,调用方负责关闭
return resp, nil
}