util.go 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. package server
  2. import (
  3. "fmt"
  4. "heckel.io/ntfy/util"
  5. "io"
  6. "net/http"
  7. "net/url"
  8. "path"
  9. "strconv"
  10. "time"
  11. )
  12. const (
  13. peakAttachmentTimeout = 2500 * time.Millisecond
  14. peakAttachmeantReadBytes = 128
  15. )
  16. func maybePeakAttachmentURL(m *message) error {
  17. return maybePeakAttachmentURLInternal(m, peakAttachmentTimeout)
  18. }
  19. func maybePeakAttachmentURLInternal(m *message, timeout time.Duration) error {
  20. if m.Attachment == nil || m.Attachment.URL == "" {
  21. return nil
  22. }
  23. client := http.Client{
  24. Timeout: timeout,
  25. Transport: &http.Transport{
  26. DisableCompression: true, // Disable "Accept-Encoding: gzip", otherwise we won't get the Content-Length
  27. Proxy: http.ProxyFromEnvironment,
  28. },
  29. }
  30. req, err := http.NewRequest(http.MethodGet, m.Attachment.URL, nil)
  31. if err != nil {
  32. return err
  33. }
  34. req.Header.Set("User-Agent", "ntfy")
  35. resp, err := client.Do(req)
  36. if err != nil {
  37. return errHTTPBadRequestAttachmentURLPeakGeneral
  38. }
  39. defer resp.Body.Close()
  40. if resp.StatusCode < 200 || resp.StatusCode > 299 {
  41. return errHTTPBadRequestAttachmentURLPeakNon2xx
  42. }
  43. if size, err := strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 64); err == nil {
  44. m.Attachment.Size = size
  45. }
  46. m.Attachment.Type = resp.Header.Get("Content-Type")
  47. if m.Attachment.Type == "" || m.Attachment.Type == "application/octet-stream" {
  48. buf := make([]byte, peakAttachmeantReadBytes)
  49. io.ReadFull(resp.Body, buf) // Best effort: We don't care about the error
  50. m.Attachment.Type = http.DetectContentType(buf)
  51. }
  52. if m.Attachment.Name == "" {
  53. u, err := url.Parse(m.Attachment.URL)
  54. if err != nil {
  55. m.Attachment.Name = fmt.Sprintf("attachment%s", util.ExtensionByType(m.Attachment.Type))
  56. } else {
  57. m.Attachment.Name = path.Base(u.Path)
  58. if m.Attachment.Name == "." || m.Attachment.Name == "/" {
  59. m.Attachment.Name = fmt.Sprintf("attachment%s", util.ExtensionByType(m.Attachment.Type))
  60. }
  61. }
  62. }
  63. return nil
  64. }