各位 v 友我又来了,国庆前分享过一款为 Go 打造的网络请求库,那会的设计实现并发需要手动加锁,性能大打折扣。这次分享的是回炉重造的 真线程安全 版本,并删除了冗余的 API,不到 500 行代码实现完整功能。PS:纯属分享,不是推广,开发者水平有限也不推荐在生产环境使用。
Github: https://github.com/winterssy/sreq
go get -u github.com/winterssy/sreq
import "github.com/winterssy/sreq"
sreq 发送请求几乎跟基础库 net/http 一样,无缝切换。举个栗子,如果你之前的请求是这样的:
resp, err := http.Get("http://www.baidu.com")
使用 sreq 你只须这样:
resp, err := sreq.Get("http://www.baidu.com").Resolve()
data, err := sreq.
Get("http://httpbin.org/get",
sreq.WithParams(sreq.Value{
"key1": "value1",
"key2": "value2",
}),
).
Text()
if err != nil {
panic(err)
}
fmt.Println(data)
data, err := sreq.
Get("http://httpbin.org/get",
sreq.WithHeaders(sreq.Value{
"Origin": "http://httpbin.org",
"Referer": "http://httpbin.org",
}),
).
Text()
if err != nil {
panic(err)
}
fmt.Println(data)
data, err := sreq.
Get("http://httpbin.org/cookies/set",
sreq.WithCookies(
&http.Cookie{
Name: "name1",
Value: "value1",
},
&http.Cookie{
Name: "name2",
Value: "value2",
},
),
).
Text()
if err != nil {
panic(err)
}
fmt.Println(data)
data, err := sreq.
Post("http://httpbin.org/post",
sreq.WithForm(sreq.Value{
"key1": "value1",
"key2": "value2",
}),
).
Text()
if err != nil {
panic(err)
}
fmt.Println(data)
data, err := sreq.
Post("http://httpbin.org/post").
JSON(sreq.Data{
"msg": "hello world",
"num": 2019,
}).
Send().
Text()
if err != nil {
panic(err)
}
fmt.Println(data)
data, err := sreq.
Post("http://httpbin.org/post", sreq.WithFiles(
&sreq.File{
FieldName: "testimage1",
FileName: "testimage1.jpg",
FilePath: "./testdata/testimage1.jpg",
},
&sreq.File{
FieldName: "testimage2",
FileName: "testimage2.jpg",
FilePath: "./testdata/testimage2.jpg",
},
)).
Text()
if err != nil {
panic(err)
}
fmt.Println(data)
data, err := sreq.
Get("http://httpbin.org/basic-auth/admin/pass",
sreq.WithBasicAuth("admin", "pass"),
).
Text()
if err != nil {
panic(err)
}
fmt.Println(data)
data, err := sreq.
Get("http://httpbin.org/bearer",
sreq.WithBearerToken("sreq"),
).
Text()
if err != nil {
panic(err)
}
fmt.Println(data)
如果你希望每个 HTTP 请求都带上一些默认选项,可以通过自定义 sreq 客户端实现。
req := sreq.New(nil,
sreq.WithParams(sreq.Value{
"defaultKey1": "defaultValue1",
"defaultKey2": "defaultValue2",
}),
)
data, err := req.
Get("http://httpbin.org/get",
sreq.WithParams(sreq.Value{
"key1": "value1",
"key2": "value2",
}),
).
Text()
if err != nil {
panic(err)
}
fmt.Println(data)
data, err = req.
Get("http://httpbin.org/get",
sreq.WithParams(sreq.Value{
"key3": "value3",
"key4": "value4",
}),
).
Text()
if err != nil {
panic(err)
}
fmt.Println(data)
sreq 没有提供直接修改传输层、重定向策略、cookie jar、超时、代理或者其它能通过构造 *http.Client
实现配置的 API,你可以通过自定义 sreq 客户端来设置它们。
transport := &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
redirectPolicy := func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
}
jar, _ := cookiejar.New(&cookiejar.Options{
PublicSuffixList: publicsuffix.List,
})
timeout := 120 * time.Second
httpClient := &http.Client{
Transport: transport,
CheckRedirect: redirectPolicy,
Jar: jar,
Timeout: timeout,
}
req := sreq.New( httpClient)
data, err := req.
Get("http://httpbin.org/get").
Text()
if err != nil {
panic(err)
}
fmt.Println(data)
sreq 是线程安全的,你可以无障碍地在 goroutines 中使用它。
const MaxWorker = 1000
wg := new(sync.WaitGroup)
for i := 0; i < MaxWorker; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
params := sreq.Value{}
params.Set(fmt.Sprintf("key%d", i), fmt.Sprintf("value%d", i))
data, err := sreq.
Get("http://httpbin.org/get",
sreq.WithParams(params),
).
Text()
if err != nil {
return
}
fmt.Println(data)
}(i)
}
wg.Wait()
1
GoLand 2019-10-02 15:57:09 +08:00
Go 里面就不叫线程安全了,bro。
|
3
EdwardLeeJan 2019-10-02 20:38:35 +08:00 via iPhone
不错,贴合 http 协议的使用方式
|
4
jedihy 2019-10-04 23:58:44 +08:00 via iPhone
支持 https 吗
|
5
SunspotsInys 2021-04-23 22:42:55 +08:00
是不维护了吗?
|