ntfy/server/util.go

70 lines
1.8 KiB
Go

package server
import (
"fmt"
"heckel.io/ntfy/util"
"io"
"net/http"
"net/url"
"path"
"strconv"
"time"
)
const (
peakAttachmentTimeout = 2500 * time.Millisecond
peakAttachmentReadBytes = 128
)
func maybePeakAttachmentURL(m *message) error {
return maybePeakAttachmentURLInternal(m, peakAttachmentTimeout)
}
func maybePeakAttachmentURLInternal(m *message, timeout time.Duration) error {
if m.Attachment == nil || m.Attachment.URL == "" {
return nil
}
client := http.Client{
Timeout: timeout,
Transport: &http.Transport{
DisableCompression: true, // Disable "Accept-Encoding: gzip", otherwise we won't get the Content-Length
Proxy: http.ProxyFromEnvironment,
},
}
req, err := http.NewRequest(http.MethodGet, m.Attachment.URL, nil)
if err != nil {
return err
}
req.Header.Set("User-Agent", "ntfy")
resp, err := client.Do(req)
if err != nil {
return errHTTPBadRequestAttachmentURLPeakGeneral
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode > 299 {
return errHTTPBadRequestAttachmentURLPeakNon2xx
}
if size, err := strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 64); err == nil {
m.Attachment.Size = size
}
buf := make([]byte, peakAttachmentReadBytes)
io.ReadFull(resp.Body, buf) // Best effort: We don't care about the error
mimeType, ext := util.DetectContentType(buf, m.Attachment.URL)
m.Attachment.Type = resp.Header.Get("Content-Type")
if m.Attachment.Type == "" {
m.Attachment.Type = mimeType
}
if m.Attachment.Name == "" {
u, err := url.Parse(m.Attachment.URL)
if err != nil {
m.Attachment.Name = fmt.Sprintf("attachment%s", ext)
} else {
m.Attachment.Name = path.Base(u.Path)
if m.Attachment.Name == "." || m.Attachment.Name == "/" {
m.Attachment.Name = fmt.Sprintf("attachment%s", ext)
}
}
}
return nil
}