i want to write an agent with golang but when i post a request, it returned 403 forbidden. here is my code,
type Request struct {
Type RequestType `cbor:"request_type,omitempty"`
// The user who issued the request.
Sender principal.Principal `cbor:"sender,omitempty"`
// Arbitrary user-provided data, typically randomly generated. This can be
// used to create distinct requests with otherwise identical fields.
Nonce []byte `cbor:"nonce,omitempty"`
// An upper limit on the validity of the request, expressed in nanoseconds
// since 1970-01-01 (like ic0.time()).
IngressExpiry uint64 `cbor:"ingress_expiry,omitempty"`
// The principal of the canister to call.
CanisterID principal.Principal `cbor:"canister_id"`
// Name of the canister method to call.
MethodName string `cbor:"method_name,omitempty"`
// Argument to pass to the canister method.
Arguments []byte `cbor:"arg,omitempty"`
// Paths (sequence of paths): A list of paths, where a path is itself a sequence of blobs.
Paths [][]byte `cbor:"paths,omitempty"`
}
type Envelope struct {
Content Request `cbor:"content,omitempty"`
SenderPubkey []byte `cbor:"sender_pubkey,omitempty"`
SenderSig []byte `cbor:"sender_sig,omitempty"`
}
func (agent *Agent) QueryRaw(canisterID, methodName string, arg []byte) ([]idl.Type, []interface{}, string, error) {
canisterIDPrincipal, err := principal.Decode(canisterID)
if err != nil {
return nil, nil, "", err
}
req := Request{
Type: RequestTypeQuery,
Sender: *agent.Sender(),
CanisterID: canisterIDPrincipal,
MethodName: methodName,
Arguments: arg,
IngressExpiry: uint64(agent.getExpiryDate().UnixNano()),
}
_, data, err := agent.signRequest(req)
if err != nil {
return nil, nil, "", err
}
resp, err := agent.queryEndpoint(canisterID, data)
if err != nil {
return nil, nil, "", err
}
func (agent *Agent) signRequest(req Request) (*RequestID, []byte, error) {
requestID := NewRequestID(req)
msg := []byte(IC_REQUEST_DOMAIN_SEPARATOR)
msg = append(msg, requestID[:]...)
sig, err := agent.key.Sign(msg)
if err != nil {
return nil, nil, err
}
envelope := Envelope{
Content: req,
SenderPubkey: agent.key.PubKey.SerializeUncompressed(),
SenderSig: sig.Serialize(),
}
marshaledEnvelope, err := cbor.Marshal(envelope)
if err != nil {
return nil, nil, err
}
return &requestID, marshaledEnvelope, nil
}
func (agent *Agent) queryEndpoint(canisterID string, data []byte) (map[string]interface{}, error) {
resp, err := agent.client.query(canisterID, data)
if err != nil {
return nil, err
}
result := make(map[string]interface{})
err = cbor.Unmarshal(resp, result)
if err != nil {
return result, err
}
return result, nil
}
func (c *Client) query(canisterId string, data []byte) ([]byte, error) {
buffer := bytes.NewBuffer(data)
endpoint := c.host + "/api/v2/canister/" + canisterId + "/query"
fmt.Println("post url:", endpoint)
resp, err := c.client.Post(endpoint, "application/cbor", buffer)
if err != nil {
return nil, err
} else if resp.StatusCode != 202 {
return nil, fmt.Errorf("post error: %v", resp.Status)
}
defer resp.Body.Close()
return io.ReadAll(resp.Body)
}