Skip to content

Commit

Permalink
сreate a method to send a custom request
Browse files Browse the repository at this point in the history
  • Loading branch information
zakhar-petukhov authored and aleksej-paschenko committed Aug 9, 2024
1 parent 86e93d7 commit 7162154
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 0 deletions.
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
github.com/gorilla/websocket v1.5.1
github.com/ogen-go/ogen v0.77.0
github.com/r3labs/sse/v2 v2.10.0
github.com/stretchr/testify v1.8.4
github.com/tonkeeper/tongo v1.7.0
go.opentelemetry.io/otel v1.19.0
go.opentelemetry.io/otel/metric v1.19.0
Expand All @@ -16,6 +17,7 @@ require (
)

require (

This comment has been minimized.

Copy link
@Hadhb

Hadhb Sep 16, 2024

UQBcLFHC7OdsxJwNRnGrsIF1bYLeYhNb74yy4FoyQNmzJaz9

This comment has been minimized.

Copy link
@Hadhb

Hadhb Sep 16, 2024

UQBcLFHC7OdsxJwNRnGrsIF1bYLeYhNb74yy4FoyQNmzJaz9

github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dlclark/regexp2 v1.10.0 // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
Expand All @@ -26,6 +28,7 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/oasisprotocol/curve25519-voi v0.0.0-20220328075252-7dd334e3daae // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/segmentio/asm v1.2.0 // indirect
github.com/snksoft/crc v1.1.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
Expand All @@ -39,4 +42,5 @@ require (
golang.org/x/tools v0.14.0 // indirect
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
88 changes: 88 additions & 0 deletions tonapi.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
package tonapi

import (
"bytes"

This comment has been minimized.

Copy link
@Hadhb

Hadhb Sep 16, 2024

UQBcLFHC7OdsxJwNRnGrsIF1bYLeYhNb74yy4FoyQNmzJaz9

"context"
"encoding/base64"
"encoding/json"
"io"
"net/url"
"time"

"github.com/go-faster/errors"
ht "github.com/ogen-go/ogen/http"
"github.com/tonkeeper/tongo"
"github.com/tonkeeper/tongo/tlb"
)

type Custom interface {

This comment has been minimized.

Copy link
@Hadhb

Hadhb Sep 16, 2024

UQBcLFHC7OdsxJwNRnGrsIF1bYLeYhNb74yy4FoyQNmzJaz9

Request(ctx context.Context, method, url string, params map[string]string, data []byte) (json.RawMessage, error)
}

func (c *Client) GetSeqno(ctx context.Context, account tongo.AccountID) (uint32, error) {
res, err := c.GetAccountSeqno(ctx, GetAccountSeqnoParams{AccountID: account.ToRaw()})

This comment has been minimized.

Copy link
@Hadhb

Hadhb Sep 16, 2024

UQBcLFHC7OdsxJwNRnGrsIF1bYLeYhNb74yy4FoyQNmzJaz9

if err != nil {
Expand Down Expand Up @@ -53,3 +64,80 @@ func (c *Client) GetAccountState(ctx context.Context, accountID tongo.AccountID)
}
return shardAccount, nil

This comment has been minimized.

Copy link
@Hadhb

Hadhb Sep 16, 2024

UQBcLFHC7OdsxJwNRnGrsIF1bYLeYhNb74yy4FoyQNmzJaz9

}

// Request sends an HTTP request with the given method, URL, parameters, and data,
// and returns the response as a json.RawMessage.
func (c *Client) Request(ctx context.Context, method, endpoint string, query map[string]string, data []byte) (json.RawMessage, error) {
const contentType = "application/json"

// Start measuring the request duration
startTime := time.Now()
defer func() {
// Use floating point division here for higher precision (instead of Millisecond method).
elapsedDuration := time.Since(startTime)
c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond))
}()

// Parse the full URL by resolving the endpoint relative to the server URL
u := c.serverURL.ResolveReference(&url.URL{Path: endpoint})

// Add query parameters to the URL if any
if query != nil {

This comment has been minimized.

Copy link
@Hadhb

Hadhb Sep 16, 2024

UQBcLFHC7OdsxJwNRnGrsIF1bYLeYhNb74yy4FoyQNmzJaz9

q := u.Query()
for key, value := range query {

This comment has been minimized.

Copy link
@Hadhb

Hadhb Sep 16, 2024

UQBcLFHC7OdsxJwNRnGrsIF1bYLeYhNb74yy4FoyQNmzJaz9

q.Set(key, value)
}
u.RawQuery = q.Encode()
}

// Create the request
req, err := ht.NewRequest(ctx, method, u)
if err != nil {

This comment has been minimized.

Copy link
@Hadhb

Hadhb Sep 16, 2024

UQBcLFHC7OdsxJwNRnGrsIF1bYLeYhNb74yy4FoyQNmzJaz9

// Increment the error counter
c.errors.Add(ctx, 1)

This comment has been minimized.

Copy link
@Hadhb

Hadhb Sep 16, 2024

UQBcLFHC7OdsxJwNRnGrsIF1bYLeYhNb74yy4FoyQNmzJaz9

return nil, err
}
if data != nil {
ht.SetBody(req, bytes.NewReader(data), contentType)
}

// Set the content type header
req.Header.Set("Content-Type", contentType)

// Send the request using the baseClient's HTTP client
resp, err := c.cfg.Client.Do(req) // Use the appropriate client or config
if err != nil {
// Increment the error counter
c.errors.Add(ctx, 1)
return nil, err
}
defer resp.Body.Close()

c.requests.Add(ctx, 1)

// Check if the response status code indicates an error
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
// Increment the error counter
c.errors.Add(ctx, 1)
return nil, errors.New(resp.Status)
}

