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 }