1package client
2
3import (
4 "bytes"
5 "context"
6 "encoding/json"
7 "fmt"
8 "io"
9
10 "github.com/bluesky-social/indigo/atproto/syntax"
11)
12
13// Implements the [github.com/bluesky-social/indigo/lex/util.LexClient] interface, for use with code-generated API helpers.
14func (c *APIClient) LexDo(ctx context.Context, method string, inputEncoding string, endpoint string, params map[string]any, bodyData any, out any) error {
15 // some of the code here is copied from indigo:xrpc/xrpc.go
16
17 nsid, err := syntax.ParseNSID(endpoint)
18 if err != nil {
19 return err
20 }
21
22 var body io.Reader
23 if bodyData != nil {
24 if rr, ok := bodyData.(io.Reader); ok {
25 body = rr
26 } else {
27 b, err := json.Marshal(bodyData)
28 if err != nil {
29 return err
30 }
31
32 body = bytes.NewReader(b)
33 if inputEncoding == "" {
34 inputEncoding = "application/json"
35 }
36 }
37 }
38
39 req := NewAPIRequest(method, nsid, body)
40
41 if inputEncoding != "" {
42 req.Headers.Set("Content-Type", inputEncoding)
43 }
44
45 if params != nil {
46 qp, err := ParseParams(params)
47 if err != nil {
48 return err
49 }
50 req.QueryParams = qp
51 }
52
53 resp, err := c.Do(ctx, req)
54 if err != nil {
55 return err
56 }
57 defer resp.Body.Close()
58
59 if !(resp.StatusCode >= 200 && resp.StatusCode < 300) {
60 var eb ErrorBody
61 if err := json.NewDecoder(resp.Body).Decode(&eb); err != nil {
62 return &APIError{StatusCode: resp.StatusCode}
63 }
64 return eb.APIError(resp.StatusCode)
65 }
66
67 if out == nil {
68 // drain body before returning
69 io.ReadAll(resp.Body)
70 return nil
71 }
72
73 if buf, ok := out.(*bytes.Buffer); ok {
74 if resp.ContentLength < 0 {
75 _, err := io.Copy(buf, resp.Body)
76 if err != nil {
77 return fmt.Errorf("reading response body: %w", err)
78 }
79 } else {
80 n, err := io.CopyN(buf, resp.Body, resp.ContentLength)
81 if err != nil {
82 return fmt.Errorf("reading length delimited response body (%d < %d): %w", n, resp.ContentLength, err)
83 }
84 }
85 } else {
86 if err := json.NewDecoder(resp.Body).Decode(out); err != nil {
87 return fmt.Errorf("failed decoding JSON response body: %w", err)
88 }
89 }
90
91 return nil
92}