diff options
Diffstat (limited to 'vendor/github.com/superseriousbusiness/activity/pub/handlers.go')
-rw-r--r-- | vendor/github.com/superseriousbusiness/activity/pub/handlers.go | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/vendor/github.com/superseriousbusiness/activity/pub/handlers.go b/vendor/github.com/superseriousbusiness/activity/pub/handlers.go new file mode 100644 index 000000000..bc7eeb9d8 --- /dev/null +++ b/vendor/github.com/superseriousbusiness/activity/pub/handlers.go @@ -0,0 +1,113 @@ +package pub + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "net/http" + + "github.com/superseriousbusiness/activity/streams" +) + +var ErrNotFound = errors.New("go-fed/activity: ActivityStreams data not found") + +// HandlerFunc determines whether an incoming HTTP request is an ActivityStreams +// GET request, and if so attempts to serve ActivityStreams data. +// +// If an error is returned, then the calling function is responsible for writing +// to the ResponseWriter as part of error handling. +// +// If 'isASRequest' is false and there is no error, then the calling function +// may continue processing the request, and the HandlerFunc will not have +// written anything to the ResponseWriter. For example, a webpage may be served +// instead. +// +// If 'isASRequest' is true and there is no error, then the HandlerFunc +// successfully served the request and wrote to the ResponseWriter. +// +// Callers are responsible for authorized access to this resource. +type HandlerFunc func(c context.Context, w http.ResponseWriter, r *http.Request) (isASRequest bool, err error) + +// NewActivityStreamsHandler creates a HandlerFunc to serve ActivityStreams +// requests which are coming from other clients or servers that wish to obtain +// an ActivityStreams representation of data. +// +// Strips retrieved ActivityStreams values of sensitive fields ('bto' and 'bcc') +// before responding with them. Sets the appropriate HTTP status code for +// Tombstone Activities as well. +// +// Defaults to supporting content to be retrieved by HTTPS only. +func NewActivityStreamsHandler(db Database, clock Clock) HandlerFunc { + return NewActivityStreamsHandlerScheme(db, clock, "https") +} + +// NewActivityStreamsHandlerScheme creates a HandlerFunc to serve +// ActivityStreams requests which are coming from other clients or servers that +// wish to obtain an ActivityStreams representation of data provided by the +// specified protocol scheme. +// +// Strips retrieved ActivityStreams values of sensitive fields ('bto' and 'bcc') +// before responding with them. Sets the appropriate HTTP status code for +// Tombstone Activities as well. +// +// Specifying the "scheme" allows for retrieving ActivityStreams content with +// identifiers such as HTTP, HTTPS, or other protocol schemes. +// +// Returns ErrNotFound when the database does not retrieve any data and no +// errors occurred during retrieval. +func NewActivityStreamsHandlerScheme(db Database, clock Clock, scheme string) HandlerFunc { + return func(c context.Context, w http.ResponseWriter, r *http.Request) (isASRequest bool, err error) { + // Do nothing if it is not an ActivityPub GET request + if !isActivityPubGet(r) { + return + } + isASRequest = true + id := requestId(r, scheme) + // Lock and obtain a copy of the requested ActivityStreams value + err = db.Lock(c, id) + if err != nil { + return + } + // WARNING: Unlock not deferred + t, err := db.Get(c, id) + if err != nil { + db.Unlock(c, id) + return + } + db.Unlock(c, id) + // Unlock must have been called by this point and in every + // branch above + if t == nil { + err = ErrNotFound + return + } + // Remove sensitive fields. + clearSensitiveFields(t) + // Serialize the fetched value. + m, err := streams.Serialize(t) + if err != nil { + return + } + raw, err := json.Marshal(m) + if err != nil { + return + } + // Construct the response. + addResponseHeaders(w.Header(), clock, raw) + // Write the response. + if streams.IsOrExtendsActivityStreamsTombstone(t) { + w.WriteHeader(http.StatusGone) + } else { + w.WriteHeader(http.StatusOK) + } + n, err := w.Write(raw) + if err != nil { + return + } else if n != len(raw) { + err = fmt.Errorf("only wrote %d of %d bytes", n, len(raw)) + return + } + return + } +} |