package delivery import ( "bytes" "encoding/gob" "net/http" "net/url" "sync" "time" "git.capotej.com/capotej/communique/config" "git.capotej.com/capotej/communique/models" "github.com/go-fed/httpsig" ) type Signed struct { signer httpsig.Signer mu sync.Mutex persister *models.Persister } func NewSigned(persister *models.Persister) (*Signed, error) { signed := &Signed{persister: persister} var err error prefs := []httpsig.Algorithm{} digestAlgorithm := httpsig.DigestSha256 headersToSign := []string{httpsig.RequestTarget, "host", "date", "digest"} signed.signer, _, err = httpsig.NewSigner(prefs, digestAlgorithm, headersToSign, httpsig.Signature, 0) if err != nil { return nil, err } return signed, nil } func (s *Signed) SignedRequest(handler config.Handler, payload []byte, inboxUrl, actorKeyUrl *url.URL) (*http.Request, error) { aso := models.NewKeypair(handler) result, err := s.persister.Find(aso) if err != nil { return nil, err } buf := bytes.NewBuffer(result) dec := gob.NewDecoder(buf) var keypair models.Keypair err = dec.Decode(&keypair) if err != nil { return nil, err } privKey := &keypair.PrivateKey request, err := http.NewRequest("POST", inboxUrl.String(), bytes.NewBuffer(payload)) date := time.Now().UTC().Format(http.TimeFormat) request.Header.Set("Date", date) request.Header.Set("Content-Type", "application/activity+json") request.Header.Set("Host", inboxUrl.Host) s.mu.Lock() err = s.signer.SignRequest(privKey, actorKeyUrl.String(), request, payload) s.mu.Unlock() if err != nil { return nil, err } return request, nil }