Некоторые проверки не удались
CI / test (push) Successful in 2m5s
Docker / Build and publish worker image (push) Failing after 31s
100 строки
2.6 KiB
Go
100 строки
2.6 KiB
Go
package sender
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"crypto/hmac"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"errors"
|
|
"io"
|
|
"net/http"
|
|
"time"
|
|
|
|
"rocketgit.ru/rsmon/worker/app/models"
|
|
"rocketgit.ru/rsmon/worker/config/application"
|
|
)
|
|
|
|
const envProduction = "production"
|
|
|
|
// RunWebhook provides functionality.
|
|
func RunWebhook(message *models.Message) (*string, error) {
|
|
if application.Env != envProduction {
|
|
return nil, errors.New("not sending in env " + application.Env)
|
|
}
|
|
|
|
body, err := json.Marshal(message)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
resp, err := httpClient.Post(
|
|
message.Contact.Value,
|
|
"application/json",
|
|
bytes.NewBuffer(body),
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
defer resp.Body.Close() //nolint:errcheck
|
|
body, err = io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
str := string(body)
|
|
return &str, nil
|
|
}
|
|
|
|
// SendWebhookWithCredential delivers a webhook notification using the
|
|
// provided wire credential block. Phase 1 ships an empty signing secret;
|
|
// phase 4 will plumb the per-account secret through Contact.Data. The
|
|
// signature header is X-RSMon-Signature (hex-encoded HMAC-SHA256 of the
|
|
// body), matching what webhook consumers in the existing fleet expect.
|
|
//
|
|
// The payload matches the wire.NotificationTask shape so customers
|
|
// receiving the legacy Message JSON see one fewer breaking change.
|
|
func SendWebhookWithCredential(payload []byte, contactValue, signingSecret string) (*string, error) {
|
|
return SendWebhookWithCredentialContext(context.Background(), payload, contactValue, signingSecret)
|
|
}
|
|
|
|
func SendWebhookWithCredentialContext(ctx context.Context, payload []byte, contactValue, signingSecret string) (*string, error) {
|
|
if application.Env != envProduction {
|
|
return nil, errors.New("not sending in env " + application.Env)
|
|
}
|
|
if contactValue == "" {
|
|
return nil, errors.New("webhook contact value is empty")
|
|
}
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, contactValue, bytes.NewReader(payload))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.Header.Set("User-Agent", "rsmon-worker/1")
|
|
if signingSecret != "" {
|
|
mac := hmac.New(sha256.New, []byte(signingSecret))
|
|
mac.Write(payload)
|
|
req.Header.Set("X-RSMon-Signature", "sha256="+hex.EncodeToString(mac.Sum(nil)))
|
|
}
|
|
|
|
client := &http.Client{Timeout: 60 * time.Second}
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close() //nolint:errcheck
|
|
|
|
respBody, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if resp.StatusCode >= 500 {
|
|
return nil, errors.New("webhook upstream " + resp.Status)
|
|
}
|
|
str := string(respBody)
|
|
return &str, nil
|
|
}
|