summaryrefslogtreecommitdiff
path: root/vendor/github.com/superseriousbusiness/activity/pub/transport.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/superseriousbusiness/activity/pub/transport.go')
-rw-r--r--vendor/github.com/superseriousbusiness/activity/pub/transport.go219
1 files changed, 0 insertions, 219 deletions
diff --git a/vendor/github.com/superseriousbusiness/activity/pub/transport.go b/vendor/github.com/superseriousbusiness/activity/pub/transport.go
deleted file mode 100644
index 101ff5c07..000000000
--- a/vendor/github.com/superseriousbusiness/activity/pub/transport.go
+++ /dev/null
@@ -1,219 +0,0 @@
-package pub
-
-import (
- "bytes"
- "context"
- "crypto"
- "encoding/json"
- "fmt"
- "net/http"
- "net/url"
- "strings"
- "sync"
-
- "github.com/go-fed/httpsig"
-)
-
-const (
- // acceptHeaderValue is the Accept header value indicating that the
- // response should contain an ActivityStreams object.
- acceptHeaderValue = "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
-)
-
-// isSuccess returns true if the HTTP status code is either OK, Created, or
-// Accepted.
-func isSuccess(code int) bool {
- return code == http.StatusOK ||
- code == http.StatusCreated ||
- code == http.StatusAccepted
-}
-
-// Transport makes ActivityStreams calls to other servers in order to send or
-// receive ActivityStreams data.
-//
-// It is responsible for setting the appropriate request headers, signing the
-// requests if needed, and facilitating the traffic between this server and
-// another.
-//
-// The transport is exclusively used to issue requests on behalf of an actor,
-// and is never sending requests on behalf of the server in general.
-//
-// It may be reused multiple times, but never concurrently.
-type Transport interface {
- // Dereference fetches the ActivityStreams object located at this IRI with
- // a GET request. Note that Response will only be returned on status = OK.
- Dereference(c context.Context, iri *url.URL) (*http.Response, error)
-
- // Deliver sends an ActivityStreams object.
- Deliver(c context.Context, obj map[string]interface{}, to *url.URL) error
-
- // BatchDeliver sends an ActivityStreams object to multiple recipients.
- BatchDeliver(c context.Context, obj map[string]interface{}, recipients []*url.URL) error
-}
-
-// Transport must be implemented by HttpSigTransport.
-var _ Transport = &HttpSigTransport{}
-
-// HttpSigTransport makes a dereference call using HTTP signatures to
-// authenticate the request on behalf of a particular actor.
-//
-// No rate limiting is applied.
-//
-// Only one request is tried per call.
-type HttpSigTransport struct {
- client HttpClient
- appAgent string
- gofedAgent string
- clock Clock
- getSigner httpsig.Signer
- getSignerMu *sync.Mutex
- postSigner httpsig.Signer
- postSignerMu *sync.Mutex
- pubKeyId string
- privKey crypto.PrivateKey
-}
-
-// NewHttpSigTransport returns a new Transport.
-//
-// It sends requests specifically on behalf of a specific actor on this server.
-// The actor's credentials are used to add an HTTP Signature to requests, which
-// requires an actor's private key, a unique identifier for their public key,
-// and an HTTP Signature signing algorithm.
-//
-// The client lets users issue requests through any HTTP client, including the
-// standard library's HTTP client.
-//
-// The appAgent uniquely identifies the calling application's requests, so peers
-// may aid debugging the requests incoming from this server. Note that the
-// agent string will also include one for go-fed, so at minimum peer servers can
-// reach out to the go-fed library to aid in notifying implementors of malformed
-// or unsupported requests.
-func NewHttpSigTransport(
- client HttpClient,
- appAgent string,
- clock Clock,
- getSigner, postSigner httpsig.Signer,
- pubKeyId string,
- privKey crypto.PrivateKey) *HttpSigTransport {
- return &HttpSigTransport{
- client: client,
- appAgent: appAgent,
- gofedAgent: goFedUserAgent(),
- clock: clock,
- getSigner: getSigner,
- getSignerMu: &sync.Mutex{},
- postSigner: postSigner,
- postSignerMu: &sync.Mutex{},
- pubKeyId: pubKeyId,
- privKey: privKey,
- }
-}
-
-// Dereference sends a GET request signed with an HTTP Signature to obtain an ActivityStreams value.
-func (h HttpSigTransport) Dereference(c context.Context, iri *url.URL) (*http.Response, error) {
- req, err := http.NewRequest("GET", iri.String(), nil)
- if err != nil {
- return nil, err
- }
- req = req.WithContext(c)
- req.Header.Add(acceptHeader, acceptHeaderValue)
- req.Header.Add("Accept-Charset", "utf-8")
- req.Header.Add("Date", h.clock.Now().UTC().Format("Mon, 02 Jan 2006 15:04:05")+" GMT")
- req.Header.Add("User-Agent", fmt.Sprintf("%s %s", h.appAgent, h.gofedAgent))
- req.Header.Set("Host", iri.Host)
- h.getSignerMu.Lock()
- err = h.getSigner.SignRequest(h.privKey, h.pubKeyId, req, nil)
- h.getSignerMu.Unlock()
- if err != nil {
- return nil, err
- }
- resp, err := h.client.Do(req)
- if err != nil {
- return nil, err
- }
- if resp.StatusCode != http.StatusOK {
- _ = resp.Body.Close()
- return nil, fmt.Errorf("GET request to %s failed (%d): %s", iri.String(), resp.StatusCode, resp.Status)
- }
- return resp, nil
-}
-
-// Deliver sends a POST request with an HTTP Signature.
-func (h HttpSigTransport) Deliver(c context.Context, data map[string]interface{}, to *url.URL) error {
- b, err := json.Marshal(data)
- if err != nil {
- return err
- }
- return h.deliver(c, b, to)
-}
-
-// BatchDeliver sends concurrent POST requests. Returns an error if any of the requests had an error.
-func (h HttpSigTransport) BatchDeliver(c context.Context, data map[string]interface{}, recipients []*url.URL) error {
- b, err := json.Marshal(data)
- if err != nil {
- return err
- }
- var wg sync.WaitGroup
- errCh := make(chan error, len(recipients))
- for _, recipient := range recipients {
- wg.Add(1)
- go func(r *url.URL) {
- defer wg.Done()
- if err := h.deliver(c, b, r); err != nil {
- errCh <- err
- }
- }(recipient)
- }
- wg.Wait()
- errs := make([]string, 0, len(recipients))
-outer:
- for {
- select {
- case e := <-errCh:
- errs = append(errs, e.Error())
- default:
- break outer
- }
- }
- if len(errs) > 0 {
- return fmt.Errorf("batch deliver had at least one failure: %s", strings.Join(errs, "; "))
- }
- return nil
-}
-
-func (h HttpSigTransport) deliver(c context.Context, b []byte, to *url.URL) error {
- req, err := http.NewRequest("POST", to.String(), bytes.NewReader(b))
- if err != nil {
- return err
- }
- req = req.WithContext(c)
- req.Header.Add(contentTypeHeader, contentTypeHeaderValue)
- req.Header.Add("Accept-Charset", "utf-8")
- req.Header.Add("Date", h.clock.Now().UTC().Format("Mon, 02 Jan 2006 15:04:05")+" GMT")
- req.Header.Add("User-Agent", fmt.Sprintf("%s %s", h.appAgent, h.gofedAgent))
- req.Header.Set("Host", to.Host)
- h.postSignerMu.Lock()
- err = h.postSigner.SignRequest(h.privKey, h.pubKeyId, req, b)
- h.postSignerMu.Unlock()
- if err != nil {
- return err
- }
- resp, err := h.client.Do(req)
- if err != nil {
- return err
- }
- defer resp.Body.Close()
- if !isSuccess(resp.StatusCode) {
- return fmt.Errorf("POST request to %s failed (%d): %s", to.String(), resp.StatusCode, resp.Status)
- }
- return nil
-}
-
-// HttpClient sends http requests, and is an abstraction only needed by the
-// HttpSigTransport. The standard library's Client satisfies this interface.
-type HttpClient interface {
- Do(req *http.Request) (*http.Response, error)
-}
-
-// HttpClient must be implemented by http.Client.
-var _ HttpClient = &http.Client{}