diff options
Diffstat (limited to 'vendor/github.com/go-fed/activity/pub/README.md')
-rw-r--r-- | vendor/github.com/go-fed/activity/pub/README.md | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/vendor/github.com/go-fed/activity/pub/README.md b/vendor/github.com/go-fed/activity/pub/README.md new file mode 100644 index 000000000..dafe176ea --- /dev/null +++ b/vendor/github.com/go-fed/activity/pub/README.md @@ -0,0 +1,270 @@ +# pub + +Implements the Social and Federating Protocols in the ActivityPub specification. + +## Reference & Tutorial + +The [go-fed website](https://go-fed.org/) contains tutorials and reference +materials, in addition to the rest of this README. + +## How To Use + +``` +go get github.com/go-fed/activity +``` + +The root of all ActivityPub behavior is the `Actor`, which requires you to +implement a few interfaces: + +```golang +import ( + "github.com/go-fed/activity/pub" +) + +type myActivityPubApp struct { /* ... */ } +type myAppsDatabase struct { /* ... */ } +type myAppsClock struct { /* ... */ } + +var ( + // Your app will implement pub.CommonBehavior, and either + // pub.SocialProtocol, pub.FederatingProtocol, or both. + myApp = &myActivityPubApp{} + myCommonBehavior pub.CommonBehavior = myApp + mySocialProtocol pub.SocialProtocol = myApp + myFederatingProtocol pub.FederatingProtocol = myApp + // Your app's database implementation. + myDatabase pub.Database = &myAppsDatabase{} + // Your app's clock. + myClock pub.Clock = &myAppsClock{} +) + +// Only support the C2S Social protocol +actor := pub.NewSocialActor( + myCommonBehavior, + mySocialProtocol, + myDatabase, + myClock) +// OR +// +// Only support S2S Federating protocol +actor = pub.NewFederatingActor( + myCommonBehavior, + myFederatingProtocol, + myDatabase, + myClock) +// OR +// +// Support both C2S Social and S2S Federating protocol. +actor = pub.NewActor( + myCommonBehavior, + mySocialProtocol, + myFederatingProtocol, + myDatabase, + myClock) +``` + +Next, hook the `Actor` into your web server: + +```golang +// The application's actor +var actor pub.Actor +var outboxHandler http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) { + c := context.Background() + // Populate c with request-specific information + if handled, err := actor.PostOutbox(c, w, r); err != nil { + // Write to w + return + } else if handled { + return + } else if handled, err = actor.GetOutbox(c, w, r); err != nil { + // Write to w + return + } else if handled { + return + } + // else: + // + // Handle non-ActivityPub request, such as serving a webpage. +} +var inboxHandler http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) { + c := context.Background() + // Populate c with request-specific information + if handled, err := actor.PostInbox(c, w, r); err != nil { + // Write to w + return + } else if handled { + return + } else if handled, err = actor.GetInbox(c, w, r); err != nil { + // Write to w + return + } else if handled { + return + } + // else: + // + // Handle non-ActivityPub request, such as serving a webpage. +} +// Add the handlers to a HTTP server +serveMux := http.NewServeMux() +serveMux.HandleFunc("/actor/outbox", outboxHandler) +serveMux.HandleFunc("/actor/inbox", inboxHandler) +var server http.Server +server.Handler = serveMux +``` + +To serve ActivityStreams data: + +```golang +myHander := pub.NewActivityStreamsHandler(myDatabase, myClock) +var activityStreamsHandler http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) { + c := context.Background() + // Populate c with request-specific information + if handled, err := myHandler(c, w, r); err != nil { + // Write to w + return + } else if handled { + return + } + // else: + // + // Handle non-ActivityPub request, such as serving a webpage. +} +serveMux.HandleFunc("/some/data/like/a/note", activityStreamsHandler) +``` + +### Dependency Injection + +Package `pub` relies on dependency injection to provide out-of-the-box support +for ActivityPub. The interfaces to be satisfied are: + +* `CommonBehavior` - Behavior needed regardless of which Protocol is used. +* `SocialProtocol` - Behavior needed for the Social Protocol. +* `FederatingProtocol` - Behavior needed for the Federating Protocol. +* `Database` - The data store abstraction, not tied to the `database/sql` +package. +* `Clock` - The server's internal clock. +* `Transport` - Responsible for the network that serves requests and deliveries +of ActivityStreams data. A `HttpSigTransport` type is provided. + +These implementations form the core of an application's behavior without +worrying about the particulars and pitfalls of the ActivityPub protocol. +Implementing these interfaces gives you greater assurance about being +ActivityPub compliant. + +### Application Logic + +The `SocialProtocol` and `FederatingProtocol` are responsible for returning +callback functions compatible with `streams.TypeResolver`. They also return +`SocialWrappedCallbacks` and `FederatingWrappedCallbacks`, which are nothing +more than a bundle of default behaviors for types like `Create`, `Update`, and +so on. + +Applications will want to focus on implementing their specific behaviors in the +callbacks, and have fine-grained control over customization: + +```golang +// Implements the FederatingProtocol interface. +// +// This illustration can also be applied for the Social Protocol. +func (m *myAppsFederatingProtocol) Callbacks(c context.Context) (wrapped pub.FederatingWrappedCallbacks, other []interface{}) { + // The context 'c' has request-specific logic and can be used to apply complex + // logic building the right behaviors, if desired. + // + // 'c' will later be passed through to the callbacks created below. + wrapped = pub.FederatingWrappedCallbacks{ + Create: func(ctx context.Context, create vocab.ActivityStreamsCreate) error { + // This function is wrapped by default behavior. + // + // More application specific logic can be written here. + // + // 'ctx' will have request-specific information from the HTTP handler. It + // is the same as the 'c' passed to the Callbacks method. + // 'create' has, at this point, already triggered the recommended + // ActivityPub side effect behavior. The application can process it + // further as needed. + return nil + }, + } + // The 'other' must contain functions that satisfy the signature pattern + // required by streams.JSONResolver. + // + // If they are not, at runtime errors will be returned to indicate this. + other = []interface{}{ + // The FederatingWrappedCallbacks has default behavior for an "Update" type, + // but since we are providing this behavior in "other" and not in the + // FederatingWrappedCallbacks.Update member, we will entirely replace the + // default behavior provided by go-fed. Be careful that this still + // implements ActivityPub properly. + func(ctx context.Context, update vocab.ActivityStreamsUpdate) error { + // This function is NOT wrapped by default behavior. + // + // Application specific logic can be written here. + // + // 'ctx' will have request-specific information from the HTTP handler. It + // is the same as the 'c' passed to the Callbacks method. + // 'update' will NOT trigger the recommended ActivityPub side effect + // behavior. The application should do so in addition to any other custom + // side effects required. + return nil + }, + // The "Listen" type has no default suggested behavior in ActivityPub, so + // this just makes this application able to handle "Listen" activities. + func(ctx context.Context, listen vocab.ActivityStreamsListen) error { + // This function is NOT wrapped by default behavior. There's not a + // FederatingWrappedCallbacks.Listen member to wrap. + // + // Application specific logic can be written here. + // + // 'ctx' will have request-specific information from the HTTP handler. It + // is the same as the 'c' passed to the Callbacks method. + // 'listen' can be processed with side effects as the application needs. + return nil + }, + } + return +} +``` + +The `pub` package supports applications that grow into more custom solutions by +overriding the default behaviors as needed. + +### ActivityStreams Extensions: Future-Proofing An Application + +Package `pub` relies on the `streams.TypeResolver` and `streams.JSONResolver` +code generated types. As new ActivityStreams extensions are developed and their +code is generated, `pub` will automatically pick up support for these +extensions. + +The steps to rapidly implement a new extension in a `pub` application are: + +1. Generate an OWL definition of the ActivityStreams extension. This definition +could be the same one defining the vocabulary at the `@context` IRI. +2. Run `astool` to autogenerate the golang types in the `streams` package. +3. Implement the application's callbacks in the `FederatingProtocol.Callbacks` +or `SocialProtocol.Callbacks` for the new behaviors needed. +4. Build the application, which builds `pub`, with the newly generated `streams` +code. No code changes in `pub` are required. + +Whether an author of an ActivityStreams extension or an application developer, +these quick steps should reduce the barrier to adopion in a statically-typed +environment. + +### DelegateActor + +For those that need a near-complete custom ActivityPub solution, or want to have +that possibility in the future after adopting go-fed, the `DelegateActor` +interface can be used to obtain an `Actor`: + +```golang +// Use custom ActivityPub implementation +actor = pub.NewCustomActor( + myDelegateActor, + isSocialProtocolEnabled, + isFederatedProtocolEnabled, + myAppsClock) +``` + +It does not guarantee that an implementation adheres to the ActivityPub +specification. It acts as a stepping stone for applications that want to build +up to a fully custom solution and not be locked into the `pub` package +implementation. |