package rules import ( "bytes" "encoding/json" "errors" "fmt" "iwarma.ru/console/correlator/events" "net/http" "text/template" "time" log "github.com/sirupsen/logrus" ) const ( HttpActionType = "http" ) // HttpAction Send record via HTTP. Wil use application/json if empty content type set type HttpAction struct { Url string Template string ContentType string bodyTemplate *template.Template } func (action HttpAction) GetType() string { return HttpActionType } func (action *HttpAction) Perform(events *[]*events.Event) error { contextLogger := log.WithFields(log.Fields{"type": HttpActionType, "event_count": len(*events)}) contextLogger.Debug("Start action") defer contextLogger.Debug("End action") if events == nil { contextLogger.Error("Nil events provided") return errors.New("nil events provided") } // Create template if action.bodyTemplate == nil { bodyTemplate, err := template.New("Action").Parse(action.Template) if err != nil { return err } action.bodyTemplate = bodyTemplate } for _, cur := range *events { // Render template var buf bytes.Buffer err := action.bodyTemplate.Execute(&buf, *cur) if err != nil { return err } reader := bytes.NewReader(buf.Bytes()) http.DefaultClient.Timeout = time.Second * 30 _, err = http.Post(action.Url, action.ContentType, reader) if err != nil { return err } } http.DefaultClient.CloseIdleConnections() return nil } func (action HttpAction) MarshalJSON() ([]byte, error) { return json.Marshal(struct { CurType string `json:"type"` Url string `json:"url"` Template string `json:"template"` ContentType string `json:"content_type"` }{ CurType: HttpActionType, Url: action.Url, Template: action.Template, ContentType: action.ContentType, }) } func (action *HttpAction) UnmarshalJSON(b []byte) error { cur := struct { CurType string `json:"type"` Url string `json:"url"` ContentType string `json:"content_type"` Template string `json:"template"` }{} err := json.Unmarshal(b, &cur) if err != nil { return err } if cur.CurType != HttpActionType { return fmt.Errorf("bad action type. Expect http, got %s", cur.CurType) } action.Url = cur.Url action.Template = cur.Template action.ContentType = cur.ContentType return nil } func (action *HttpAction) ParseInterface(v interface{}) error { m, ok := v.(map[string]interface{}) if !ok { return fmt.Errorf("can't parse %v from %T", v, v) } action.Url, ok = m["url"].(string) if !ok { return fmt.Errorf("can't get URL") } // Template can be in data or template if action.Template, ok = m["data"].(string); !ok { if action.Template, ok = m["template"].(string); !ok { return fmt.Errorf("can't get template") } } if action.ContentType, ok = m["content_type"].(string); !ok { return fmt.Errorf("no content type provided") } return nil }