// Read the response body
body, err := io.ReadAll(resp.Body)
if err != nil {
// Increment the error counter
c.errors.Add(ctx, 1)
return nil, err
}

// Unmarshal the response body into json.RawMessage
var jsonResponse json.RawMessage
err = json.Unmarshal(body, &jsonResponse)
if err != nil {
// Increment the error counter
c.errors.Add(ctx, 1)
return nil, err
}

return jsonResponse, nil
}
77 changes: 77 additions & 0 deletions tonapi_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package tonapi

import (
"context"
"fmt"
"net/http"
"testing"
"time"

"github.com/go-faster/errors"
"github.com/stretchr/testify/require"
"github.com/tonkeeper/tongo/ton"
)

var systemAccountID = ton.MustParseAccountID("Ef8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAU")

func TestCustomRequest(t *testing.T) {
client, err := New()
if err != nil {
t.Fatalf("failed to init tonapi client: %v", err)
}

tests := []struct {
name string
method string
path string
query map[string]string
err error
}{
{
name: "fail to get account info - method not allowed",
method: http.MethodPost,
path: fmt.Sprintf("v2/accounts/%v", systemAccountID),
err: errors.New("405 Method Not Allowed"),
},
{
name: "ok to get account info",
method: http.MethodGet,
path: fmt.Sprintf("v2/accounts/%v", systemAccountID),
err: nil,
},
{
name: "fail with invalid account ID",
method: http.MethodGet,
path: "v2/accounts/invalidAccountID",
err: errors.New("400 Bad Request"),
},
{
name: "fail with non-existent path",
method: http.MethodGet,
path: "v2/nonexistentpath",
err: errors.New("404 Not Found"),
},
{
name: "ok to get collections",
method: http.MethodGet,
path: "v2/nfts/collections",
query: map[string]string{"limit": "10"},
err: nil,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
resp, err := client.Request(context.Background(), tt.method, tt.path, tt.query, nil)
if tt.err != nil {
require.Error(t, err)
require.Equal(t, tt.err.Error(), err.Error())
require.Nil(t, resp)
} else {
require.NoError(t, err)
require.NotNil(t, resp)
}
time.Sleep(time.Millisecond * 100) // rps limit
})
}
}

0 comments on commit 7162154

Please sign in to comment.