git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/bunny/client.go (about)

     1  package bunny
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"encoding/json"
     7  	"io"
     8  	"net/http"
     9  
    10  	"git.sr.ht/~pingoo/stdx/httpx"
    11  )
    12  
    13  type Client struct {
    14  	httpClient       *http.Client
    15  	acountApiKey     string
    16  	apiBaseURL       string
    17  	streamApiBaseUrl string
    18  	streamApiKey     string
    19  }
    20  
    21  func NewClient(acountApiKey, streamApiKey string, httpClient *http.Client) *Client {
    22  	if httpClient == nil {
    23  		httpClient = httpx.DefaultClient()
    24  	}
    25  
    26  	return &Client{
    27  		httpClient:       httpClient,
    28  		acountApiKey:     acountApiKey,
    29  		streamApiKey:     streamApiKey,
    30  		apiBaseURL:       "https://api.bunny.net",
    31  		streamApiBaseUrl: "https://video.bunnycdn.com",
    32  	}
    33  }
    34  
    35  type requestParams struct {
    36  	Method          string
    37  	URL             string
    38  	Payload         interface{}
    39  	useStreamApiKey bool
    40  }
    41  
    42  type uploadParams struct {
    43  	Method          string
    44  	URL             string
    45  	Data            io.Reader
    46  	useStreamApiKey bool
    47  }
    48  
    49  type APIError struct {
    50  	Message string
    51  }
    52  
    53  func (res APIError) Error() string {
    54  	return res.Message
    55  }
    56  
    57  func (client *Client) request(ctx context.Context, params requestParams, dst interface{}) error {
    58  	req, err := http.NewRequestWithContext(ctx, params.Method, params.URL, nil)
    59  	if err != nil {
    60  		return err
    61  	}
    62  
    63  	if params.Payload != nil {
    64  		payloadData, err := json.Marshal(params.Payload)
    65  		if err != nil {
    66  			return err
    67  		}
    68  		req.Body = io.NopCloser(bytes.NewBuffer(payloadData))
    69  	}
    70  
    71  	apiKey := client.acountApiKey
    72  	if params.useStreamApiKey {
    73  		apiKey = client.streamApiKey
    74  	}
    75  
    76  	req.Header.Add(httpx.HeaderAccept, httpx.MediaTypeJson)
    77  	req.Header.Add(httpx.HeaderContentType, httpx.MediaTypeJson)
    78  	req.Header.Add("AccessKey", apiKey)
    79  
    80  	res, err := client.httpClient.Do(req)
    81  	if err != nil {
    82  		return err
    83  	}
    84  	defer res.Body.Close()
    85  
    86  	body, err := io.ReadAll(res.Body)
    87  	if err != nil {
    88  		return err
    89  	}
    90  
    91  	if res.StatusCode >= 400 {
    92  		var apiErr APIError
    93  
    94  		err = json.Unmarshal(body, &apiErr)
    95  		if err != nil {
    96  			return err
    97  		}
    98  
    99  		return apiErr
   100  	} else if dst != nil {
   101  		err = json.Unmarshal(body, dst)
   102  	}
   103  
   104  	return err
   105  }
   106  
   107  func (client *Client) upload(ctx context.Context, params uploadParams, dst interface{}) error {
   108  	req, err := http.NewRequestWithContext(ctx, params.Method, params.URL, params.Data)
   109  	if err != nil {
   110  		return err
   111  	}
   112  
   113  	apiKey := client.acountApiKey
   114  	if params.useStreamApiKey {
   115  		apiKey = client.streamApiKey
   116  	}
   117  
   118  	req.Header.Add(httpx.HeaderAccept, httpx.MediaTypeJson)
   119  	req.Header.Add(httpx.HeaderContentType, "application/octet-stream")
   120  	req.Header.Add("AccessKey", apiKey)
   121  
   122  	res, err := client.httpClient.Do(req)
   123  	if err != nil {
   124  		return err
   125  	}
   126  	defer res.Body.Close()
   127  
   128  	body, err := io.ReadAll(res.Body)
   129  	if err != nil {
   130  		return err
   131  	}
   132  
   133  	if res.StatusCode >= 400 {
   134  		var apiErr APIError
   135  
   136  		err = json.Unmarshal(body, &apiErr)
   137  		if err != nil {
   138  			return err
   139  		}
   140  
   141  		return apiErr
   142  	} else if dst != nil {
   143  		err = json.Unmarshal(body, dst)
   144  	}
   145  
   146  	return err
   147  }