14 1d5ddf5d 2024-02-20 o var defaultClient Client = Client{Client: http.DefaultClient}
16 1d5ddf5d 2024-02-20 o func Lookup(id string) (*Activity, error) {
17 1d5ddf5d 2024-02-20 o return defaultClient.Lookup(id)
20 1d5ddf5d 2024-02-20 o func LookupActor(id string) (*Actor, error) {
21 1d5ddf5d 2024-02-20 o return defaultClient.LookupActor(id)
24 1d5ddf5d 2024-02-20 o type Client struct {
26 25fed994 2024-03-12 o // Key is a RSA private key which will be used to sign requests.
27 25fed994 2024-03-12 o Key *rsa.PrivateKey
28 25fed994 2024-03-12 o // PubKeyID is a URL where the corresponding public key of Key
29 25fed994 2024-03-12 o // may be accessed. This must be set if Key is also set.
30 25fed994 2024-03-12 o PubKeyID string // actor.PublicKey.ID
33 1d5ddf5d 2024-02-20 o func (c *Client) Lookup(id string) (*Activity, error) {
34 1d5ddf5d 2024-02-20 o if !strings.HasPrefix(id, "http") {
35 1d5ddf5d 2024-02-20 o return nil, fmt.Errorf("id is not a HTTP URL")
37 1d5ddf5d 2024-02-20 o if c.Client == nil {
38 1d5ddf5d 2024-02-20 o c.Client = http.DefaultClient
41 1d5ddf5d 2024-02-20 o req, err := http.NewRequest(http.MethodGet, id, nil)
42 1d5ddf5d 2024-02-20 o if err != nil {
43 1d5ddf5d 2024-02-20 o return nil, err
45 1d5ddf5d 2024-02-20 o req.Header.Set("Accept", ContentType)
46 25fed994 2024-03-12 o if c.Key != nil && c.PubKeyID != "" {
47 25fed994 2024-03-12 o if err := Sign(req, c.Key, c.PubKeyID); err != nil {
48 1d5ddf5d 2024-02-20 o return nil, fmt.Errorf("sign http request: %w", err)
51 1d5ddf5d 2024-02-20 o resp, err := c.Do(req)
52 1d5ddf5d 2024-02-20 o if err != nil {
53 1d5ddf5d 2024-02-20 o return nil, err
55 1d5ddf5d 2024-02-20 o defer resp.Body.Close()
56 1d5ddf5d 2024-02-20 o if resp.StatusCode == http.StatusNotFound {
57 71191436 2024-02-28 o return nil, ErrNotExist
58 1d5ddf5d 2024-02-20 o } else if resp.StatusCode >= 400 {
59 1d5ddf5d 2024-02-20 o return nil, fmt.Errorf("non-ok response status %s", resp.Status)
61 1d5ddf5d 2024-02-20 o return Decode(resp.Body)
64 1d5ddf5d 2024-02-20 o func (c *Client) LookupActor(id string) (*Actor, error) {
65 1d5ddf5d 2024-02-20 o activity, err := c.Lookup(id)
66 1d5ddf5d 2024-02-20 o if err != nil {
67 1d5ddf5d 2024-02-20 o return nil, err
69 71191436 2024-02-28 o return activityToActor(activity), nil
72 71191436 2024-02-28 o func activityToActor(activity *Activity) *Actor {
73 77918b00 2024-03-07 o actor := &Actor{
74 1d5ddf5d 2024-02-20 o AtContext: activity.AtContext,
75 1d5ddf5d 2024-02-20 o ID: activity.ID,
76 1d5ddf5d 2024-02-20 o Type: activity.Type,
77 1d5ddf5d 2024-02-20 o Name: activity.Name,
78 1d5ddf5d 2024-02-20 o Username: activity.Username,
79 1d5ddf5d 2024-02-20 o Inbox: activity.Inbox,
80 1d5ddf5d 2024-02-20 o Outbox: activity.Outbox,
81 77918b00 2024-03-07 o Followers: activity.Followers,
82 71191436 2024-02-28 o Published: activity.Published,
83 71191436 2024-02-28 o Summary: activity.Summary,
85 77918b00 2024-03-07 o if activity.PublicKey != nil {
86 77918b00 2024-03-07 o actor.PublicKey = *activity.PublicKey
91 1d5ddf5d 2024-02-20 o func (c *Client) Send(inbox string, activity *Activity) (*Activity, error) {
92 1d5ddf5d 2024-02-20 o b, err := json.Marshal(activity)
93 1d5ddf5d 2024-02-20 o if err != nil {
94 1d5ddf5d 2024-02-20 o return nil, fmt.Errorf("encode outgoing activity: %w", err)
96 1d5ddf5d 2024-02-20 o req, err := http.NewRequest(http.MethodPost, inbox, bytes.NewReader(b))
97 1d5ddf5d 2024-02-20 o if err != nil {
98 1d5ddf5d 2024-02-20 o return nil, err
100 1d5ddf5d 2024-02-20 o req.Header.Set("Content-Type", ContentType)
101 25fed994 2024-03-12 o if err := Sign(req, c.Key, c.PubKeyID); err != nil {
102 1d5ddf5d 2024-02-20 o return nil, fmt.Errorf("sign outgoing request: %w", err)
104 1d5ddf5d 2024-02-20 o resp, err := c.Do(req)
105 1d5ddf5d 2024-02-20 o if err != nil {
106 1d5ddf5d 2024-02-20 o return nil, err
108 1d5ddf5d 2024-02-20 o switch resp.StatusCode {
109 77918b00 2024-03-07 o case http.StatusOK, http.StatusAccepted, http.StatusNoContent:
110 1d5ddf5d 2024-02-20 o return nil, nil
111 1d5ddf5d 2024-02-20 o case http.StatusNotFound:
112 1d5ddf5d 2024-02-20 o return nil, fmt.Errorf("no such inbox %s", inbox)
114 1d5ddf5d 2024-02-20 o io.Copy(os.Stderr, resp.Body)
115 1d5ddf5d 2024-02-20 o resp.Body.Close()
116 1d5ddf5d 2024-02-20 o return nil, fmt.Errorf("non-ok response status %s", resp.Status)