gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

README.md (9440B)


      1 # pub
      2 
      3 Implements the Social and Federating Protocols in the ActivityPub specification.
      4 
      5 ## Reference & Tutorial
      6 
      7 The [go-fed website](https://go-fed.org/) contains tutorials and reference
      8 materials, in addition to the rest of this README.
      9 
     10 ## How To Use
     11 
     12 ```
     13 go get github.com/go-fed/activity
     14 ```
     15 
     16 The root of all ActivityPub behavior is the `Actor`, which requires you to
     17 implement a few interfaces:
     18 
     19 ```golang
     20 import (
     21   "github.com/superseriousbusiness/activity/pub"
     22 )
     23 
     24 type myActivityPubApp struct { /* ... */ }
     25 type myAppsDatabase struct { /* ... */ }
     26 type myAppsClock struct { /* ... */ }
     27 
     28 var (
     29   // Your app will implement pub.CommonBehavior, and either
     30   // pub.SocialProtocol, pub.FederatingProtocol, or both.
     31   myApp = &myActivityPubApp{}
     32   myCommonBehavior pub.CommonBehavior = myApp
     33   mySocialProtocol pub.SocialProtocol = myApp
     34   myFederatingProtocol pub.FederatingProtocol = myApp
     35   // Your app's database implementation.
     36   myDatabase pub.Database = &myAppsDatabase{}
     37   // Your app's clock.
     38   myClock pub.Clock = &myAppsClock{}
     39 )
     40 
     41 // Only support the C2S Social protocol
     42 actor := pub.NewSocialActor(
     43   myCommonBehavior,
     44   mySocialProtocol,
     45   myDatabase,
     46   myClock)
     47 // OR
     48 //
     49 // Only support S2S Federating protocol
     50 actor = pub.NewFederatingActor(
     51   myCommonBehavior,
     52   myFederatingProtocol,
     53   myDatabase,
     54   myClock)
     55 // OR
     56 //
     57 // Support both C2S Social and S2S Federating protocol.
     58 actor = pub.NewActor(
     59   myCommonBehavior,
     60   mySocialProtocol,
     61   myFederatingProtocol,
     62   myDatabase,
     63   myClock)
     64 ```
     65 
     66 Next, hook the `Actor` into your web server:
     67 
     68 ```golang
     69 // The application's actor
     70 var actor pub.Actor
     71 var outboxHandler http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) {
     72   c := context.Background()
     73   // Populate c with request-specific information
     74   if handled, err := actor.PostOutbox(c, w, r); err != nil {
     75     // Write to w
     76     return
     77   } else if handled {
     78     return
     79   } else if handled, err = actor.GetOutbox(c, w, r); err != nil {
     80     // Write to w
     81     return
     82   } else if handled {
     83     return
     84   }
     85   // else:
     86   //
     87   // Handle non-ActivityPub request, such as serving a webpage.
     88 }
     89 var inboxHandler http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) {
     90   c := context.Background()
     91   // Populate c with request-specific information
     92   if handled, err := actor.PostInbox(c, w, r); err != nil {
     93     // Write to w
     94     return
     95   } else if handled {
     96     return
     97   } else if handled, err = actor.GetInbox(c, w, r); err != nil {
     98     // Write to w
     99     return
    100   } else if handled {
    101     return
    102   }
    103   // else:
    104   //
    105   // Handle non-ActivityPub request, such as serving a webpage.
    106 }
    107 // Add the handlers to a HTTP server
    108 serveMux := http.NewServeMux()
    109 serveMux.HandleFunc("/actor/outbox", outboxHandler)
    110 serveMux.HandleFunc("/actor/inbox", inboxHandler)
    111 var server http.Server
    112 server.Handler = serveMux
    113 ```
    114 
    115 To serve ActivityStreams data:
    116 
    117 ```golang
    118 myHander := pub.NewActivityStreamsHandler(myDatabase, myClock)
    119 var activityStreamsHandler http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) {
    120   c := context.Background()
    121   // Populate c with request-specific information
    122   if handled, err := myHandler(c, w, r); err != nil {
    123     // Write to w
    124     return
    125   } else if handled {
    126     return
    127   }
    128   // else:
    129   //
    130   // Handle non-ActivityPub request, such as serving a webpage.
    131 }
    132 serveMux.HandleFunc("/some/data/like/a/note", activityStreamsHandler)
    133 ```
    134 
    135 ### Dependency Injection
    136 
    137 Package `pub` relies on dependency injection to provide out-of-the-box support
    138 for ActivityPub. The interfaces to be satisfied are:
    139 
    140 * `CommonBehavior` - Behavior needed regardless of which Protocol is used.
    141 * `SocialProtocol` - Behavior needed for the Social Protocol.
    142 * `FederatingProtocol` - Behavior needed for the Federating Protocol.
    143 * `Database` - The data store abstraction, not tied to the `database/sql`
    144 package.
    145 * `Clock` - The server's internal clock.
    146 * `Transport` - Responsible for the network that serves requests and deliveries
    147 of ActivityStreams data. A `HttpSigTransport` type is provided.
    148 
    149 These implementations form the core of an application's behavior without
    150 worrying about the particulars and pitfalls of the ActivityPub protocol.
    151 Implementing these interfaces gives you greater assurance about being
    152 ActivityPub compliant.
    153 
    154 ### Application Logic
    155 
    156 The `SocialProtocol` and `FederatingProtocol` are responsible for returning
    157 callback functions compatible with `streams.TypeResolver`. They also return
    158 `SocialWrappedCallbacks` and `FederatingWrappedCallbacks`, which are nothing
    159 more than a bundle of default behaviors for types like `Create`, `Update`, and
    160 so on.
    161 
    162 Applications will want to focus on implementing their specific behaviors in the
    163 callbacks, and have fine-grained control over customization:
    164 
    165 ```golang
    166 // Implements the FederatingProtocol interface.
    167 //
    168 // This illustration can also be applied for the Social Protocol.
    169 func (m *myAppsFederatingProtocol) Callbacks(c context.Context) (wrapped pub.FederatingWrappedCallbacks, other []interface{}) {
    170   // The context 'c' has request-specific logic and can be used to apply complex
    171   // logic building the right behaviors, if desired.
    172   //
    173   // 'c' will later be passed through to the callbacks created below.
    174   wrapped = pub.FederatingWrappedCallbacks{
    175     Create: func(ctx context.Context, create vocab.ActivityStreamsCreate) error {
    176       // This function is wrapped by default behavior.
    177       //
    178       // More application specific logic can be written here.
    179       //
    180       // 'ctx' will have request-specific information from the HTTP handler. It
    181       // is the same as the 'c' passed to the Callbacks method.
    182       // 'create' has, at this point, already triggered the recommended
    183       // ActivityPub side effect behavior. The application can process it
    184       // further as needed.
    185       return nil
    186     },
    187   }
    188   // The 'other' must contain functions that satisfy the signature pattern
    189   // required by streams.JSONResolver.
    190   //
    191   // If they are not, at runtime errors will be returned to indicate this.
    192   other = []interface{}{
    193     // The FederatingWrappedCallbacks has default behavior for an "Update" type,
    194     // but since we are providing this behavior in "other" and not in the
    195     // FederatingWrappedCallbacks.Update member, we will entirely replace the
    196     // default behavior provided by go-fed. Be careful that this still
    197     // implements ActivityPub properly.
    198     func(ctx context.Context, update vocab.ActivityStreamsUpdate) error {
    199       // This function is NOT wrapped by default behavior.
    200       //
    201       // Application specific logic can be written here.
    202       //
    203       // 'ctx' will have request-specific information from the HTTP handler. It
    204       // is the same as the 'c' passed to the Callbacks method.
    205       // 'update' will NOT trigger the recommended ActivityPub side effect
    206       // behavior. The application should do so in addition to any other custom
    207       // side effects required.
    208       return nil
    209     },
    210     // The "Listen" type has no default suggested behavior in ActivityPub, so
    211     // this just makes this application able to handle "Listen" activities.
    212     func(ctx context.Context, listen vocab.ActivityStreamsListen) error {
    213       // This function is NOT wrapped by default behavior. There's not a
    214       // FederatingWrappedCallbacks.Listen member to wrap.
    215       //
    216       // Application specific logic can be written here.
    217       //
    218       // 'ctx' will have request-specific information from the HTTP handler. It
    219       // is the same as the 'c' passed to the Callbacks method.
    220       // 'listen' can be processed with side effects as the application needs.
    221       return nil
    222     },
    223   }
    224   return
    225 }
    226 ```
    227 
    228 The `pub` package supports applications that grow into more custom solutions by
    229 overriding the default behaviors as needed.
    230 
    231 ### ActivityStreams Extensions: Future-Proofing An Application
    232 
    233 Package `pub` relies on the `streams.TypeResolver` and `streams.JSONResolver`
    234 code generated types. As new ActivityStreams extensions are developed and their
    235 code is generated, `pub` will automatically pick up support for these
    236 extensions.
    237 
    238 The steps to rapidly implement a new extension in a `pub` application are:
    239 
    240 1. Generate an OWL definition of the ActivityStreams extension. This definition
    241 could be the same one defining the vocabulary at the `@context` IRI.
    242 2. Run `astool` to autogenerate the golang types in the `streams` package.
    243 3. Implement the application's callbacks in the `FederatingProtocol.Callbacks`
    244 or `SocialProtocol.Callbacks` for the new behaviors needed.
    245 4. Build the application, which builds `pub`, with the newly generated `streams`
    246 code. No code changes in `pub` are required.
    247 
    248 Whether an author of an ActivityStreams extension or an application developer,
    249 these quick steps should reduce the barrier to adopion in a statically-typed
    250 environment.
    251 
    252 ### DelegateActor
    253 
    254 For those that need a near-complete custom ActivityPub solution, or want to have
    255 that possibility in the future after adopting go-fed, the `DelegateActor`
    256 interface can be used to obtain an `Actor`:
    257 
    258 ```golang
    259 // Use custom ActivityPub implementation
    260 actor = pub.NewCustomActor(
    261   myDelegateActor,
    262   isSocialProtocolEnabled,
    263   isFederatedProtocolEnabled,
    264   myAppsClock)
    265 ```
    266 
    267 It does not guarantee that an implementation adheres to the ActivityPub
    268 specification. It acts as a stepping stone for applications that want to build
    269 up to a fully custom solution and not be locked into the `pub` package
    270 implementation.