client.go raw

   1  /*
   2  Intelligent DNS API
   3  
   4  No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
   5  
   6  API version: 1.0.0
   7  */
   8  
   9  // Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
  10  
  11  package idns
  12  
  13  import (
  14  	"bytes"
  15  	"context"
  16  	"encoding/json"
  17  	"encoding/xml"
  18  	"errors"
  19  	"fmt"
  20  	"io"
  21  	"log"
  22  	"mime/multipart"
  23  	"net/http"
  24  	"net/http/httputil"
  25  	"net/url"
  26  	"os"
  27  	"path/filepath"
  28  	"reflect"
  29  	"regexp"
  30  	"strconv"
  31  	"strings"
  32  	"time"
  33  	"unicode/utf8"
  34  
  35  )
  36  
  37  var (
  38  	jsonCheck = regexp.MustCompile(`(?i:(?:application|text)/(?:vnd\.[^;]+\+)?json)`)
  39  	xmlCheck  = regexp.MustCompile(`(?i:(?:application|text)/xml)`)
  40  	queryParamSplit = regexp.MustCompile(`(^|&)([^&]+)`)
  41  	queryDescape    = strings.NewReplacer( "%5B", "[", "%5D", "]" )
  42  )
  43  
  44  // APIClient manages communication with the Intelligent DNS API API v1.0.0
  45  // In most cases there should be only one, shared, APIClient.
  46  type APIClient struct {
  47  	cfg    *Configuration
  48  	common service // Reuse a single struct instead of allocating one for each service on the heap.
  49  
  50  	// API Services
  51  
  52  	DNSSECAPI *DNSSECAPIService
  53  
  54  	RecordsAPI *RecordsAPIService
  55  
  56  	ZonesAPI *ZonesAPIService
  57  }
  58  
  59  type service struct {
  60  	client *APIClient
  61  }
  62  
  63  // NewAPIClient creates a new API client. Requires a userAgent string describing your application.
  64  // optionally a custom http.Client to allow for advanced features such as caching.
  65  func NewAPIClient(cfg *Configuration) *APIClient {
  66  	if cfg.HTTPClient == nil {
  67  		cfg.HTTPClient = http.DefaultClient
  68  	}
  69  
  70  	c := &APIClient{}
  71  	c.cfg = cfg
  72  	c.common.client = c
  73  
  74  	// API Services
  75  	c.DNSSECAPI = (*DNSSECAPIService)(&c.common)
  76  	c.RecordsAPI = (*RecordsAPIService)(&c.common)
  77  	c.ZonesAPI = (*ZonesAPIService)(&c.common)
  78  
  79  	return c
  80  }
  81  
  82  func atoi(in string) (int, error) {
  83  	return strconv.Atoi(in)
  84  }
  85  
  86  // selectHeaderContentType select a content type from the available list.
  87  func selectHeaderContentType(contentTypes []string) string {
  88  	if len(contentTypes) == 0 {
  89  		return ""
  90  	}
  91  	if contains(contentTypes, "application/json") {
  92  		return "application/json"
  93  	}
  94  	return contentTypes[0] // use the first content type specified in 'consumes'
  95  }
  96  
  97  // selectHeaderAccept join all accept types and return
  98  func selectHeaderAccept(accepts []string) string {
  99  	if len(accepts) == 0 {
 100  		return ""
 101  	}
 102  
 103  	if contains(accepts, "application/json") {
 104  		return "application/json"
 105  	}
 106  
 107  	return strings.Join(accepts, ",")
 108  }
 109  
 110  // contains is a case insensitive match, finding needle in a haystack
 111  func contains(haystack []string, needle string) bool {
 112  	for _, a := range haystack {
 113  		if strings.EqualFold(a, needle) {
 114  			return true
 115  		}
 116  	}
 117  	return false
 118  }
 119  
 120  // Verify optional parameters are of the correct type.
 121  func typeCheckParameter(obj interface{}, expected string, name string) error {
 122  	// Make sure there is an object.
 123  	if obj == nil {
 124  		return nil
 125  	}
 126  
 127  	// Check the type is as expected.
 128  	if reflect.TypeOf(obj).String() != expected {
 129  		return fmt.Errorf("expected %s to be of type %s but received %s", name, expected, reflect.TypeOf(obj).String())
 130  	}
 131  	return nil
 132  }
 133  
 134  func parameterValueToString( obj interface{}, key string ) string {
 135  	if reflect.TypeOf(obj).Kind() != reflect.Ptr {
 136  		return fmt.Sprintf("%v", obj)
 137  	}
 138  	var param,ok = obj.(MappedNullable)
 139  	if !ok {
 140  		return ""
 141  	}
 142  	dataMap,err := param.ToMap()
 143  	if err != nil {
 144  		return ""
 145  	}
 146  	return fmt.Sprintf("%v", dataMap[key])
 147  }
 148  
 149  // parameterAddToHeaderOrQuery adds the provided object to the request header or url query
 150  // supporting deep object syntax
 151  func parameterAddToHeaderOrQuery(headerOrQueryParams interface{}, keyPrefix string, obj interface{}, collectionType string) {
 152  	var v = reflect.ValueOf(obj)
 153  	var value = ""
 154  	if v == reflect.ValueOf(nil) {
 155  		value = "null"
 156  	} else {
 157  		switch v.Kind() {
 158  			case reflect.Invalid:
 159  				value = "invalid"
 160  
 161  			case reflect.Struct:
 162  				if t,ok := obj.(MappedNullable); ok {
 163  					dataMap,err := t.ToMap()
 164  					if err != nil {
 165  						return
 166  					}
 167  					parameterAddToHeaderOrQuery(headerOrQueryParams, keyPrefix, dataMap, collectionType)
 168  					return
 169  				}
 170  				if t, ok := obj.(time.Time); ok {
 171  					parameterAddToHeaderOrQuery(headerOrQueryParams, keyPrefix, t.Format(time.RFC3339), collectionType)
 172  					return
 173  				}
 174  				value = v.Type().String() + " value"
 175  			case reflect.Slice:
 176  				var indValue = reflect.ValueOf(obj)
 177  				if indValue == reflect.ValueOf(nil) {
 178  					return
 179  				}
 180  				var lenIndValue = indValue.Len()
 181  				for i:=0;i<lenIndValue;i++ {
 182  					var arrayValue = indValue.Index(i)
 183  					parameterAddToHeaderOrQuery(headerOrQueryParams, keyPrefix, arrayValue.Interface(), collectionType)
 184  				}
 185  				return
 186  
 187  			case reflect.Map:
 188  				var indValue = reflect.ValueOf(obj)
 189  				if indValue == reflect.ValueOf(nil) {
 190  					return
 191  				}
 192  				iter := indValue.MapRange()
 193  				for iter.Next() {
 194  					k,v := iter.Key(), iter.Value()
 195  					parameterAddToHeaderOrQuery(headerOrQueryParams, fmt.Sprintf("%s[%s]", keyPrefix, k.String()), v.Interface(), collectionType)
 196  				}
 197  				return
 198  
 199  			case reflect.Interface:
 200  				fallthrough
 201  			case reflect.Ptr:
 202  				parameterAddToHeaderOrQuery(headerOrQueryParams, keyPrefix, v.Elem().Interface(), collectionType)
 203  				return
 204  
 205  			case reflect.Int, reflect.Int8, reflect.Int16,
 206  				reflect.Int32, reflect.Int64:
 207  				value = strconv.FormatInt(v.Int(), 10)
 208  			case reflect.Uint, reflect.Uint8, reflect.Uint16,
 209  				reflect.Uint32, reflect.Uint64, reflect.Uintptr:
 210  				value = strconv.FormatUint(v.Uint(), 10)
 211  			case reflect.Float32, reflect.Float64:
 212  				value = strconv.FormatFloat(v.Float(), 'g', -1, 32)
 213  			case reflect.Bool:
 214  				value = strconv.FormatBool(v.Bool())
 215  			case reflect.String:
 216  				value = v.String()
 217  			default:
 218  				value = v.Type().String() + " value"
 219  		}
 220  	}
 221  
 222  	switch valuesMap := headerOrQueryParams.(type) {
 223  		case url.Values:
 224  			if collectionType == "csv" && valuesMap.Get(keyPrefix) != "" {
 225  				valuesMap.Set(keyPrefix, valuesMap.Get(keyPrefix) + "," + value)
 226  			} else {
 227  				valuesMap.Add(keyPrefix, value)
 228  			}
 229  			break
 230  		case map[string]string:
 231  			valuesMap[keyPrefix] = value
 232  			break
 233  	}
 234  }
 235  
 236  // helper for converting interface{} parameters to json strings
 237  func parameterToJson(obj interface{}) (string, error) {
 238  	jsonBuf, err := json.Marshal(obj)
 239  	if err != nil {
 240  		return "", err
 241  	}
 242  	return string(jsonBuf), err
 243  }
 244  
 245  // callAPI do the request.
 246  func (c *APIClient) callAPI(request *http.Request) (*http.Response, error) {
 247  	if c.cfg.Debug {
 248  		dump, err := httputil.DumpRequestOut(request, true)
 249  		if err != nil {
 250  			return nil, err
 251  		}
 252  		log.Printf("\n%s\n", string(dump))
 253  	}
 254  
 255  	resp, err := c.cfg.HTTPClient.Do(request)
 256  	if err != nil {
 257  		return resp, err
 258  	}
 259  
 260  	if c.cfg.Debug {
 261  		dump, err := httputil.DumpResponse(resp, true)
 262  		if err != nil {
 263  			return resp, err
 264  		}
 265  		log.Printf("\n%s\n", string(dump))
 266  	}
 267  	return resp, err
 268  }
 269  
 270  // Allow modification of underlying config for alternate implementations and testing
 271  // Caution: modifying the configuration while live can cause data races and potentially unwanted behavior
 272  func (c *APIClient) GetConfig() *Configuration {
 273  	return c.cfg
 274  }
 275  
 276  type formFile struct {
 277  		fileBytes []byte
 278  		fileName string
 279  		formFileName string
 280  }
 281  
 282  // prepareRequest build the request
 283  func (c *APIClient) prepareRequest(
 284  	ctx context.Context,
 285  	path string, method string,
 286  	postBody interface{},
 287  	headerParams map[string]string,
 288  	queryParams url.Values,
 289  	formParams url.Values,
 290  	formFiles []formFile) (localVarRequest *http.Request, err error) {
 291  
 292  	var body *bytes.Buffer
 293  
 294  	// Detect postBody type and post.
 295  	if postBody != nil {
 296  		contentType := headerParams["Content-Type"]
 297  		if contentType == "" {
 298  			contentType = detectContentType(postBody)
 299  			headerParams["Content-Type"] = contentType
 300  		}
 301  
 302  		body, err = setBody(postBody, contentType)
 303  		if err != nil {
 304  			return nil, err
 305  		}
 306  	}
 307  
 308  	// add form parameters and file if available.
 309  	if strings.HasPrefix(headerParams["Content-Type"], "multipart/form-data") && len(formParams) > 0 || (len(formFiles) > 0) {
 310  		if body != nil {
 311  			return nil, errors.New("Cannot specify postBody and multipart form at the same time.")
 312  		}
 313  		body = &bytes.Buffer{}
 314  		w := multipart.NewWriter(body)
 315  
 316  		for k, v := range formParams {
 317  			for _, iv := range v {
 318  				if strings.HasPrefix(k, "@") { // file
 319  					err = addFile(w, k[1:], iv)
 320  					if err != nil {
 321  						return nil, err
 322  					}
 323  				} else { // form value
 324  					w.WriteField(k, iv)
 325  				}
 326  			}
 327  		}
 328  		for _, formFile := range formFiles {
 329  			if len(formFile.fileBytes) > 0 && formFile.fileName != "" {
 330  				w.Boundary()
 331  				part, err := w.CreateFormFile(formFile.formFileName, filepath.Base(formFile.fileName))
 332  				if err != nil {
 333  						return nil, err
 334  				}
 335  				_, err = part.Write(formFile.fileBytes)
 336  				if err != nil {
 337  						return nil, err
 338  				}
 339  			}
 340  		}
 341  
 342  		// Set the Boundary in the Content-Type
 343  		headerParams["Content-Type"] = w.FormDataContentType()
 344  
 345  		// Set Content-Length
 346  		headerParams["Content-Length"] = fmt.Sprintf("%d", body.Len())
 347  		w.Close()
 348  	}
 349  
 350  	if strings.HasPrefix(headerParams["Content-Type"], "application/x-www-form-urlencoded") && len(formParams) > 0 {
 351  		if body != nil {
 352  			return nil, errors.New("Cannot specify postBody and x-www-form-urlencoded form at the same time.")
 353  		}
 354  		body = &bytes.Buffer{}
 355  		body.WriteString(formParams.Encode())
 356  		// Set Content-Length
 357  		headerParams["Content-Length"] = fmt.Sprintf("%d", body.Len())
 358  	}
 359  
 360  	// Setup path and query parameters
 361  	url, err := url.Parse(path)
 362  	if err != nil {
 363  		return nil, err
 364  	}
 365  
 366  	// Override request host, if applicable
 367  	if c.cfg.Host != "" {
 368  		url.Host = c.cfg.Host
 369  	}
 370  
 371  	// Override request scheme, if applicable
 372  	if c.cfg.Scheme != "" {
 373  		url.Scheme = c.cfg.Scheme
 374  	}
 375  
 376  	// Adding Query Param
 377  	query := url.Query()
 378  	for k, v := range queryParams {
 379  		for _, iv := range v {
 380  			query.Add(k, iv)
 381  		}
 382  	}
 383  
 384  	// Encode the parameters.
 385  	url.RawQuery = queryParamSplit.ReplaceAllStringFunc(query.Encode(), func(s string) string {
 386  		pieces := strings.Split(s, "=")
 387  		pieces[0] = queryDescape.Replace(pieces[0])
 388  		return strings.Join(pieces, "=")
 389  	})
 390  
 391  	// Generate a new request
 392  	if body != nil {
 393  		localVarRequest, err = http.NewRequest(method, url.String(), body)
 394  	} else {
 395  		localVarRequest, err = http.NewRequest(method, url.String(), nil)
 396  	}
 397  	if err != nil {
 398  		return nil, err
 399  	}
 400  
 401  	// add header parameters, if any
 402  	if len(headerParams) > 0 {
 403  		headers := http.Header{}
 404  		for h, v := range headerParams {
 405  			headers[h] = []string{v}
 406  		}
 407  		localVarRequest.Header = headers
 408  	}
 409  
 410  	// Add the user agent to the request.
 411  	localVarRequest.Header.Add("User-Agent", c.cfg.UserAgent)
 412  
 413  	if ctx != nil {
 414  		// add context to the request
 415  		localVarRequest = localVarRequest.WithContext(ctx)
 416  
 417  		// Walk through any authentication.
 418  
 419  	}
 420  
 421  	for header, value := range c.cfg.DefaultHeader {
 422  		localVarRequest.Header.Add(header, value)
 423  	}
 424  	return localVarRequest, nil
 425  }
 426  
 427  func (c *APIClient) decode(v interface{}, b []byte, contentType string) (err error) {
 428  	if len(b) == 0 {
 429  		return nil
 430  	}
 431  	if s, ok := v.(*string); ok {
 432  		*s = string(b)
 433  		return nil
 434  	}
 435  	if f, ok := v.(*os.File); ok {
 436  		f, err = os.CreateTemp("", "HttpClientFile")
 437  		if err != nil {
 438  			return
 439  		}
 440  		_, err = f.Write(b)
 441  		if err != nil {
 442  			return
 443  		}
 444  		_, err = f.Seek(0, io.SeekStart)
 445  		err = os.Remove(f.Name())
 446  		return
 447  	}
 448  	if f, ok := v.(**os.File); ok {
 449  		*f, err = os.CreateTemp("", "HttpClientFile")
 450  		if err != nil {
 451  			return
 452  		}
 453  		_, err = (*f).Write(b)
 454  		if err != nil {
 455  			return
 456  		}
 457  		_, err = (*f).Seek(0, io.SeekStart)
 458  		err = os.Remove((*f).Name())
 459  		return
 460  	}
 461  	if xmlCheck.MatchString(contentType) {
 462  		if err = xml.Unmarshal(b, v); err != nil {
 463  			return err
 464  		}
 465  		return nil
 466  	}
 467  	if jsonCheck.MatchString(contentType) {
 468  		if actualObj, ok := v.(interface{ GetActualInstance() interface{} }); ok { // oneOf, anyOf schemas
 469  			if unmarshalObj, ok := actualObj.(interface{ UnmarshalJSON([]byte) error }); ok { // make sure it has UnmarshalJSON defined
 470  				if err = unmarshalObj.UnmarshalJSON(b); err != nil {
 471  					return err
 472  				}
 473  			} else {
 474  				return errors.New("Unknown type with GetActualInstance but no unmarshalObj.UnmarshalJSON defined")
 475  			}
 476  		} else if err = json.Unmarshal(b, v); err != nil { // simple model
 477  			return err
 478  		}
 479  		return nil
 480  	}
 481  	return errors.New("undefined response type")
 482  }
 483  
 484  // Add a file to the multipart request
 485  func addFile(w *multipart.Writer, fieldName, path string) error {
 486  	file, err := os.Open(filepath.Clean(path))
 487  	if err != nil {
 488  		return err
 489  	}
 490  	err = file.Close()
 491  	if err != nil {
 492  		return err
 493  	}
 494  
 495  	part, err := w.CreateFormFile(fieldName, filepath.Base(path))
 496  	if err != nil {
 497  		return err
 498  	}
 499  	_, err = io.Copy(part, file)
 500  
 501  	return err
 502  }
 503  
 504  // Prevent trying to import "fmt"
 505  func reportError(format string, a ...interface{}) error {
 506  	return fmt.Errorf(format, a...)
 507  }
 508  
 509  // A wrapper for strict JSON decoding
 510  func newStrictDecoder(data []byte) *json.Decoder {
 511  	dec := json.NewDecoder(bytes.NewBuffer(data))
 512  	dec.DisallowUnknownFields()
 513  	return dec
 514  }
 515  
 516  // Set request body from an interface{}
 517  func setBody(body interface{}, contentType string) (bodyBuf *bytes.Buffer, err error) {
 518  	if bodyBuf == nil {
 519  		bodyBuf = &bytes.Buffer{}
 520  	}
 521  
 522  	if reader, ok := body.(io.Reader); ok {
 523  		_, err = bodyBuf.ReadFrom(reader)
 524  	} else if fp, ok := body.(*os.File); ok {
 525  		_, err = bodyBuf.ReadFrom(fp)
 526  	} else if b, ok := body.([]byte); ok {
 527  		_, err = bodyBuf.Write(b)
 528  	} else if s, ok := body.(string); ok {
 529  		_, err = bodyBuf.WriteString(s)
 530  	} else if s, ok := body.(*string); ok {
 531  		_, err = bodyBuf.WriteString(*s)
 532  	} else if jsonCheck.MatchString(contentType) {
 533  		err = json.NewEncoder(bodyBuf).Encode(body)
 534  	} else if xmlCheck.MatchString(contentType) {
 535  		var bs []byte
 536  		bs, err = xml.Marshal(body)
 537  		if err == nil {
 538  			bodyBuf.Write(bs)
 539  		}
 540  	}
 541  
 542  	if err != nil {
 543  		return nil, err
 544  	}
 545  
 546  	if bodyBuf.Len() == 0 {
 547  		err = fmt.Errorf("invalid body type %s\n", contentType)
 548  		return nil, err
 549  	}
 550  	return bodyBuf, nil
 551  }
 552  
 553  // detectContentType method is used to figure out `Request.Body` content type for request header
 554  func detectContentType(body interface{}) string {
 555  	contentType := "text/plain; charset=utf-8"
 556  	kind := reflect.TypeOf(body).Kind()
 557  
 558  	switch kind {
 559  	case reflect.Struct, reflect.Map, reflect.Ptr:
 560  		contentType = "application/json; charset=utf-8"
 561  	case reflect.String:
 562  		contentType = "text/plain; charset=utf-8"
 563  	default:
 564  		if b, ok := body.([]byte); ok {
 565  			contentType = http.DetectContentType(b)
 566  		} else if kind == reflect.Slice {
 567  			contentType = "application/json; charset=utf-8"
 568  		}
 569  	}
 570  
 571  	return contentType
 572  }
 573  
 574  // Ripped from https://github.com/gregjones/httpcache/blob/master/httpcache.go
 575  type cacheControl map[string]string
 576  
 577  func parseCacheControl(headers http.Header) cacheControl {
 578  	cc := cacheControl{}
 579  	ccHeader := headers.Get("Cache-Control")
 580  	for _, part := range strings.Split(ccHeader, ",") {
 581  		part = strings.Trim(part, " ")
 582  		if part == "" {
 583  			continue
 584  		}
 585  		if strings.ContainsRune(part, '=') {
 586  			keyval := strings.Split(part, "=")
 587  			cc[strings.Trim(keyval[0], " ")] = strings.Trim(keyval[1], ",")
 588  		} else {
 589  			cc[part] = ""
 590  		}
 591  	}
 592  	return cc
 593  }
 594  
 595  // CacheExpires helper function to determine remaining time before repeating a request.
 596  func CacheExpires(r *http.Response) time.Time {
 597  	// Figure out when the cache expires.
 598  	var expires time.Time
 599  	now, err := time.Parse(time.RFC1123, r.Header.Get("date"))
 600  	if err != nil {
 601  		return time.Now()
 602  	}
 603  	respCacheControl := parseCacheControl(r.Header)
 604  
 605  	if maxAge, ok := respCacheControl["max-age"]; ok {
 606  		lifetime, err := time.ParseDuration(maxAge + "s")
 607  		if err != nil {
 608  			expires = now
 609  		} else {
 610  			expires = now.Add(lifetime)
 611  		}
 612  	} else {
 613  		expiresHeader := r.Header.Get("Expires")
 614  		if expiresHeader != "" {
 615  			expires, err = time.Parse(time.RFC1123, expiresHeader)
 616  			if err != nil {
 617  				expires = now
 618  			}
 619  		}
 620  	}
 621  	return expires
 622  }
 623  
 624  func strlen(s string) int {
 625  	return utf8.RuneCountInString(s)
 626  }
 627  
 628  // GenericOpenAPIError Provides access to the body, error and model on returned errors.
 629  type GenericOpenAPIError struct {
 630  	body  []byte
 631  	error string
 632  	model interface{}
 633  }
 634  
 635  // Error returns non-empty string if there was an error.
 636  func (e GenericOpenAPIError) Error() string {
 637  	return e.error
 638  }
 639  
 640  // Body returns the raw bytes of the response
 641  func (e GenericOpenAPIError) Body() []byte {
 642  	return e.body
 643  }
 644  
 645  // Model returns the unpacked model of the error
 646  func (e GenericOpenAPIError) Model() interface{} {
 647  	return e.model
 648  }
 649  
 650  // format error message using title and detail when model implements rfc7807
 651  func formatErrorMessage(status string, v interface{}) string {
 652  	str := ""
 653  	metaValue := reflect.ValueOf(v).Elem()
 654  
 655  	if metaValue.Kind() == reflect.Struct {
 656  		field := metaValue.FieldByName("Title")
 657  		if field != (reflect.Value{}) {
 658  			str = fmt.Sprintf("%s", field.Interface())
 659  		}
 660  
 661  		field = metaValue.FieldByName("Detail")
 662  		if field != (reflect.Value{}) {
 663  			str = fmt.Sprintf("%s (%s)", str, field.Interface())
 664  		}
 665  	}
 666  
 667  	return strings.TrimSpace(fmt.Sprintf("%s %s", status, str))
 668  }
 669