fix: query params support + remove duplicate response wrappers + fix tests
This commit is contained in:
@@ -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.get(ctx, "/expense/orders/list", &raw); err != nil {
|
if err := b.client.getWithQuery(ctx, "/expense/orders/list", map[string]string{"options": "1"}, &raw); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
orders := make([]provider.Order, len(raw))
|
orders := make([]provider.Order, len(raw))
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -36,23 +37,35 @@ type apiResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *client) get(ctx context.Context, path string, result any) error {
|
func (c *client) get(ctx context.Context, path string, result any) error {
|
||||||
return c.do(ctx, "GET", path, nil, result)
|
return c.do(ctx, "GET", path, nil, result, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *client) getWithQuery(ctx context.Context, path string, query map[string]string, result any) error {
|
||||||
|
return c.do(ctx, "GET", path, nil, result, query)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
return c.do(ctx, "POST", path, body, result, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *client) patch(ctx context.Context, path string, body, result any) error {
|
func (c *client) patch(ctx context.Context, path string, body, result any) error {
|
||||||
return c.do(ctx, "PATCH", path, body, result)
|
return c.do(ctx, "PATCH", path, body, result, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *client) delete(ctx context.Context, path string, result any) error {
|
func (c *client) delete(ctx context.Context, path string, result any) error {
|
||||||
return c.do(ctx, "DELETE", path, nil, result)
|
return c.do(ctx, "DELETE", path, nil, result, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *client) do(ctx context.Context, method, path string, body, result any) error {
|
func (c *client) do(ctx context.Context, method, path string, body, result any, query map[string]string) error {
|
||||||
url := c.baseURL + path
|
u := c.baseURL + path
|
||||||
|
|
||||||
|
if len(query) > 0 {
|
||||||
|
params := url.Values{}
|
||||||
|
for k, v := range query {
|
||||||
|
params.Set(k, v)
|
||||||
|
}
|
||||||
|
u += "?" + params.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
var bodyReader io.Reader
|
var bodyReader io.Reader
|
||||||
if body != nil {
|
if body != nil {
|
||||||
@@ -63,7 +76,7 @@ func (c *client) do(ctx context.Context, method, path string, body, result any)
|
|||||||
bodyReader = bytes.NewReader(b)
|
bodyReader = bytes.NewReader(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(ctx, method, url, bodyReader)
|
req, err := http.NewRequestWithContext(ctx, method, u, bodyReader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("create request: %w", err)
|
return fmt.Errorf("create request: %w", err)
|
||||||
}
|
}
|
||||||
@@ -88,7 +101,7 @@ func (c *client) do(ctx context.Context, method, path string, body, result any)
|
|||||||
return &APIError{
|
return &APIError{
|
||||||
StatusCode: resp.StatusCode,
|
StatusCode: resp.StatusCode,
|
||||||
Method: method,
|
Method: method,
|
||||||
URL: url,
|
URL: u,
|
||||||
Body: respBody,
|
Body: respBody,
|
||||||
APICode: apiResp.Code,
|
APICode: apiResp.Code,
|
||||||
APIMsg: apiResp.Msg,
|
APIMsg: apiResp.Msg,
|
||||||
@@ -98,14 +111,14 @@ func (c *client) do(ctx context.Context, method, path string, body, result any)
|
|||||||
return &APIError{
|
return &APIError{
|
||||||
StatusCode: resp.StatusCode,
|
StatusCode: resp.StatusCode,
|
||||||
Method: method,
|
Method: method,
|
||||||
URL: url,
|
URL: u,
|
||||||
Body: respBody,
|
Body: respBody,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if result != nil {
|
if result != nil && apiResp.Data != nil {
|
||||||
if err := json.Unmarshal(respBody, result); err != nil {
|
if err := json.Unmarshal(apiResp.Data, result); err != nil {
|
||||||
return fmt.Errorf("unmarshal response: %w", err)
|
return fmt.Errorf("unmarshal data: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -18,11 +18,8 @@ func TestClientAuthHeader(t *testing.T) {
|
|||||||
|
|
||||||
c := newClient(srv.URL, "sk-test")
|
c := newClient(srv.URL, "sk-test")
|
||||||
var result struct {
|
var result struct {
|
||||||
Code int `json:"code"`
|
ID int `json:"id"`
|
||||||
Data struct {
|
Name string `json:"name"`
|
||||||
ID int `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
} `json:"data"`
|
|
||||||
}
|
}
|
||||||
if err := c.get(context.Background(), "/test", &result); err != nil {
|
if err := c.get(context.Background(), "/test", &result); err != nil {
|
||||||
t.Fatalf("get() error: %v", err)
|
t.Fatalf("get() error: %v", err)
|
||||||
@@ -30,8 +27,8 @@ func TestClientAuthHeader(t *testing.T) {
|
|||||||
if gotKey != "sk-test" {
|
if gotKey != "sk-test" {
|
||||||
t.Errorf("X-Api-Key = %q, want %q", gotKey, "sk-test")
|
t.Errorf("X-Api-Key = %q, want %q", gotKey, "sk-test")
|
||||||
}
|
}
|
||||||
if result.Data.Name != "test" {
|
if result.Name != "test" {
|
||||||
t.Errorf("Data.Name = %q, want %q", result.Data.Name, "test")
|
t.Errorf("Name = %q, want %q", result.Name, "test")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.get(ctx, "/product/domain/", &raw); err != nil {
|
if err := d.client.getWithQuery(ctx, "/product/domain/", map[string]string{"options": "1"}, &raw); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
domains := make([]provider.Domain, len(raw))
|
domains := make([]provider.Domain, len(raw))
|
||||||
|
|||||||
@@ -27,43 +27,25 @@ type rainyunServer struct {
|
|||||||
ExpireDate string `json:"expire_date"`
|
ExpireDate string `json:"expire_date"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Response wrappers — the client unmarshals the full API envelope (code + data).
|
|
||||||
type serverListResponse struct {
|
|
||||||
Code int `json:"code"`
|
|
||||||
Data []rainyunServer `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type serverGetResponse struct {
|
|
||||||
Code int `json:"code"`
|
|
||||||
Data rainyunServer `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type vncResponse struct {
|
|
||||||
Code int `json:"code"`
|
|
||||||
Data struct {
|
|
||||||
VNCURL string `json:"vnc_url"`
|
|
||||||
} `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ServerService) List(ctx context.Context) ([]provider.Server, error) {
|
func (s *ServerService) List(ctx context.Context) ([]provider.Server, error) {
|
||||||
var resp serverListResponse
|
var raw []rainyunServer
|
||||||
if err := s.client.get(ctx, "/product/rcs/", &resp); err != nil {
|
if err := s.client.getWithQuery(ctx, "/product/rcs/", map[string]string{"options": "1"}, &raw); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
servers := make([]provider.Server, len(resp.Data))
|
servers := make([]provider.Server, len(raw))
|
||||||
for i, r := range resp.Data {
|
for i, r := range raw {
|
||||||
servers[i] = toServer(r)
|
servers[i] = toServer(r)
|
||||||
}
|
}
|
||||||
return servers, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ServerService) Get(ctx context.Context, id string) (*provider.Server, error) {
|
func (s *ServerService) Get(ctx context.Context, id string) (*provider.Server, error) {
|
||||||
var resp serverGetResponse
|
var raw rainyunServer
|
||||||
path := fmt.Sprintf("/product/rcs/%s/", id)
|
path := fmt.Sprintf("/product/rcs/%s/", id)
|
||||||
if err := s.client.get(ctx, path, &resp); err != nil {
|
if err := s.client.get(ctx, path, &raw); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
sv := toServer(resp.Data)
|
sv := toServer(raw)
|
||||||
return &sv, nil
|
return &sv, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,11 +71,13 @@ func (s *ServerService) ResetPassword(ctx context.Context, id string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *ServerService) GetVNC(ctx context.Context, id string) (string, error) {
|
func (s *ServerService) GetVNC(ctx context.Context, id string) (string, error) {
|
||||||
var resp vncResponse
|
var resp struct {
|
||||||
|
VNCURL string `json:"vnc_url"`
|
||||||
|
}
|
||||||
if err := s.client.get(ctx, fmt.Sprintf("/product/rcs/%s/vnc", id), &resp); err != nil {
|
if err := s.client.get(ctx, fmt.Sprintf("/product/rcs/%s/vnc", id), &resp); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return resp.Data.VNCURL, nil
|
return resp.VNCURL, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ServerService) Upgrade(ctx context.Context, id, plan string) error {
|
func (s *ServerService) Upgrade(ctx context.Context, id, plan string) error {
|
||||||
|
|||||||
@@ -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.get(ctx, "/product/ros/instance", &raw); err != nil {
|
if err := s.client.getWithQuery(ctx, "/product/ros/instance", map[string]string{"options": "1"}, &raw); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
instances := make([]provider.StorageInstance, len(raw))
|
instances := make([]provider.StorageInstance, len(raw))
|
||||||
|
|||||||
Reference in New Issue
Block a user