Skip to content

Commit

Permalink
Use POST, check errors correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
Shaptic committed Aug 19, 2024
1 parent ac5d325 commit ed1392e
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 26 deletions.
60 changes: 39 additions & 21 deletions clients/stellarcore/client.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package stellarcore

import (
"bytes"
"context"
"encoding/json"
"fmt"
Expand Down Expand Up @@ -152,19 +153,19 @@ func (c *Client) SetCursor(ctx context.Context, id string, cursor int32) (err er
return nil
}

func (c *Client) GetLedgerEntries(ctx context.Context, ledgerSeq uint32, keys ...xdr.LedgerKey) (*proto.GetLedgerEntriesResponse, error) {
var resp *proto.GetLedgerEntriesResponse
return resp, c.makeLedgerKeyRequest(ctx, resp, "getledgerentries", ledgerSeq, keys...)
func (c *Client) GetLedgerEntries(ctx context.Context, ledgerSeq uint32, keys ...xdr.LedgerKey) (proto.GetLedgerEntriesResponse, error) {
var resp proto.GetLedgerEntriesResponse
return resp, c.makeLedgerKeyRequest(ctx, &resp, "getledgerentry", ledgerSeq, keys...)
}

func (c *Client) getInvocationProof(ctx context.Context, ledgerSeq uint32, keys ...xdr.LedgerKey) (*proto.ProofResponse, error) {
var resp *proto.ProofResponse
return resp, c.makeLedgerKeyRequest(ctx, resp, "getinvocationproof", ledgerSeq, keys...)
func (c *Client) getInvocationProof(ctx context.Context, ledgerSeq uint32, keys ...xdr.LedgerKey) (proto.ProofResponse, error) {
var resp proto.ProofResponse
return resp, c.makeLedgerKeyRequest(ctx, &resp, "getinvocationproof", ledgerSeq, keys...)
}

func (c *Client) getRestorationProof(ctx context.Context, ledgerSeq uint32, keys ...xdr.LedgerKey) (*proto.ProofResponse, error) {
var resp *proto.ProofResponse
return resp, c.makeLedgerKeyRequest(ctx, resp, "getrestorationproof", ledgerSeq, keys...)
func (c *Client) getRestorationProof(ctx context.Context, ledgerSeq uint32, keys ...xdr.LedgerKey) (proto.ProofResponse, error) {
var resp proto.ProofResponse
return resp, c.makeLedgerKeyRequest(ctx, &resp, "getrestorationproof", ledgerSeq, keys...)
}

// SubmitTransaction calls the `tx` command on the connected stellar core with the provided envelope
Expand Down Expand Up @@ -268,31 +269,48 @@ func (c *Client) simpleGet(
newPath string,
query url.Values,
) (*http.Request, error) {
q := ""
u, err := url.Parse(c.URL)
if err != nil {
return nil, errors.Wrap(err, "unparseable url")
}

u.Path = path.Join(u.Path, newPath)
if query != nil {
q = query.Encode()
u.RawQuery = query.Encode()
}
newURL := u.String()

var req *http.Request
req, err = http.NewRequestWithContext(ctx, http.MethodGet, newURL, nil)
if err != nil {
return nil, errors.Wrap(err, "failed to create request")
}
return c.rawGet(ctx, newPath, q)

return req, nil
}

// rawGet returns a new GET request to the connected stellar-core using the
// provided path and a raw query string to construct the result.
func (c *Client) rawGet(
// rawPost returns a new POST request to the connected stellar-core using the
// provided path and the params values encoded as the request body to construct
// the result.
func (c *Client) rawPost(
ctx context.Context,
newPath string,
query string,
params string,
) (*http.Request, error) {
u, err := url.Parse(c.URL)
if err != nil {
return nil, errors.Wrap(err, "unparseable url")
}

u.Path = path.Join(u.Path, newPath)
u.RawQuery = query
newURL := u.String()

var req *http.Request
req, err = http.NewRequestWithContext(ctx, http.MethodGet, newURL, nil)
req, err = http.NewRequestWithContext(
ctx,
http.MethodPost,
newURL,
bytes.NewBuffer([]byte(params)))
if err != nil {
return nil, errors.Wrap(err, "failed to create request")
}
Expand All @@ -302,7 +320,7 @@ func (c *Client) rawGet(

// makeLedgerKeyRequest is a generic method to perform a request in the form
// `key=...&key=...&ledgerSeq=...` which is useful because three Stellar Core
// endpoints all use this request format.
// endpoints all use this request format. Be sure to pass `target by reference.
func (c *Client) makeLedgerKeyRequest(
ctx context.Context,
target interface{},
Expand All @@ -317,7 +335,7 @@ func (c *Client) makeLedgerKeyRequest(
}

var req *http.Request
req, err = c.rawGet(ctx, endpoint, q)
req, err = c.rawPost(ctx, endpoint, q)
if err != nil {
return err
}
Expand All @@ -327,7 +345,7 @@ func (c *Client) makeLedgerKeyRequest(
return err
}

// returns nil if the error is nil
// wrap returns nil if the inner error is nil
return errors.Wrap(json.NewDecoder(hresp.Body).Decode(&target), "json decode failed")
}

Expand Down
9 changes: 4 additions & 5 deletions clients/stellarcore/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ func TestGetLedgerEntries(t *testing.T) {
hmock := httptest.NewClient()
c := &Client{HTTP: hmock, URL: "http://localhost:11626"}

// happy path - new transaction
hmock.On("GET", "http://localhost:11626/getledgerentry").
// happy path - fetch an entry
hmock.On("POST", "http://localhost:11626/getledgerentry").
ReturnString(http.StatusOK,
`{"ledger": 1234, "entries": [ {"e": "pretend it's xdr lol", "state": "Dead" }]}`,
`{"ledger": 1234, "entries": [ {"e": "pretend it's xdr lol", "state": "dead" }]}`,
)

var key xdr.LedgerKey
Expand All @@ -96,10 +96,9 @@ func TestGetLedgerEntries(t *testing.T) {

resp, err := c.GetLedgerEntries(context.Background(), 1234, key)
require.NoError(t, err)
require.NotNil(t, resp)

require.EqualValues(t, 1234, resp.Ledger)
require.Len(t, resp.Entries, 1)
require.Equal(t, resp.Entries[0].State, proto.DeadState)

require.EqualError(t, err, "exception in response: Set MANUAL_CLOSE=true")
}

0 comments on commit ed1392e

Please sign in to comment.