Skip to content

Commit

Permalink
Close http connections.
Browse files Browse the repository at this point in the history
  • Loading branch information
q-uint committed Feb 5, 2025
1 parent 79eeff6 commit 604678d
Show file tree
Hide file tree
Showing 8 changed files with 221 additions and 80 deletions.
23 changes: 3 additions & 20 deletions agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"encoding/hex"
"errors"
"fmt"
"net/url"
"reflect"
"time"

Expand All @@ -23,12 +22,6 @@ import (
// DefaultConfig is the default configuration for an Agent.
var DefaultConfig = Config{}

// ic0 is the old (default) host for the Internet Computer.
// var ic0, _ = url.Parse("https://ic0.app/")

// icp0 is the default host for the Internet Computer.
var icp0, _ = url.Parse("https://icp0.io/")

func effectiveCanisterID(canisterID principal.Principal, args []any) principal.Principal {
// If the canisterID is not aaaaa-aa (encoded as empty byte array), return it.
if 0 < len(canisterID.Raw) || len(args) < 1 {
Expand Down Expand Up @@ -171,17 +164,7 @@ func New(cfg Config) (*Agent, error) {
if cfg.Identity != nil {
id = cfg.Identity
}
var logger Logger = new(NoopLogger)
if cfg.Logger != nil {
logger = cfg.Logger
}
ccfg := ClientConfig{
Host: icp0,
}
if cfg.ClientConfig != nil {
ccfg = *cfg.ClientConfig
}
client := NewClientWithLogger(ccfg, logger)
client := NewClient(cfg.ClientConfig...)
rootKey, _ := hex.DecodeString(certification.RootKey)
if cfg.FetchRootKey {
status, err := client.Status()
Expand All @@ -204,7 +187,7 @@ func New(cfg Config) (*Agent, error) {
identity: id,
ingressExpiry: cfg.IngressExpiry,
rootKey: rootKey,
logger: logger,
logger: client.logger,
delay: delay,
timeout: timeout,
verifySignatures: !cfg.DisableSignedQueryVerification,
Expand Down Expand Up @@ -501,7 +484,7 @@ type Config struct {
// The default is set to 5 minutes.
IngressExpiry time.Duration
// ClientConfig is the configuration for the underlying Client.
ClientConfig *ClientConfig
ClientConfig []ClientOption
// FetchRootKey determines whether the root key should be fetched from the IC.
FetchRootKey bool
// Logger is the logger used by the Agent.
Expand Down
84 changes: 57 additions & 27 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,30 @@ import (
"github.com/fxamacker/cbor/v2"
)

// ic0 is the old (default) host for the Internet Computer.
// var ic0, _ = url.Parse("https://ic0.app/")

// icp0 is the default host for the Internet Computer.
var icp0, _ = url.Parse("https://icp0.io/")

// Client is a client for the IC agent.
type Client struct {
client http.Client
config ClientConfig
client *http.Client
host *url.URL
logger Logger
}

// NewClient creates a new client based on the given configuration.
func NewClient(cfg ClientConfig) Client {
return Client{
client: http.Client{},
config: cfg,
func NewClient(options ...ClientOption) Client {
c := Client{
client: http.DefaultClient,
host: icp0,
logger: new(NoopLogger),
}
}

// NewClientWithLogger creates a new client based on the given configuration and logger.
func NewClientWithLogger(cfg ClientConfig, logger Logger) Client {
if logger == nil {
logger = new(NoopLogger)
}
return Client{
client: http.Client{},
config: cfg,
logger: logger,
for _, o := range options {
o(&c)
}
return c
}

func (c Client) Call(ctx context.Context, canisterID principal.Principal, data []byte) ([]byte, error) {
Expand All @@ -52,16 +50,20 @@ func (c Client) Call(ctx context.Context, canisterID principal.Principal, data [
if err != nil {
return nil, err
}
defer resp.Body.Close()
switch resp.StatusCode {
case http.StatusAccepted:
return io.ReadAll(resp.Body)
case http.StatusOK:
body, _ := io.ReadAll(resp.Body)
var err preprocessingError
if err := cbor.Unmarshal(body, &err); err != nil {
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return nil, fmt.Errorf("(%d) %s: %s", err.RejectCode, err.Message, err.ErrorCode)
var pErr preprocessingError
if err := cbor.Unmarshal(body, &pErr); err != nil {
return nil, err
}
return nil, pErr
default:
body, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("(%d) %s: %s", resp.StatusCode, resp.Status, body)
Expand Down Expand Up @@ -96,6 +98,7 @@ func (c Client) get(path string) ([]byte, error) {
if err != nil {
return nil, err
}
defer resp.Body.Close()
return io.ReadAll(resp.Body)
}

Expand All @@ -119,11 +122,15 @@ func (c Client) post(ctx context.Context, path string, canisterID principal.Prin
if err != nil {
return nil, err
}
defer resp.Body.Close()
switch resp.StatusCode {
case http.StatusOK:
return io.ReadAll(resp.Body)
default:
body, _ := io.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return nil, fmt.Errorf("(%d) %s: %s", resp.StatusCode, resp.Status, body)
}
}
Expand All @@ -139,24 +146,43 @@ func (c Client) postSubnet(ctx context.Context, path string, subnetID principal.
if err != nil {
return nil, err
}
defer resp.Body.Close()
switch resp.StatusCode {
case http.StatusOK:
return io.ReadAll(resp.Body)
default:
body, _ := io.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return nil, fmt.Errorf("(%d) %s: %s", resp.StatusCode, resp.Status, body)
}
}

func (c Client) url(p string) string {
u := *c.config.Host
u := *c.host
u.Path = path.Join(u.Path, p)
return u.String()
}

// ClientConfig is the configuration for a client.
type ClientConfig struct {
Host *url.URL
type ClientOption func(c *Client)

func WithHostURL(host *url.URL) ClientOption {
return func(c *Client) {
c.host = host
}
}

func WithHttpClient(client *http.Client) ClientOption {
return func(c *Client) {
c.client = client
}
}

func WithLogger(logger Logger) ClientOption {
return func(c *Client) {
c.logger = logger
}
}

type preprocessingError struct {
Expand All @@ -167,3 +193,7 @@ type preprocessingError struct {
// An optional implementation-specific textual error code.
ErrorCode string `cbor:"error_code"`
}

func (e preprocessingError) Error() string {
return fmt.Sprintf("(%d) %s: %s", e.RejectCode, e.Message, e.ErrorCode)
}
56 changes: 28 additions & 28 deletions clients/registry/proto/v1/operator.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions gen/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"io/fs"
"strings"
"text/template"
"unicode"

"github.com/aviate-labs/agent-go/candid/did"
)
Expand Down Expand Up @@ -84,6 +85,9 @@ func NewGenerator(agentName, canisterName, packageName string, rawDID []rune) (*
if err != nil {
return nil, err
}
if rs := []rune(agentName); unicode.IsLower(rs[0]) {
agentName = strings.ToUpper(agentName[:1]) + agentName[1:]
}
return &Generator{
AgentName: agentName,
CanisterName: canisterName,
Expand Down
Loading

0 comments on commit 604678d

Please sign in to comment.