Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
so-operation-api
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
smart-operation
so-operation-api
Commits
9b36b44b
Commit
9b36b44b
authored
Jul 12, 2023
by
陈子龙
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'dev' of
https://cloud.wodcloud.com/git/smart-operation/so-operation-api
into dev
parents
b134e363
d8f6e959
Changes
9
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
353 additions
and
5 deletions
+353
-5
go.mod
go.mod
+10
-1
go.sum
go.sum
+28
-0
src/common/conf/options.go
src/common/conf/options.go
+3
-0
src/main.go
src/main.go
+6
-4
src/pkg/beagle/constant/constant.go
src/pkg/beagle/constant/constant.go
+10
-0
src/service/k8s/common.go
src/service/k8s/common.go
+94
-0
src/service/k8s/prometheusrule.go
src/service/k8s/prometheusrule.go
+55
-0
src/service/k8s/prometheusrule_test.go
src/service/k8s/prometheusrule_test.go
+108
-0
src/util/http.go
src/util/http.go
+39
-0
No files found.
go.mod
View file @
9b36b44b
...
...
@@ -42,10 +42,13 @@ require (
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/goccy/go-json v0.10.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/henrylee2cn/ameda v1.5.0 // indirect
github.com/henrylee2cn/goutil v0.0.0-20220704075712-42f2ec55fe8d // indirect
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect
...
...
@@ -62,6 +65,7 @@ require (
github.com/nyaruka/phonenumbers v1.1.7 // indirect
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.66.0 // indirect
github.com/rs/xid v1.5.0 // indirect
github.com/sirupsen/logrus v1.9.2 // indirect
github.com/syndtr/goleveldb v1.0.0 // indirect
...
...
@@ -75,11 +79,16 @@ require (
golang.org/x/image v0.0.0-20190501045829-6d32002ffd75 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/text v0.
9
.0 // indirect
golang.org/x/text v0.
10
.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.27.2 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/utils v0.0.0-20230505201702-9f6742963106 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978 // indirect
)
go.sum
View file @
9b36b44b
This diff is collapsed.
Click to expand it.
src/common/conf/options.go
View file @
9b36b44b
...
...
@@ -43,6 +43,9 @@ type Config struct {
SmsAccessSecret
string
SmsTemplateLogin
string
SmsSignName
string
AweRestURL
string
KubernetesToken
string
}
const
(
...
...
src/main.go
View file @
9b36b44b
...
...
@@ -80,10 +80,12 @@ func initConfig() {
//PublicKeySSH: util.SetEnvStr("PUBLIC_KEY_SSH", "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCw4WT05QHzCD19348MfJfycS1NI9Jlj62PGrZ1rU9/kWQif5TV1rqHZ6qjAX2WfK+W3u4SV51MhZBkMZZOgZgJmdGiaZJkSmj+8gj6XU/bxslUd+BYUKqbE18gFkVDgqs6n2tcqJ2at3x+WEr81Msk2qvKuGEiIOzcJPICWKxwiw== chenzilong@example.com\n"),
OrderDingTalkAccessToken
:
util
.
SetEnvStr
(
"ORDER_DING_TALK_ACCESS_TOKEN"
,
"203fe1644b446bba0a34e6e622c523d39ee9916fdad94b9c64224449f659e20b"
),
OrderDingTalkSecret
:
util
.
SetEnvStr
(
"ORDER_DING_TALK_SECRET"
,
"SECa73d8372e336451c9daf29a99f750ee1bdd170c1dab910eab9cd06d729a831b7"
),
SmsAccessKeyId
:
util
.
SetEnvStr
(
"SMS_ACCESS_KEY"
,
"LTAI4GBcVubRjzX7ABPcHnhB"
),
// 短信key
SmsAccessSecret
:
util
.
SetEnvStr
(
"SMS_ACCESS_SECRET"
,
"dYE2dtABFOqYtK1ijcrits0yedHkw7"
),
// 短信secret
SmsTemplateLogin
:
util
.
SetEnvStr
(
"SMS_TEMPLATE_LOGIN"
,
"SMS_212925130"
),
// 短信验证码模板
SmsSignName
:
util
.
SetEnvStr
(
"SMS_SIGN_NAME"
,
"比格数据"
),
// 签名
SmsAccessKeyId
:
util
.
SetEnvStr
(
"SMS_ACCESS_KEY"
,
"LTAI4GBcVubRjzX7ABPcHnhB"
),
// 短信key
SmsAccessSecret
:
util
.
SetEnvStr
(
"SMS_ACCESS_SECRET"
,
"dYE2dtABFOqYtK1ijcrits0yedHkw7"
),
// 短信secret
SmsTemplateLogin
:
util
.
SetEnvStr
(
"SMS_TEMPLATE_LOGIN"
,
"SMS_212925130"
),
// 短信验证码模板
SmsSignName
:
util
.
SetEnvStr
(
"SMS_SIGN_NAME"
,
"比格数据"
),
// 签名
AweRestURL
:
util
.
SetEnvStr
(
"AWE_REST_URL"
,
"http://awecloud-rest/awecloud/rest"
),
// awecloud-rest
KubernetesToken
:
util
.
SetEnvStr
(
"AWE_REST_K8S_TOKEN"
,
"eyJhbGciOiJSUzI1NiIsImtpZCI6InJ1alJzNEVGamN5UC0wRU1rS1BKQ0JZVUtNNWpzR0t2bmlrSlJhY2Q3R00ifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJiZWFnbGUtc3lzdGVtIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6InJvb3QiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoicm9vdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjRlMDM0OTI3LTc0ZTMtNDQ5Yy1hN2RlLWExMGE3MjU1NGYyMCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpiZWFnbGUtc3lzdGVtOnJvb3QifQ.YPLE_E2kIeo-YFQtKScBt5p4KhnniJF9n3iWN2i9UMYS06lIsq2-2wBrgON-YsJihWJupYyDQRiZ9h8bUWTrQzhnpsnuJ_aUclKyAw3QOT9rjvZhJp7qP--27dmdspSHncKtvIiprWE7UTUKzvF33WsMB0fSYFqYXOggNFMoT-fXmWwUXjgar3op0iOl3c3deJ_GeBzFyLSHEuGM7OVdjU8032aUmTen0Kji_P1yB4-O3Iqd0OdVs33BQy_tycjbxhQ8TDEpqrqhLnXjAwJCprLDEpFMx7ODZbjB9Wmuns8yJhaRDxTO47rTME7ZIAxjZ-zLR_QybtW97rlwnUTaNw"
),
// k8s token
}
}
...
...
src/pkg/beagle/constant/constant.go
View file @
9b36b44b
...
...
@@ -122,3 +122,13 @@ var OpTypeIntMap = map[OpType]int{
DownMove
:
13
,
Export
:
14
,
}
// RiskLevel 风险等级
type
RiskLevel
int
const
(
RiskLevelLow
RiskLevel
=
iota
+
1
// 1:低风险
RiskLevelModerate
// 1:一般风险
RiskLevelHigh
// 3:较大风险
RiskLevelCritical
// 4:重大风险
)
src/service/k8s/common.go
0 → 100644
View file @
9b36b44b
package
k8s
import
(
"encoding/json"
"fmt"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/util"
"github.com/pkg/errors"
v1
"k8s.io/apimachinery/pkg/apis/meta/v1"
)
type
K8sSvc
struct
{
Header
map
[
string
]
string
}
type
SendFile
struct
{
Name
string
`json:"name"`
Namespace
string
`json:"namespace"`
Content
interface
{}
`json:"content"`
}
type
K8sCsrfToken
struct
{
Token
string
`json:"token"`
}
type
UploadFileObj
struct
{
Name
string
`json:"name"`
Namespace
string
`json:"namespace"`
Content
Content
`json:"content"`
}
type
Content
struct
{
Kind
string
`json:"kind"`
ApiVersion
string
`json:"apiVersion"`
Metadata
v1
.
ObjectMeta
`json:"metadata"`
Spec
interface
{}
`json:"spec"`
}
type
AddBgObjectFile
struct
{
ApiVersion
string
`json:"apiVersion"`
Kind
string
`json:"kind"`
Metadata
struct
{
Name
string
`json:"name"`
Namespace
string
`json:"namespace"`
Annotations
map
[
string
]
string
`json:"annotations,omitempty"`
Labels
map
[
string
]
string
`json:"labels"`
}
`json:"metadata"`
Spec
interface
{}
`json:"spec"`
Data
interface
{}
`json:"data"`
}
var
KindBlackList
=
[]
string
{
"PersistentVolumeClaim"
,
"PersistentVolume"
,
"namespace"
}
func
(
k
*
K8sSvc
)
SendFile
(
content
*
Content
)
(
res
string
,
err
error
)
{
if
err
=
k
.
checkK8sKind
(
content
.
Kind
);
err
!=
nil
{
return
}
csrfUrl
:=
fmt
.
Sprintf
(
"%s/kubernetes/api/v1/csrftoken/appdeploymentfromfile"
,
conf
.
Options
.
AweRestURL
)
sendUrl
:=
fmt
.
Sprintf
(
"%s/kubernetes/api/v1/appdeploymentfromfile"
,
conf
.
Options
.
AweRestURL
)
csrf
,
err
:=
util
.
ProxySendRes
(
"GET"
,
csrfUrl
,
""
,
k
.
Header
)
if
err
!=
nil
{
return
""
,
err
}
csrfToken
:=
K8sCsrfToken
{}
json
.
Unmarshal
(
csrf
,
&
csrfToken
)
if
csrfToken
.
Token
==
""
{
err
:=
errors
.
New
(
"get csrfToken failed"
)
return
""
,
err
}
k
.
Header
[
"x-csrf-token"
]
=
csrfToken
.
Token
k
.
Header
[
"Content-Type"
]
=
"application/json"
// sendFile
sendFile
:=
SendFile
{
Name
:
content
.
Metadata
.
Name
,
Namespace
:
content
.
Metadata
.
Namespace
}
c
,
_
:=
json
.
Marshal
(
content
)
sendFile
.
Content
=
string
(
c
)
sStr
,
_
:=
json
.
Marshal
(
sendFile
)
k8sUserJwtRes
,
err
:=
util
.
ProxySendRes
(
"POST"
,
sendUrl
,
string
(
sStr
),
k
.
Header
)
if
err
!=
nil
{
return
""
,
err
}
res
=
string
(
k8sUserJwtRes
)
//json.Unmarshal(k8sUserJwtRes, &res)
return
}
func
(
k
*
K8sSvc
)
checkK8sKind
(
kind
string
)
(
err
error
)
{
for
_
,
v
:=
range
KindBlackList
{
if
kind
==
v
{
return
errors
.
New
(
"当前用户没有上传此类型资源的权限!"
)
}
}
return
nil
}
src/service/k8s/prometheusrule.go
0 → 100644
View file @
9b36b44b
package
k8s
import
(
"encoding/json"
"fmt"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/util"
"strings"
v1
"github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
)
var
(
PrometheusRuleGroup
=
"monitoring.beagle.io"
// kubectl api-resources | grep -i prome
PrometheusRuleVersion
=
"v1"
PrometheusRuleKind
=
"PrometheusRule"
PrometheusRuleApiVersion
=
PrometheusRuleGroup
+
"/"
+
PrometheusRuleVersion
PrometheusRuleName
=
strings
.
ToLower
(
PrometheusRuleKind
)
+
"s."
+
PrometheusRuleGroup
)
type
PrometheusRule
struct
{
Header
map
[
string
]
string
}
func
(
p
PrometheusRule
)
Create
(
pRule
*
v1
.
PrometheusRule
)
error
{
k8sSvc
:=
K8sSvc
{
Header
:
p
.
Header
}
c
:=
&
Content
{
Kind
:
PrometheusRuleKind
,
ApiVersion
:
PrometheusRuleApiVersion
,
Metadata
:
pRule
.
ObjectMeta
,
Spec
:
pRule
.
Spec
}
_
,
err
:=
k8sSvc
.
SendFile
(
c
)
return
err
}
func
(
p
PrometheusRule
)
Delete
(
namespace
string
,
name
string
)
error
{
delUrl
:=
fmt
.
Sprintf
(
"%s/kubernetes/api/v1/_raw/%s/namespace/%s/name/%s"
,
conf
.
Options
.
AweRestURL
,
PrometheusRuleName
,
namespace
,
name
)
_
,
err
:=
util
.
ProxySendRes
(
"DELETE"
,
delUrl
,
""
,
p
.
Header
)
return
err
}
func
(
p
PrometheusRule
)
Update
(
pRule
*
v1
.
PrometheusRule
)
error
{
updateUrl
:=
fmt
.
Sprintf
(
"%s/kubernetes/api/v1/_raw/%s/namespace/%s/name/%s"
,
conf
.
Options
.
AweRestURL
,
PrometheusRuleName
,
pRule
.
Namespace
,
pRule
.
Name
)
body
,
_
:=
json
.
Marshal
(
pRule
)
p
.
Header
[
"Content-Type"
]
=
"application/json"
_
,
err
:=
util
.
ProxySendRes
(
"PUT"
,
updateUrl
,
string
(
body
),
p
.
Header
)
return
err
}
func
(
p
PrometheusRule
)
Get
(
namespace
string
,
name
string
)
(
obj
*
v1
.
PrometheusRule
,
err
error
)
{
// http://awecloud-rest/awecloud/rest/kubernetes/api/v1/_raw/prometheusrules.monitoring.coreos.com/namespace/kube-public/name/nginx
getUrl
:=
fmt
.
Sprintf
(
"%s/kubernetes/api/v1/_raw/%s/namespace/%s/name/%s"
,
conf
.
Options
.
AweRestURL
,
PrometheusRuleName
,
namespace
,
name
)
res
,
err
:=
util
.
ProxySendRes
(
"GET"
,
getUrl
,
""
,
p
.
Header
)
if
err
!=
nil
{
return
}
err
=
json
.
Unmarshal
(
res
,
&
obj
)
return
}
src/service/k8s/prometheusrule_test.go
0 → 100644
View file @
9b36b44b
package
k8s
import
(
"fmt"
v1
"github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
"github.com/spf13/cast"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/constant"
"k8s.io/apimachinery/pkg/util/intstr"
"log"
"testing"
"time"
)
var
svc
PrometheusRule
var
obj
v1
.
PrometheusRule
var
AlertDefLabels
=
map
[
string
]
string
{
"app"
:
"prometheus"
,
"app.bd-apaas.com/cluster-component"
:
"monitoring"
,
"prometheus-operator"
:
"monitoring"
,
"release"
:
"beagle-prometheus"
,
}
func
init
()
{
conf
.
Options
=
&
conf
.
Config
{}
conf
.
Options
.
AweRestURL
=
"https://cloud.wodcloud.com/awecloud/rest"
conf
.
Options
.
KubernetesToken
=
"380e3557499a13c4ec4aa11d7456bb45ef2303c1"
header
:=
make
(
map
[
string
]
string
)
header
[
"Authorization"
]
=
"Bearer "
+
conf
.
Options
.
KubernetesToken
svc
=
PrometheusRule
{
Header
:
header
}
obj
=
v1
.
PrometheusRule
{}
obj
.
Name
=
"beagle-prometheus-operation-api-rules-101"
obj
.
Namespace
=
"beagle-monitoring"
obj
.
Labels
=
AlertDefLabels
}
func
TestRule
(
t
*
testing
.
T
)
{
group
:=
v1
.
RuleGroup
{}
group
.
Name
=
"demo-group-1m"
rule
:=
v1
.
Rule
{}
rule
.
Alert
=
"kubernetes启动状态"
rule
.
Annotations
=
make
(
map
[
string
]
string
)
rule
.
Annotations
[
"value"
]
=
"{{ $value }}"
rule
.
Annotations
[
"message"
]
=
"启动了"
rule
.
Expr
=
intstr
.
FromString
(
`up{endpoint="https", instance="192.168.1.244:6443", job="apiserver", namespace="default", service="kubernetes"} == 1`
)
ruleFor
:=
v1
.
Duration
(
"1m"
)
rule
.
For
=
&
ruleFor
rule
.
Labels
=
make
(
map
[
string
]
string
)
rule
.
Labels
[
"severity"
]
=
"warning"
rule
.
Labels
[
"severity_name"
]
=
"一般风险"
rule
.
Labels
[
"risk_level"
]
=
cast
.
ToString
(
constant
.
RiskLevelLow
)
rule
.
Labels
[
"source"
]
=
"so-operation-api"
rule
.
Labels
[
"alert_id"
]
=
"101"
group
.
Rules
=
append
(
group
.
Rules
,
rule
)
obj
.
Spec
.
Groups
=
append
(
obj
.
Spec
.
Groups
,
group
)
err
:=
svc
.
Create
(
&
obj
)
if
err
!=
nil
{
fmt
.
Println
(
"添加失败"
+
err
.
Error
())
}
else
{
fmt
.
Println
(
"添加成功"
)
}
}
func
TestGet
(
t
*
testing
.
T
)
{
// 获取对象
ruleObj
,
err
:=
svc
.
Get
(
obj
.
Namespace
,
obj
.
Name
)
if
err
!=
nil
{
fmt
.
Println
(
"获取失败"
+
err
.
Error
())
}
else
{
fmt
.
Println
(
"获取成功"
)
}
log
.
Printf
(
"ruleObj:%+v
\n
"
,
ruleObj
)
}
func
TestUpdate
(
t
*
testing
.
T
)
{
ruleObj
,
err
:=
svc
.
Get
(
obj
.
Namespace
,
obj
.
Name
)
if
err
!=
nil
{
fmt
.
Println
(
"获取失败"
+
err
.
Error
())
}
else
{
fmt
.
Println
(
"获取成功"
)
}
// 更新
ruleObj
.
Name
=
"galileo-101"
ruleObj
.
Spec
.
Groups
[
0
]
.
Rules
[
0
]
.
Alert
=
"请求次数大于10"
ruleObj
.
Spec
.
Groups
[
0
]
.
Name
=
"2分钟组"
ruleFor
:=
v1
.
Duration
(
"2m"
)
ruleObj
.
Spec
.
Groups
[
0
]
.
Rules
[
0
]
.
For
=
&
ruleFor
ruleObj
.
Spec
.
Groups
[
0
]
.
Rules
[
0
]
.
Expr
=
intstr
.
FromString
(
`up{endpoint="https", instance="192.168.1.244:6443", job="apiserver", namespace="default", service="kubernetes"} == 0`
)
err
=
svc
.
Update
(
ruleObj
)
if
err
!=
nil
{
fmt
.
Println
(
"更新失败"
+
err
.
Error
())
}
else
{
fmt
.
Println
(
"更新成功"
)
}
}
func
TestDelete
(
t
*
testing
.
T
)
{
// 删除
time
.
Sleep
(
time
.
Second
*
10
)
err
:=
svc
.
Delete
(
obj
.
Namespace
,
obj
.
Name
)
if
err
!=
nil
{
fmt
.
Println
(
"删除失败"
+
err
.
Error
())
}
else
{
fmt
.
Println
(
"删除成功"
)
}
}
src/util/http.go
View file @
9b36b44b
...
...
@@ -2,15 +2,20 @@ package util
import
(
"crypto/tls"
"errors"
"github.com/valyala/fasthttp"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"go.uber.org/zap"
"io"
"net"
"net/http"
"strings"
"sync"
"time"
)
var
lock
sync
.
RWMutex
const
(
MediaTypeJSON
=
"application/json"
MediaTypeXML
=
"application/xml"
...
...
@@ -121,3 +126,37 @@ func HttpSend(sendType string, url string, body string, header map[string]string
}
return
response
,
err
}
func
ProxySendRes
(
sendType
string
,
url
string
,
body
string
,
header
map
[
string
]
string
)
(
result
[]
byte
,
err
error
)
{
client
:=
&
http
.
Client
{}
var
reqest
*
http
.
Request
if
sendType
==
"GET"
||
sendType
==
"DELETE"
{
reqest
,
_
=
http
.
NewRequest
(
sendType
,
url
,
nil
)
}
else
if
sendType
==
"POST"
||
sendType
==
"PUT"
{
reqest
,
_
=
http
.
NewRequest
(
sendType
,
url
,
strings
.
NewReader
(
body
))
}
http
.
DefaultTransport
.
(
*
http
.
Transport
)
.
TLSClientConfig
=
&
tls
.
Config
{
InsecureSkipVerify
:
true
}
lock
.
Lock
()
if
header
==
nil
{
header
=
make
(
map
[
string
]
string
)
}
reqest
.
Header
.
Set
(
"Accept"
,
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
)
reqest
.
Header
.
Set
(
"Accept-Language"
,
"ja,zh-CN;q=0.8,zh;q=0.6"
)
reqest
.
Header
.
Set
(
"Connection"
,
"keep-alive"
)
for
k
,
v
:=
range
header
{
reqest
.
Header
.
Set
(
k
,
v
)
}
lock
.
Unlock
()
response
,
errc
:=
client
.
Do
(
reqest
)
if
errc
!=
nil
{
return
nil
,
errc
}
else
{
defer
response
.
Body
.
Close
()
body
,
erra
:=
io
.
ReadAll
(
response
.
Body
)
if
response
.
StatusCode
>=
400
{
err
=
errors
.
New
(
string
(
body
))
return
}
return
body
,
erra
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment