fix: add getList with records wrapper + correct options format from browser capture

This commit is contained in:
2026-07-28 17:03:59 +08:00
parent 284a503541
commit 7190d93edf
7 changed files with 56 additions and 15 deletions
+1 -1
View File
@@ -21,7 +21,7 @@ func (b *BillingService) Orders(ctx context.Context) ([]provider.Order, error) {
CreateDate string `json:"create_date"` CreateDate string `json:"create_date"`
} }
var raw []rainyunOrder var raw []rainyunOrder
if err := b.client.getWithQuery(ctx, "/expense/orders/list", map[string]string{"options": "1"}, &raw); err != nil { if err := b.client.getList(ctx, "/expense/orders/list", &raw); err != nil {
return nil, err return nil, err
} }
orders := make([]provider.Order, len(raw)) orders := make([]provider.Order, len(raw))
+17
View File
@@ -44,6 +44,23 @@ func (c *client) getWithQuery(ctx context.Context, path string, query map[string
return c.do(ctx, "GET", path, nil, result, query) return c.do(ctx, "GET", path, nil, result, query)
} }
// getList sends a GET request to a Rainyun list endpoint and extracts the "records" field.
func (c *client) getList(ctx context.Context, path string, result any) error {
var wrapper listResponse
if err := c.do(ctx, "GET", path, nil, &wrapper, listOptions()); err != nil {
return err
}
// Unmarshal the records array into the result
recordsJSON, err := json.Marshal(wrapper.Records)
if err != nil {
return fmt.Errorf("marshal records: %w", err)
}
if err := json.Unmarshal(recordsJSON, result); err != nil {
return fmt.Errorf("unmarshal records: %w", err)
}
return nil
}
func (c *client) post(ctx context.Context, path string, body, result any) error { func (c *client) post(ctx context.Context, path string, body, result any) error {
return c.do(ctx, "POST", path, body, result, nil) return c.do(ctx, "POST", path, body, result, nil)
} }
+1 -1
View File
@@ -20,7 +20,7 @@ type rainyunDomain struct {
func (d *DomainService) List(ctx context.Context) ([]provider.Domain, error) { func (d *DomainService) List(ctx context.Context) ([]provider.Domain, error) {
var raw []rainyunDomain var raw []rainyunDomain
if err := d.client.getWithQuery(ctx, "/product/domain/", map[string]string{"options": "1"}, &raw); err != nil { if err := d.client.getList(ctx, "/product/domain/", &raw); err != nil {
return nil, err return nil, err
} }
domains := make([]provider.Domain, len(raw)) domains := make([]provider.Domain, len(raw))
+21
View File
@@ -0,0 +1,21 @@
package rainyun
// listOptions returns the standard pagination query for Rainyun list endpoints.
// Format verified via browser DevTools capture of the Rainyun web console:
//
// https://api.v2.rainyun.com/product/rcs/?options={url-encoded JSON}
//
// The decoded JSON is: {"columnFilters":{},"sort":[],"page":1,"perPage":20}
func listOptions() map[string]string {
return map[string]string{
"options": `{"columnFilters":{},"sort":[],"page":1,"perPage":50}`,
}
}
// listResponse is the JSON envelope returned by Rainyun list endpoints.
// The API wraps data in {"code":0,"data":{"records":[...],"totalRecords":N}}.
// Our client extracts apiResp.Data ({"records":[...]}), then we unmarshal into this.
type listResponse struct {
Records []any `json:"records"`
TotalRecords int `json:"totalRecords"`
}
+1 -1
View File
@@ -29,7 +29,7 @@ type rainyunServer struct {
func (s *ServerService) List(ctx context.Context) ([]provider.Server, error) { func (s *ServerService) List(ctx context.Context) ([]provider.Server, error) {
var raw []rainyunServer var raw []rainyunServer
if err := s.client.getWithQuery(ctx, "/product/rcs/", map[string]string{"options": "1"}, &raw); err != nil { if err := s.client.getList(ctx, "/product/rcs/", &raw); err != nil {
return nil, err return nil, err
} }
servers := make([]provider.Server, len(raw)) servers := make([]provider.Server, len(raw))
+4 -1
View File
@@ -15,7 +15,8 @@ func TestServerList(t *testing.T) {
} }
resp := map[string]any{ resp := map[string]any{
"code": 0, "code": 0,
"data": []map[string]any{ "data": map[string]any{
"records": []map[string]any{
{ {
"id": 12001, "id": 12001,
"name": "web-server", "name": "web-server",
@@ -28,6 +29,8 @@ func TestServerList(t *testing.T) {
"expire_date": "2026-08-15", "expire_date": "2026-08-15",
}, },
}, },
"totalRecords": 1,
},
} }
json.NewEncoder(w).Encode(resp) json.NewEncoder(w).Encode(resp)
})) }))
+1 -1
View File
@@ -17,7 +17,7 @@ func (s *StorageService) List(ctx context.Context) ([]provider.StorageInstance,
Name string `json:"name"` Name string `json:"name"`
Status string `json:"status"` Status string `json:"status"`
} }
if err := s.client.getWithQuery(ctx, "/product/ros/instance", map[string]string{"options": "1"}, &raw); err != nil { if err := s.client.getList(ctx, "/product/ros/instance", &raw); err != nil {
return nil, err return nil, err
} }
instances := make([]provider.StorageInstance, len(raw)) instances := make([]provider.StorageInstance, len(raw))