github.com/muxinc/mux-go@v1.1.1/client.go (about)

     1  // Mux Go - Copyright 2019 Mux Inc.
     2  // NOTE: This file is auto generated. Do not edit this file manually.
     3  
     4  package muxgo
     5  
     6  import (
     7  	"bytes"
     8  	"context"
     9  	"encoding/json"
    10  	"encoding/xml"
    11  	"errors"
    12  	"fmt"
    13  	"io"
    14  	"mime/multipart"
    15  	"net/http"
    16  	"net/url"
    17  	"os"
    18  	"path/filepath"
    19  	"reflect"
    20  	"regexp"
    21  	"strconv"
    22  	"strings"
    23  	"time"
    24  	"unicode/utf8"
    25  )
    26  
    27  var (
    28  	jsonCheck = regexp.MustCompile("(?i:[application|text]/json)")
    29  	xmlCheck  = regexp.MustCompile("(?i:[application|text]/xml)")
    30  )
    31  
    32  // APIClient manages communication with the Mux API API vv1
    33  // In most cases there should be only one, shared, APIClient.
    34  type APIClient struct {
    35  	cfg    *Configuration
    36  	httpc  *http.Client
    37  	common service // Reuse a single struct instead of allocating one for each service on the heap.
    38  
    39  	// API Services
    40  	AssetsApi         *AssetsApiService
    41  	DeliveryUsageApi  *DeliveryUsageApiService
    42  	DimensionsApi     *DimensionsApiService
    43  	DirectUploadsApi  *DirectUploadsApiService
    44  	ErrorsApi         *ErrorsApiService
    45  	ExportsApi        *ExportsApiService
    46  	FiltersApi        *FiltersApiService
    47  	IncidentsApi      *IncidentsApiService
    48  	LiveStreamsApi    *LiveStreamsApiService
    49  	MetricsApi        *MetricsApiService
    50  	PlaybackIDApi     *PlaybackIDApiService
    51  	RealTimeApi       *RealTimeApiService
    52  	URLSigningKeysApi *URLSigningKeysApiService
    53  	VideoViewsApi     *VideoViewsApiService
    54  }
    55  
    56  type service struct {
    57  	client *APIClient
    58  }
    59  
    60  // NewAPIClient creates a new API client.
    61  func NewAPIClient(cfg *Configuration) *APIClient {
    62  	c := &APIClient{}
    63  	c.cfg = cfg
    64  	c.httpc = &http.Client{
    65  		Timeout: cfg.timeout,
    66  	}
    67  	c.common.client = c
    68  
    69  	// API Services
    70  	c.AssetsApi = (*AssetsApiService)(&c.common)
    71  	c.DeliveryUsageApi = (*DeliveryUsageApiService)(&c.common)
    72  	c.DimensionsApi = (*DimensionsApiService)(&c.common)
    73  	c.DirectUploadsApi = (*DirectUploadsApiService)(&c.common)
    74  	c.ErrorsApi = (*ErrorsApiService)(&c.common)
    75  	c.ExportsApi = (*ExportsApiService)(&c.common)
    76  	c.FiltersApi = (*FiltersApiService)(&c.common)
    77  	c.IncidentsApi = (*IncidentsApiService)(&c.common)
    78  	c.LiveStreamsApi = (*LiveStreamsApiService)(&c.common)
    79  	c.MetricsApi = (*MetricsApiService)(&c.common)
    80  	c.PlaybackIDApi = (*PlaybackIDApiService)(&c.common)
    81  	c.RealTimeApi = (*RealTimeApiService)(&c.common)
    82  	c.URLSigningKeysApi = (*URLSigningKeysApiService)(&c.common)
    83  	c.VideoViewsApi = (*VideoViewsApiService)(&c.common)
    84  
    85  	return c
    86  }
    87  
    88  func atoi(in string) (int, error) {
    89  	return strconv.Atoi(in)
    90  }
    91  
    92  // selectHeaderContentType select a content type from the available list.
    93  func selectHeaderContentType(contentTypes []string) string {
    94  	if len(contentTypes) == 0 {
    95  		return ""
    96  	}
    97  	if contains(contentTypes, "application/json") {
    98  		return "application/json"
    99  	}
   100  	return contentTypes[0] // use the first content type specified in 'consumes'
   101  }
   102  
   103  // selectHeaderAccept join all accept types and return
   104  func selectHeaderAccept(accepts []string) string {
   105  	if len(accepts) == 0 {
   106  		return ""
   107  	}
   108  
   109  	if contains(accepts, "application/json") {
   110  		return "application/json"
   111  	}
   112  
   113  	return strings.Join(accepts, ",")
   114  }
   115  
   116  // contains is a case insenstive match, finding needle in a haystack
   117  func contains(haystack []string, needle string) bool {
   118  	for _, a := range haystack {
   119  		if strings.ToLower(a) == strings.ToLower(needle) {
   120  			return true
   121  		}
   122  	}
   123  	return false
   124  }
   125  
   126  // Verify optional parameters are of the correct type.
   127  func typeCheckParameter(obj interface{}, expected string, name string) error {
   128  	// Make sure there is an object.
   129  	if obj == nil {
   130  		return nil
   131  	}
   132  
   133  	// Check the type is as expected.
   134  	if reflect.TypeOf(obj).String() != expected {
   135  		return fmt.Errorf("Expected %s to be of type %s but received %s.", name, expected, reflect.TypeOf(obj).String())
   136  	}
   137  	return nil
   138  }
   139  
   140  // parameterToString convert interface{} parameters to string, using a delimiter if format is provided.
   141  func parameterToString(obj interface{}, collectionFormat string) string {
   142  	var delimiter string
   143  
   144  	switch collectionFormat {
   145  	case "pipes":
   146  		delimiter = "|"
   147  	case "ssv":
   148  		delimiter = " "
   149  	case "tsv":
   150  		delimiter = "\t"
   151  	case "csv":
   152  		delimiter = ","
   153  	}
   154  
   155  	if reflect.TypeOf(obj).Kind() == reflect.Slice {
   156  		return strings.Trim(strings.Replace(fmt.Sprint(obj), " ", delimiter, -1), "[]")
   157  	} else if t, ok := obj.(time.Time); ok {
   158  		return t.Format(time.RFC3339)
   159  	}
   160  
   161  	return fmt.Sprintf("%v", obj)
   162  }
   163  
   164  // callAPI do the request.
   165  func (c *APIClient) callAPI(request *http.Request) (*http.Response, error) {
   166  	return c.httpc.Do(request)
   167  }
   168  
   169  // prepareRequest build the request
   170  func (c *APIClient) prepareRequest(
   171  	opts *APIOptions,
   172  	path string, method string,
   173  	postBody interface{},
   174  	headerParams map[string]string,
   175  	queryParams url.Values,
   176  	formParams url.Values,
   177  	formFileName string,
   178  	fileName string,
   179  	fileBytes []byte) (localVarRequest *http.Request, err error) {
   180  
   181  	var body *bytes.Buffer
   182  
   183  	// Detect postBody type and post.
   184  	if postBody != nil {
   185  		contentType := headerParams["Content-Type"]
   186  		if contentType == "" {
   187  			contentType = detectContentType(postBody)
   188  			headerParams["Content-Type"] = contentType
   189  		}
   190  
   191  		body, err = setBody(postBody, contentType)
   192  		if err != nil {
   193  			return nil, err
   194  		}
   195  	}
   196  
   197  	// add form parameters and file if available.
   198  	if strings.HasPrefix(headerParams["Content-Type"], "multipart/form-data") && len(formParams) > 0 || (len(fileBytes) > 0 && fileName != "") {
   199  		if body != nil {
   200  			return nil, errors.New("Cannot specify postBody and multipart form at the same time.")
   201  		}
   202  		body = &bytes.Buffer{}
   203  		w := multipart.NewWriter(body)
   204  
   205  		for k, v := range formParams {
   206  			for _, iv := range v {
   207  				if strings.HasPrefix(k, "@") { // file
   208  					err = addFile(w, k[1:], iv)
   209  					if err != nil {
   210  						return nil, err
   211  					}
   212  				} else { // form value
   213  					w.WriteField(k, iv)
   214  				}
   215  			}
   216  		}
   217  		if len(fileBytes) > 0 && fileName != "" {
   218  			w.Boundary()
   219  			//_, fileNm := filepath.Split(fileName)
   220  			part, err := w.CreateFormFile(formFileName, filepath.Base(fileName))
   221  			if err != nil {
   222  				return nil, err
   223  			}
   224  			_, err = part.Write(fileBytes)
   225  			if err != nil {
   226  				return nil, err
   227  			}
   228  			// Set the Boundary in the Content-Type
   229  			headerParams["Content-Type"] = w.FormDataContentType()
   230  		}
   231  
   232  		// Set Content-Length
   233  		headerParams["Content-Length"] = fmt.Sprintf("%d", body.Len())
   234  		w.Close()
   235  	}
   236  
   237  	if strings.HasPrefix(headerParams["Content-Type"], "application/x-www-form-urlencoded") && len(formParams) > 0 {
   238  		if body != nil {
   239  			return nil, errors.New("Cannot specify postBody and x-www-form-urlencoded form at the same time.")
   240  		}
   241  		body = &bytes.Buffer{}
   242  		body.WriteString(formParams.Encode())
   243  		// Set Content-Length
   244  		headerParams["Content-Length"] = fmt.Sprintf("%d", body.Len())
   245  	}
   246  
   247  	// Setup path and query parameters
   248  	url, err := url.Parse(path)
   249  	if err != nil {
   250  		return nil, err
   251  	}
   252  
   253  	// Adding Query Param
   254  	query := url.Query()
   255  	for k, v := range queryParams {
   256  		for _, iv := range v {
   257  			query.Add(k, iv)
   258  		}
   259  	}
   260  
   261  	// Encode the parameters.
   262  	url.RawQuery = query.Encode()
   263  
   264  	// Generate a new request
   265  	if body != nil {
   266  		localVarRequest, err = http.NewRequest(method, url.String(), body)
   267  	} else {
   268  		localVarRequest, err = http.NewRequest(method, url.String(), nil)
   269  	}
   270  	if err != nil {
   271  		return nil, err
   272  	}
   273  
   274  	// add header parameters, if any
   275  	if len(headerParams) > 0 {
   276  		headers := http.Header{}
   277  		for h, v := range headerParams {
   278  			headers.Set(h, v)
   279  		}
   280  		localVarRequest.Header = headers
   281  	}
   282  
   283  	// Override request host, if applicable
   284  	if c.cfg.host != "" {
   285  		localVarRequest.Host = c.cfg.host
   286  	}
   287  
   288  	// Add the user agent to the request.
   289  	localVarRequest.Header.Add("User-Agent", c.cfg.userAgent)
   290  
   291  	if opts.ctx != nil {
   292  		// add context to the request
   293  		localVarRequest = localVarRequest.WithContext(opts.ctx)
   294  	}
   295  
   296  	// Basic HTTP Authentication
   297  	if c.cfg.username == "" || c.cfg.password == "" {
   298  		return nil, errors.New("unauthorized APIClient")
   299  	}
   300  	localVarRequest.SetBasicAuth(c.cfg.username, c.cfg.password)
   301  
   302  	return localVarRequest, nil
   303  }
   304  
   305  func (c *APIClient) decode(v interface{}, b []byte, contentType string) (err error) {
   306  	if strings.Contains(contentType, "application/xml") {
   307  		if err = xml.Unmarshal(b, v); err != nil {
   308  			return err
   309  		}
   310  		return nil
   311  	} else if strings.Contains(contentType, "application/json") {
   312  		if err = json.Unmarshal(b, v); err != nil {
   313  			return err
   314  		}
   315  		return nil
   316  	}
   317  	return errors.New("undefined response type")
   318  }
   319  
   320  // Add a file to the multipart request
   321  func addFile(w *multipart.Writer, fieldName, path string) error {
   322  	file, err := os.Open(path)
   323  	if err != nil {
   324  		return err
   325  	}
   326  	defer file.Close()
   327  
   328  	part, err := w.CreateFormFile(fieldName, filepath.Base(path))
   329  	if err != nil {
   330  		return err
   331  	}
   332  	_, err = io.Copy(part, file)
   333  
   334  	return err
   335  }
   336  
   337  // Prevent trying to import "fmt"
   338  func reportError(format string, a ...interface{}) error {
   339  	return fmt.Errorf(format, a...)
   340  }
   341  
   342  // Set request body from an interface{}
   343  func setBody(body interface{}, contentType string) (bodyBuf *bytes.Buffer, err error) {
   344  	if bodyBuf == nil {
   345  		bodyBuf = &bytes.Buffer{}
   346  	}
   347  
   348  	if reader, ok := body.(io.Reader); ok {
   349  		_, err = bodyBuf.ReadFrom(reader)
   350  	} else if b, ok := body.([]byte); ok {
   351  		_, err = bodyBuf.Write(b)
   352  	} else if s, ok := body.(string); ok {
   353  		_, err = bodyBuf.WriteString(s)
   354  	} else if s, ok := body.(*string); ok {
   355  		_, err = bodyBuf.WriteString(*s)
   356  	} else if jsonCheck.MatchString(contentType) {
   357  		err = json.NewEncoder(bodyBuf).Encode(body)
   358  	} else if xmlCheck.MatchString(contentType) {
   359  		xml.NewEncoder(bodyBuf).Encode(body)
   360  	}
   361  
   362  	if err != nil {
   363  		return nil, err
   364  	}
   365  
   366  	if bodyBuf.Len() == 0 {
   367  		err = fmt.Errorf("Invalid body type %s\n", contentType)
   368  		return nil, err
   369  	}
   370  	return bodyBuf, nil
   371  }
   372  
   373  // detectContentType method is used to figure out `Request.Body` content type for request header
   374  func detectContentType(body interface{}) string {
   375  	contentType := "text/plain; charset=utf-8"
   376  	kind := reflect.TypeOf(body).Kind()
   377  
   378  	switch kind {
   379  	case reflect.Struct, reflect.Map, reflect.Ptr:
   380  		contentType = "application/json; charset=utf-8"
   381  	case reflect.String:
   382  		contentType = "text/plain; charset=utf-8"
   383  	default:
   384  		if b, ok := body.([]byte); ok {
   385  			contentType = http.DetectContentType(b)
   386  		} else if kind == reflect.Slice {
   387  			contentType = "application/json; charset=utf-8"
   388  		}
   389  	}
   390  
   391  	return contentType
   392  }
   393  
   394  func strlen(s string) int {
   395  	return utf8.RuneCountInString(s)
   396  }
   397  
   398  // APIOption sets options for API calls.
   399  type APIOption func(*APIOptions)
   400  
   401  // APIOptions wraps internal API call options.
   402  type APIOptions struct {
   403  	ctx    context.Context
   404  	params interface{}
   405  }
   406  
   407  // WithContext returns an APIOption that sets the context for an API call.
   408  func WithContext(ctx context.Context) APIOption {
   409  	return func(o *APIOptions) {
   410  		o.ctx = ctx
   411  	}
   412  }
   413  
   414  // WithParams returns an APIOption that sets the params for an API call. The params provided must be the correct type for the call or an error will be thrown by the call.
   415  func WithParams(params interface{}) APIOption {
   416  	return func(o *APIOptions) {
   417  		o.params = params
   418  	}
   419  }
   420  
   421  func isSet(val interface{}) bool {
   422  	return !(val == nil || reflect.DeepEqual(val, reflect.Zero(reflect.TypeOf(val)).Interface()))
   423  }
   424  
   425  // GenericOpenAPIError Provides access to the body, error and model on returned errors.
   426  type GenericOpenAPIError struct {
   427  	body  []byte
   428  	error string
   429  	model interface{}
   430  }
   431  
   432  // Error returns non-empty string if there was an error.
   433  func (e GenericOpenAPIError) Error() string {
   434  	return e.error
   435  }
   436  
   437  // Body returns the raw bytes of the response
   438  func (e GenericOpenAPIError) Body() []byte {
   439  	return e.body
   440  }
   441  
   442  // Model returns the unpacked model of the error
   443  func (e GenericOpenAPIError) Model() interface{} {
   444  	return e.model
   445  }
   446  
   447  // Below are the custom Mux API Error types, so that users of the SDK can identify
   448  // what issue they're running into more easily.
   449  
   450  // Generic 400 error
   451  type BadRequestError struct {
   452  	body  []byte
   453  	error string
   454  }
   455  
   456  func (e BadRequestError) Error() string {
   457  	return e.error
   458  }
   459  
   460  // 401 Error
   461  type UnauthorizedError struct {
   462  	body  []byte
   463  	error string
   464  }
   465  
   466  func (e UnauthorizedError) Error() string {
   467  	return e.error
   468  }
   469  
   470  func (e UnauthorizedError) Body() []byte {
   471  	return e.body
   472  }
   473  
   474  // 403 Error
   475  type ForbiddenError struct {
   476  	body  []byte
   477  	error string
   478  }
   479  
   480  func (e ForbiddenError) Error() string {
   481  	return e.error
   482  }
   483  
   484  func (e ForbiddenError) Body() []byte {
   485  	return e.body
   486  }
   487  
   488  // 404 Error
   489  type NotFoundError struct {
   490  	body  []byte
   491  	error string
   492  }
   493  
   494  func (e NotFoundError) Error() string {
   495  	return e.error
   496  }
   497  
   498  func (e NotFoundError) Body() []byte {
   499  	return e.body
   500  }
   501  
   502  // 429 Error
   503  type TooManyRequestsError struct {
   504  	body  []byte
   505  	error string
   506  }
   507  
   508  func (e TooManyRequestsError) Error() string {
   509  	return e.error
   510  }
   511  
   512  func (e TooManyRequestsError) Body() []byte {
   513  	return e.body
   514  }
   515  
   516  // 5XX Error
   517  type ServiceError struct {
   518  	body   []byte
   519  	status int
   520  	error  string
   521  }
   522  
   523  func (e ServiceError) Error() string {
   524  	return e.error
   525  }
   526  
   527  func (e ServiceError) Body() []byte {
   528  	return e.body
   529  }
   530  
   531  func (e ServiceError) Code() int {
   532  	return e.status
   533  }
   534  
   535  // Helper to check for common non-200 errors
   536  func CheckForHttpError(code int, body []byte) error {
   537  
   538  	if code >= 200 && code <= 299 {
   539  		return nil
   540  	}
   541  
   542  	switch code {
   543  	case 400:
   544  		return BadRequestError{body: body, error: "Bad Request"}
   545  	case 401:
   546  		return UnauthorizedError{body: body, error: "Unauthorized"}
   547  	case 403:
   548  		return ForbiddenError{body: body, error: "Forbidden"}
   549  	case 404:
   550  		return NotFoundError{body: body, error: "Not Found"}
   551  	case 429:
   552  		return TooManyRequestsError{body: body, error: "Too Many Requests"}
   553  	}
   554  
   555  	if code >= 500 && code <= 599 {
   556  		return ServiceError{body: body, status: code, error: "Service Error"}
   557  	}
   558  
   559  	return GenericOpenAPIError{body: body, error: "Generic Error"}
   560  }