github.com/safedep/dry@v0.0.0-20241016050132-a15651f0548b/apiguard/tykgen/client.go (about)

     1  /*
     2   * Tyk Gateway API
     3   *
     4   * The Tyk Gateway API is the primary means for integrating your application with the Tyk API Gateway system. This API is very small, and has no granular permissions system. It is intended to be used purely for internal automation and integration.  **Warning: Under no circumstances should outside parties be granted access to this API.**  The Tyk Gateway API is capable of:  * Managing session objects (key generation) * Managing and listing policies * Managing and listing API Definitions (only when not using the Dashboard) * Hot reloads / reloading a cluster configuration * OAuth client creation (only when not using the Dashboard)   In order to use the Gateway API, you'll need to set the `secret` parameter in your tyk.conf file.  The shared secret you set should then be sent along as a header with each Gateway API Request in order for it to be successful:  ``` x-tyk-authorization: <your-secret> ``` <br/> <b>The Tyk Gateway API is subsumed by the Tyk Dashboard API in Pro installations.</b>
     5   *
     6   * API version: 5.5.0
     7   * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
     8   */
     9  package swagger
    10  
    11  import (
    12  	"bytes"
    13  	"context"
    14  	"encoding/json"
    15  	"encoding/xml"
    16  	"errors"
    17  	"fmt"
    18  	"io"
    19  	"mime/multipart"
    20  	"net/http"
    21  	"net/url"
    22  	"os"
    23  	"path/filepath"
    24  	"reflect"
    25  	"regexp"
    26  	"strconv"
    27  	"strings"
    28  	"time"
    29  	"unicode/utf8"
    30  
    31  	"golang.org/x/oauth2"
    32  )
    33  
    34  var (
    35  	jsonCheck = regexp.MustCompile("(?i:[application|text]/json)")
    36  	xmlCheck  = regexp.MustCompile("(?i:[application|text]/xml)")
    37  )
    38  
    39  // APIClient manages communication with the Tyk Gateway API API v5.5.0
    40  // In most cases there should be only one, shared, APIClient.
    41  type APIClient struct {
    42  	cfg    *Configuration
    43  	common service // Reuse a single struct instead of allocating one for each service on the heap.
    44  
    45  	// API Services
    46  
    47  	APIsApi *APIsApiService
    48  
    49  	BatchRequestsApi *BatchRequestsApiService
    50  
    51  	CacheInvalidationApi *CacheInvalidationApiService
    52  
    53  	CertsApi *CertsApiService
    54  
    55  	HealthCheckingApi *HealthCheckingApiService
    56  
    57  	HotReloadApi *HotReloadApiService
    58  
    59  	KeysApi *KeysApiService
    60  
    61  	OASAPIsApi *OASAPIsApiService
    62  
    63  	OAuthApi *OAuthApiService
    64  
    65  	OrganisationQuotasApi *OrganisationQuotasApiService
    66  
    67  	PoliciesApi *PoliciesApiService
    68  
    69  	SchemaApi *SchemaApiService
    70  }
    71  
    72  type service struct {
    73  	client *APIClient
    74  }
    75  
    76  // NewAPIClient creates a new API client. Requires a userAgent string describing your application.
    77  // optionally a custom http.Client to allow for advanced features such as caching.
    78  func NewAPIClient(cfg *Configuration) *APIClient {
    79  	if cfg.HTTPClient == nil {
    80  		cfg.HTTPClient = http.DefaultClient
    81  	}
    82  
    83  	c := &APIClient{}
    84  	c.cfg = cfg
    85  	c.common.client = c
    86  
    87  	// API Services
    88  	c.APIsApi = (*APIsApiService)(&c.common)
    89  	c.BatchRequestsApi = (*BatchRequestsApiService)(&c.common)
    90  	c.CacheInvalidationApi = (*CacheInvalidationApiService)(&c.common)
    91  	c.CertsApi = (*CertsApiService)(&c.common)
    92  	c.HealthCheckingApi = (*HealthCheckingApiService)(&c.common)
    93  	c.HotReloadApi = (*HotReloadApiService)(&c.common)
    94  	c.KeysApi = (*KeysApiService)(&c.common)
    95  	c.OASAPIsApi = (*OASAPIsApiService)(&c.common)
    96  	c.OAuthApi = (*OAuthApiService)(&c.common)
    97  	c.OrganisationQuotasApi = (*OrganisationQuotasApiService)(&c.common)
    98  	c.PoliciesApi = (*PoliciesApiService)(&c.common)
    99  	c.SchemaApi = (*SchemaApiService)(&c.common)
   100  
   101  	return c
   102  }
   103  
   104  func atoi(in string) (int, error) {
   105  	return strconv.Atoi(in)
   106  }
   107  
   108  // selectHeaderContentType select a content type from the available list.
   109  func selectHeaderContentType(contentTypes []string) string {
   110  	if len(contentTypes) == 0 {
   111  		return ""
   112  	}
   113  	if contains(contentTypes, "application/json") {
   114  		return "application/json"
   115  	}
   116  	return contentTypes[0] // use the first content type specified in 'consumes'
   117  }
   118  
   119  // selectHeaderAccept join all accept types and return
   120  func selectHeaderAccept(accepts []string) string {
   121  	if len(accepts) == 0 {
   122  		return ""
   123  	}
   124  
   125  	if contains(accepts, "application/json") {
   126  		return "application/json"
   127  	}
   128  
   129  	return strings.Join(accepts, ",")
   130  }
   131  
   132  // contains is a case insenstive match, finding needle in a haystack
   133  func contains(haystack []string, needle string) bool {
   134  	for _, a := range haystack {
   135  		if strings.ToLower(a) == strings.ToLower(needle) {
   136  			return true
   137  		}
   138  	}
   139  	return false
   140  }
   141  
   142  // Verify optional parameters are of the correct type.
   143  func typeCheckParameter(obj interface{}, expected string, name string) error {
   144  	// Make sure there is an object.
   145  	if obj == nil {
   146  		return nil
   147  	}
   148  
   149  	// Check the type is as expected.
   150  	if reflect.TypeOf(obj).String() != expected {
   151  		return fmt.Errorf("Expected %s to be of type %s but received %s.", name, expected, reflect.TypeOf(obj).String())
   152  	}
   153  	return nil
   154  }
   155  
   156  // parameterToString convert interface{} parameters to string, using a delimiter if format is provided.
   157  func parameterToString(obj interface{}, collectionFormat string) string {
   158  	var delimiter string
   159  
   160  	switch collectionFormat {
   161  	case "pipes":
   162  		delimiter = "|"
   163  	case "ssv":
   164  		delimiter = " "
   165  	case "tsv":
   166  		delimiter = "\t"
   167  	case "csv":
   168  		delimiter = ","
   169  	}
   170  
   171  	if reflect.TypeOf(obj).Kind() == reflect.Slice {
   172  		return strings.Trim(strings.Replace(fmt.Sprint(obj), " ", delimiter, -1), "[]")
   173  	}
   174  
   175  	return fmt.Sprintf("%v", obj)
   176  }
   177  
   178  // callAPI do the request.
   179  func (c *APIClient) callAPI(request *http.Request) (*http.Response, error) {
   180  	return c.cfg.HTTPClient.Do(request)
   181  }
   182  
   183  // Change base path to allow switching to mocks
   184  func (c *APIClient) ChangeBasePath(path string) {
   185  	c.cfg.BasePath = path
   186  }
   187  
   188  // prepareRequest build the request
   189  func (c *APIClient) prepareRequest(
   190  	ctx context.Context,
   191  	path string, method string,
   192  	postBody interface{},
   193  	headerParams map[string]string,
   194  	queryParams url.Values,
   195  	formParams url.Values,
   196  	fileName string,
   197  	fileBytes []byte) (localVarRequest *http.Request, err error) {
   198  
   199  	var body *bytes.Buffer
   200  
   201  	// Detect postBody type and post.
   202  	if postBody != nil {
   203  		contentType := headerParams["Content-Type"]
   204  		if contentType == "" {
   205  			contentType = detectContentType(postBody)
   206  			headerParams["Content-Type"] = contentType
   207  		}
   208  
   209  		body, err = setBody(postBody, contentType)
   210  		if err != nil {
   211  			return nil, err
   212  		}
   213  	}
   214  
   215  	// add form parameters and file if available.
   216  	if strings.HasPrefix(headerParams["Content-Type"], "multipart/form-data") && len(formParams) > 0 || (len(fileBytes) > 0 && fileName != "") {
   217  		if body != nil {
   218  			return nil, errors.New("Cannot specify postBody and multipart form at the same time.")
   219  		}
   220  		body = &bytes.Buffer{}
   221  		w := multipart.NewWriter(body)
   222  
   223  		for k, v := range formParams {
   224  			for _, iv := range v {
   225  				if strings.HasPrefix(k, "@") { // file
   226  					err = addFile(w, k[1:], iv)
   227  					if err != nil {
   228  						return nil, err
   229  					}
   230  				} else { // form value
   231  					w.WriteField(k, iv)
   232  				}
   233  			}
   234  		}
   235  		if len(fileBytes) > 0 && fileName != "" {
   236  			w.Boundary()
   237  			//_, fileNm := filepath.Split(fileName)
   238  			part, err := w.CreateFormFile("file", filepath.Base(fileName))
   239  			if err != nil {
   240  				return nil, err
   241  			}
   242  			_, err = part.Write(fileBytes)
   243  			if err != nil {
   244  				return nil, err
   245  			}
   246  			// Set the Boundary in the Content-Type
   247  			headerParams["Content-Type"] = w.FormDataContentType()
   248  		}
   249  
   250  		// Set Content-Length
   251  		headerParams["Content-Length"] = fmt.Sprintf("%d", body.Len())
   252  		w.Close()
   253  	}
   254  
   255  	if strings.HasPrefix(headerParams["Content-Type"], "application/x-www-form-urlencoded") && len(formParams) > 0 {
   256  		if body != nil {
   257  			return nil, errors.New("Cannot specify postBody and x-www-form-urlencoded form at the same time.")
   258  		}
   259  		body = &bytes.Buffer{}
   260  		body.WriteString(formParams.Encode())
   261  		// Set Content-Length
   262  		headerParams["Content-Length"] = fmt.Sprintf("%d", body.Len())
   263  	}
   264  
   265  	// Setup path and query parameters
   266  	url, err := url.Parse(path)
   267  	if err != nil {
   268  		return nil, err
   269  	}
   270  
   271  	// Adding Query Param
   272  	query := url.Query()
   273  	for k, v := range queryParams {
   274  		for _, iv := range v {
   275  			query.Add(k, iv)
   276  		}
   277  	}
   278  
   279  	// Encode the parameters.
   280  	url.RawQuery = query.Encode()
   281  
   282  	// Generate a new request
   283  	if body != nil {
   284  		localVarRequest, err = http.NewRequest(method, url.String(), body)
   285  	} else {
   286  		localVarRequest, err = http.NewRequest(method, url.String(), nil)
   287  	}
   288  	if err != nil {
   289  		return nil, err
   290  	}
   291  
   292  	// add header parameters, if any
   293  	if len(headerParams) > 0 {
   294  		headers := http.Header{}
   295  		for h, v := range headerParams {
   296  			headers.Set(h, v)
   297  		}
   298  		localVarRequest.Header = headers
   299  	}
   300  
   301  	// Override request host, if applicable
   302  	if c.cfg.Host != "" {
   303  		localVarRequest.Host = c.cfg.Host
   304  	}
   305  
   306  	// Add the user agent to the request.
   307  	localVarRequest.Header.Add("User-Agent", c.cfg.UserAgent)
   308  
   309  	if ctx != nil {
   310  		// add context to the request
   311  		localVarRequest = localVarRequest.WithContext(ctx)
   312  
   313  		// Walk through any authentication.
   314  
   315  		// OAuth2 authentication
   316  		if tok, ok := ctx.Value(ContextOAuth2).(oauth2.TokenSource); ok {
   317  			// We were able to grab an oauth2 token from the context
   318  			var latestToken *oauth2.Token
   319  			if latestToken, err = tok.Token(); err != nil {
   320  				return nil, err
   321  			}
   322  
   323  			latestToken.SetAuthHeader(localVarRequest)
   324  		}
   325  
   326  		// Basic HTTP Authentication
   327  		if auth, ok := ctx.Value(ContextBasicAuth).(BasicAuth); ok {
   328  			localVarRequest.SetBasicAuth(auth.UserName, auth.Password)
   329  		}
   330  
   331  		// AccessToken Authentication
   332  		if auth, ok := ctx.Value(ContextAccessToken).(string); ok {
   333  			localVarRequest.Header.Add("Authorization", "Bearer "+auth)
   334  		}
   335  	}
   336  
   337  	for header, value := range c.cfg.DefaultHeader {
   338  		localVarRequest.Header.Add(header, value)
   339  	}
   340  
   341  	return localVarRequest, nil
   342  }
   343  
   344  func (c *APIClient) decode(v interface{}, b []byte, contentType string) (err error) {
   345  		if strings.Contains(contentType, "application/xml") {
   346  			if err = xml.Unmarshal(b, v); err != nil {
   347  				return err
   348  			}
   349  			return nil
   350  		} else if strings.Contains(contentType, "application/json") {
   351  			if err = json.Unmarshal(b, v); err != nil {
   352  				return err
   353  			}
   354  			return nil
   355  		}
   356  	return errors.New("undefined response type")
   357  }
   358  
   359  // Add a file to the multipart request
   360  func addFile(w *multipart.Writer, fieldName, path string) error {
   361  	file, err := os.Open(path)
   362  	if err != nil {
   363  		return err
   364  	}
   365  	defer file.Close()
   366  
   367  	part, err := w.CreateFormFile(fieldName, filepath.Base(path))
   368  	if err != nil {
   369  		return err
   370  	}
   371  	_, err = io.Copy(part, file)
   372  
   373  	return err
   374  }
   375  
   376  // Prevent trying to import "fmt"
   377  func reportError(format string, a ...interface{}) error {
   378  	return fmt.Errorf(format, a...)
   379  }
   380  
   381  // Set request body from an interface{}
   382  func setBody(body interface{}, contentType string) (bodyBuf *bytes.Buffer, err error) {
   383  	if bodyBuf == nil {
   384  		bodyBuf = &bytes.Buffer{}
   385  	}
   386  
   387  	if reader, ok := body.(io.Reader); ok {
   388  		_, err = bodyBuf.ReadFrom(reader)
   389  	} else if b, ok := body.([]byte); ok {
   390  		_, err = bodyBuf.Write(b)
   391  	} else if s, ok := body.(string); ok {
   392  		_, err = bodyBuf.WriteString(s)
   393  	} else if s, ok := body.(*string); ok {
   394  		_, err = bodyBuf.WriteString(*s)
   395  	} else if jsonCheck.MatchString(contentType) {
   396  		err = json.NewEncoder(bodyBuf).Encode(body)
   397  	} else if xmlCheck.MatchString(contentType) {
   398  		xml.NewEncoder(bodyBuf).Encode(body)
   399  	}
   400  
   401  	if err != nil {
   402  		return nil, err
   403  	}
   404  
   405  	if bodyBuf.Len() == 0 {
   406  		err = fmt.Errorf("Invalid body type %s\n", contentType)
   407  		return nil, err
   408  	}
   409  	return bodyBuf, nil
   410  }
   411  
   412  // detectContentType method is used to figure out `Request.Body` content type for request header
   413  func detectContentType(body interface{}) string {
   414  	contentType := "text/plain; charset=utf-8"
   415  	kind := reflect.TypeOf(body).Kind()
   416  
   417  	switch kind {
   418  	case reflect.Struct, reflect.Map, reflect.Ptr:
   419  		contentType = "application/json; charset=utf-8"
   420  	case reflect.String:
   421  		contentType = "text/plain; charset=utf-8"
   422  	default:
   423  		if b, ok := body.([]byte); ok {
   424  			contentType = http.DetectContentType(b)
   425  		} else if kind == reflect.Slice {
   426  			contentType = "application/json; charset=utf-8"
   427  		}
   428  	}
   429  
   430  	return contentType
   431  }
   432  
   433  // Ripped from https://github.com/gregjones/httpcache/blob/master/httpcache.go
   434  type cacheControl map[string]string
   435  
   436  func parseCacheControl(headers http.Header) cacheControl {
   437  	cc := cacheControl{}
   438  	ccHeader := headers.Get("Cache-Control")
   439  	for _, part := range strings.Split(ccHeader, ",") {
   440  		part = strings.Trim(part, " ")
   441  		if part == "" {
   442  			continue
   443  		}
   444  		if strings.ContainsRune(part, '=') {
   445  			keyval := strings.Split(part, "=")
   446  			cc[strings.Trim(keyval[0], " ")] = strings.Trim(keyval[1], ",")
   447  		} else {
   448  			cc[part] = ""
   449  		}
   450  	}
   451  	return cc
   452  }
   453  
   454  // CacheExpires helper function to determine remaining time before repeating a request.
   455  func CacheExpires(r *http.Response) time.Time {
   456  	// Figure out when the cache expires.
   457  	var expires time.Time
   458  	now, err := time.Parse(time.RFC1123, r.Header.Get("date"))
   459  	if err != nil {
   460  		return time.Now()
   461  	}
   462  	respCacheControl := parseCacheControl(r.Header)
   463  
   464  	if maxAge, ok := respCacheControl["max-age"]; ok {
   465  		lifetime, err := time.ParseDuration(maxAge + "s")
   466  		if err != nil {
   467  			expires = now
   468  		}
   469  		expires = now.Add(lifetime)
   470  	} else {
   471  		expiresHeader := r.Header.Get("Expires")
   472  		if expiresHeader != "" {
   473  			expires, err = time.Parse(time.RFC1123, expiresHeader)
   474  			if err != nil {
   475  				expires = now
   476  			}
   477  		}
   478  	}
   479  	return expires
   480  }
   481  
   482  func strlen(s string) int {
   483  	return utf8.RuneCountInString(s)
   484  }
   485  
   486  // GenericSwaggerError Provides access to the body, error and model on returned errors.
   487  type GenericSwaggerError struct {
   488  	body  []byte
   489  	error string
   490  	model interface{}
   491  }
   492  
   493  // Error returns non-empty string if there was an error.
   494  func (e GenericSwaggerError) Error() string {
   495  	return e.error
   496  }
   497  
   498  // Body returns the raw bytes of the response
   499  func (e GenericSwaggerError) Body() []byte {
   500  	return e.body
   501  }
   502  
   503  // Model returns the unpacked model of the error
   504  func (e GenericSwaggerError) Model() interface{} {
   505  	return e.model
   506  }