-
Notifications
You must be signed in to change notification settings - Fork 5
/
http.go
134 lines (112 loc) · 3.35 KB
/
http.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package action
import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"strings"
"time"
"github.com/mylxsw/adanos-alert/configs"
"github.com/mylxsw/adanos-alert/internal/repository"
"github.com/mylxsw/asteria/log"
"github.com/mylxsw/go-utils/str"
)
// HTTPAction HTTP 动作
type HTTPAction struct {
manager Manager
}
// Validate 参数校验
func (act HTTPAction) Validate(meta string, userRefs []string) error {
var httpMeta HTTPMeta
if err := json.Unmarshal([]byte(meta), &httpMeta); err != nil {
return err
}
httpURL := strings.TrimSpace(httpMeta.URL)
if httpURL == "" {
return errors.New("URL is required")
}
if _, err := url.Parse(httpURL); err != nil {
return fmt.Errorf("invalid url: %w", err)
}
method := strings.ToUpper(httpMeta.Method)
if !str.In(method, []string{"GET", "POST", "PUT", "PATCH", "HEAD", "DELETE", "OPTIONS", "PURGE"}) {
return fmt.Errorf("not support such request method: %s", method)
}
return nil
}
// NewHTTPAction create a new HTTPAction
func NewHTTPAction(manager Manager) *HTTPAction {
return &HTTPAction{manager: manager}
}
// Handle 动作处理
func (act HTTPAction) Handle(rule repository.Rule, trigger repository.Trigger, grp repository.EventGroup) error {
var meta HTTPMeta
if err := json.Unmarshal([]byte(trigger.Meta), &meta); err != nil {
return fmt.Errorf("parse http meta failed: %v", err)
}
return act.manager.Resolve(func(conf *configs.Config, evtRepo repository.EventRepo) error {
payload, _ := createPayloadAndSummary(act.manager, "http", conf, evtRepo, rule, trigger, grp)
body := parseTemplate(act.manager, meta.Body, payload)
var reqBody io.Reader
if body != "" {
reqBody = strings.NewReader(body)
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, meta.Method, parseTemplate(act.manager, meta.URL, payload), reqBody)
if err != nil {
log.WithFields(log.Fields{
"trigger": trigger,
"rule_id": rule.ID.Hex(),
}).Errorf("create request failed: %v", err)
return fmt.Errorf("create request failed: %v", err)
}
for _, header := range meta.Headers {
req.Header.Add(header.Key, parseTemplate(act.manager, header.Value, payload))
}
client := &http.Client{}
client.Timeout = 5 * time.Second
resp, err := client.Do(req)
if err != nil {
log.WithFields(log.Fields{
"trigger": trigger,
"rule_id": rule.ID.Hex(),
}).Errorf("send http request failed: %v", err)
return fmt.Errorf("send http request failed: %v", err)
}
defer resp.Body.Close()
respBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.WithFields(log.Fields{
"trigger": trigger,
"rule_id": rule.ID.Hex(),
"resp": string(respBody),
}).Errorf("read http response failed: %v", err)
return nil
}
if log.DebugEnabled() {
log.WithFields(log.Fields{
"trigger": trigger,
"rule_id": rule.ID.Hex(),
"resp": string(respBody),
}).Debug("send message to jira succeed")
}
return nil
})
}
// HTTPHeaderMeta HTTP 请求头
type HTTPHeaderMeta struct {
Key string `json:"key"`
Value string `json:"value"`
}
// HTTPMeta HTTP 元数据
type HTTPMeta struct {
URL string `json:"url"`
Method string `json:"method"`
Headers []HTTPHeaderMeta `json:"headers"`
Body string `json:"body"`
}