webhook.go 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. package webhook
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "io"
  6. "net/http"
  7. "time"
  8. "github.com/pkg/errors"
  9. "google.golang.org/protobuf/encoding/protojson"
  10. v1pb "github.com/usememos/memos/proto/gen/api/v1"
  11. )
  12. var (
  13. // timeout is the timeout for webhook request. Default to 30 seconds.
  14. timeout = 30 * time.Second
  15. )
  16. // Post posts the message to webhook endpoint.
  17. func Post(requestPayload *v1pb.WebhookRequestPayload) error {
  18. body, err := protojson.Marshal(requestPayload)
  19. if err != nil {
  20. return errors.Wrapf(err, "failed to marshal webhook request to %s", requestPayload.Url)
  21. }
  22. req, err := http.NewRequest("POST", requestPayload.Url, bytes.NewBuffer(body))
  23. if err != nil {
  24. return errors.Wrapf(err, "failed to construct webhook request to %s", requestPayload.Url)
  25. }
  26. req.Header.Set("Content-Type", "application/json")
  27. client := &http.Client{
  28. Timeout: timeout,
  29. }
  30. resp, err := client.Do(req)
  31. if err != nil {
  32. return errors.Wrapf(err, "failed to post webhook to %s", requestPayload.Url)
  33. }
  34. b, err := io.ReadAll(resp.Body)
  35. if err != nil {
  36. return errors.Wrapf(err, "failed to read webhook response from %s", requestPayload.Url)
  37. }
  38. defer resp.Body.Close()
  39. if resp.StatusCode < 200 || resp.StatusCode > 299 {
  40. return errors.Errorf("failed to post webhook %s, status code: %d, response body: %s", requestPayload.Url, resp.StatusCode, b)
  41. }
  42. response := &struct {
  43. Code int `json:"code"`
  44. Message string `json:"message"`
  45. }{}
  46. if err := json.Unmarshal(b, response); err != nil {
  47. return errors.Wrapf(err, "failed to unmarshal webhook response from %s", requestPayload.Url)
  48. }
  49. if response.Code != 0 {
  50. return errors.Errorf("receive error code sent by webhook server, code %d, msg: %s", response.Code, response.Message)
  51. }
  52. return nil
  53. }