mirror of
https://git.mills.io/saltyim/saltyim.git
synced 2024-06-16 11:58:24 +00:00
754fcc7323
feat: add compression negotiation for sent messages fix: unix homedir handling the service will negotiate a compression algo for sending messages when a user chats someone during the auto discovery, the service returns an `Accept-Encoding: br, gzip, deflate` the client saves that response and so when it makes POSTs of messages adds the best `Content-Encoding` and compresses the message example: ``` >> GET /.well-known/salty/c765c69040d98f3af2181237f47ec01398d80f8ab2690fe929e4311ab05dec01.json << Accept-Encoding: br, gzip, deflate << << {"endpoint":"https://salty.home.arpa/inbox/01FZBR8Y2E6TH949JA3925WF71","key":"kex1wurry09ftqjuxgjl0jxmqypv4axqvzqljkgeadxjcpwtfuhcedcslck52d"} >> POST /inbox/01FZBR8Y2E6TH949JA3925WF71 >> Content-Encoding: br >> >> [Brotli Compressed data] ``` this PR depends on https://git.mills.io/prologic/msgbus/pulls/24 Co-authored-by: Jon Lundy <jon@xuu.cc> Reviewed-on: https://git.mills.io/saltyim/saltyim/pulls/91 Co-authored-by: xuu <xuu@noreply@mills.io> Co-committed-by: xuu <xuu@noreply@mills.io>
104 lines
2.2 KiB
Go
104 lines
2.2 KiB
Go
package saltyim
|
|
|
|
import (
|
|
"bytes"
|
|
"compress/gzip"
|
|
"crypto/rand"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/andybalholm/brotli"
|
|
"github.com/oklog/ulid/v2"
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
const (
|
|
defaultRequestTimeout = time.Second * 30
|
|
)
|
|
|
|
// GenerateULID generates a new unique identifer
|
|
func GenerateULID() (string, error) {
|
|
entropy := rand.Reader
|
|
id, err := ulid.New(ulid.Timestamp(time.Now()), entropy)
|
|
if err != nil {
|
|
return "", fmt.Errorf("error generating ulid: %w", err)
|
|
}
|
|
|
|
return id.String(), nil
|
|
}
|
|
|
|
// MustGenerateULID generates a new unique identifer or fails
|
|
func MustGenerateULID() string {
|
|
ulid, err := GenerateULID()
|
|
if err != nil {
|
|
log.WithError(err).Fatal("error generating ulid")
|
|
}
|
|
return ulid
|
|
}
|
|
|
|
// Request is a generic request handling function for making artbitrary HTPT
|
|
// requests to Salty endpoints for looking up Salty Addresses, Configs and
|
|
// publishing encrypted messages.
|
|
func Request(method, uri string, headers http.Header, body io.Reader) (*http.Response, error) {
|
|
if headers == nil {
|
|
headers = make(http.Header)
|
|
}
|
|
|
|
if body != nil {
|
|
switch headers.Get("Content-Encoding") {
|
|
case "br":
|
|
buf := &bytes.Buffer{}
|
|
br := brotli.NewWriter(buf)
|
|
io.Copy(br, body)
|
|
br.Close()
|
|
body = buf
|
|
case "gzip":
|
|
buf := &bytes.Buffer{}
|
|
gz := gzip.NewWriter(buf)
|
|
io.Copy(gz, body)
|
|
gz.Close()
|
|
body = buf
|
|
}
|
|
}
|
|
|
|
req, err := http.NewRequest(method, uri, body)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("%s: http.NewRequest fail: %s", uri, err)
|
|
}
|
|
|
|
// Set a default User-Agent (if none set)
|
|
if headers.Get("User-Agent") == "" {
|
|
headers.Set("User-Agent", fmt.Sprintf("saltyim/%s", FullVersion()))
|
|
}
|
|
|
|
req.Header = headers
|
|
|
|
client := http.Client{
|
|
Timeout: defaultRequestTimeout,
|
|
}
|
|
|
|
res, err := client.Do(req)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("%s: client.Do fail: %s", uri, err)
|
|
}
|
|
|
|
if res.StatusCode/100 != 2 {
|
|
return nil, fmt.Errorf("non-2xx response received: %s", res.Status)
|
|
}
|
|
|
|
return res, nil
|
|
}
|
|
|
|
// SplitInbox splits and endpoint into it's components (inbox, uri)
|
|
// where inbox is a topic queue on the Salty broker uri
|
|
func SplitInbox(endpoint string) (string, string) {
|
|
idx := strings.LastIndex(endpoint, "/")
|
|
if idx == -1 {
|
|
return "", ""
|
|
}
|
|
return endpoint[:idx], endpoint[idx+1:]
|
|
}
|