httpclient

package
v0.0.24 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 12, 2024 License: MIT Imports: 20 Imported by: 5

Documentation

Overview

api_handler.go

http_client_auth_token_management.go

http_client_bearer_token_auth.go

The http_client_auth package focuses on authentication mechanisms for an HTTP client.

It provides structures and methods for handling both basic and bearer token based authentication

http_client.go

The `http_client` package provides a configurable HTTP client tailored for interacting with specific APIs.

It supports different authentication methods, including "bearer" and "oauth". The client is designed with a focus on concurrency management, structured error handling, and flexible configuration options. The package offers a default timeout, custom backoff strategies, dynamic rate limiting, and detailed logging capabilities. The main `Client` structure encapsulates all necessary components, like the baseURL, authentication details, and an embedded standard HTTP client.

http_concurrency_management.go package httpclient provides utilities to manage HTTP client interactions, including concurrency control. The Concurrency Manager ensures no more than a certain number of concurrent requests (e.g., 5 for Jamf Pro) are sent at the same time. This is managed using a semaphore

http_helpers.go

http_client_oauth.go

The http_client_auth package focuses on authentication mechanisms for an HTTP client.

It provides structures and methods for handling OAuth-based authentication

http_request.go

sdk_version.go

Index

Constants

View Source
const (
	MaxConcurrency     = 10              // Maximum allowed concurrent requests
	MinConcurrency     = 1               // Minimum allowed concurrent requests
	EvaluationInterval = 1 * time.Minute // Time interval for evaluating metrics and adjusting concurrency
)
View Source
const (
	DefaultLogLevel                  = logger.LogLevelInfo
	DefaultMaxRetryAttempts          = 3
	DefaultEnableDynamicRateLimiting = true
	DefaultMaxConcurrentRequests     = 5
	DefaultTokenBufferPeriod         = 5 * time.Minute
	DefaultTotalRetryDuration        = 5 * time.Minute
	DefaultTimeout                   = 10 * time.Second
)
View Source
const (
	SDKVersion    = "0.0.8"
	UserAgentBase = "go-api-http-client"
)

Variables

This section is empty.

Functions

func CheckDeprecationHeader

func CheckDeprecationHeader(resp *http.Response, log logger.Logger)

CheckDeprecationHeader checks the response headers for the Deprecation header and logs a warning if present.

func DetermineAuthMethod added in v0.0.9

func DetermineAuthMethod(authConfig AuthConfig) (string, error)

DetermineAuthMethod determines the authentication method based on the provided credentials. It prefers strong authentication methods (e.g., OAuth) over weaker ones (e.g., bearer tokens). It logs an error and returns "unknown" if no valid credentials are provided.

func GetUserAgentHeader

func GetUserAgentHeader() string

func HeadersToString

func HeadersToString(headers http.Header) string

HeadersToString converts an http.Header map to a single string representation.

func IsValidClientID added in v0.0.9

func IsValidClientID(clientID string) (bool, string)

IsValidClientID checks if the provided client ID is a valid UUID. Returns true if valid, along with an empty error message; otherwise, returns false with an error message.

func IsValidClientSecret added in v0.0.9

func IsValidClientSecret(clientSecret string) (bool, string)

IsValidClientSecret checks if the provided client secret meets your application's validation criteria. Returns true if valid, along with an empty error message; otherwise, returns false with an error message.

func IsValidPassword added in v0.0.9

func IsValidPassword(password string) (bool, string)

IsValidPassword checks if the provided password meets your application's validation criteria. Returns true if valid, along with an empty error message; otherwise, returns false with an error message.

func IsValidUsername added in v0.0.9

func IsValidUsername(username string) (bool, string)

IsValidUsername checks if the provided username meets your application's validation criteria. Returns true if valid, along with an empty error message; otherwise, returns false with an error message.

func Min

func Min(a, b int) int

Min returns the smaller of the two integers.

func ParseISO8601Date

func ParseISO8601Date(dateStr string) (time.Time, error)

ParseISO8601Date attempts to parse a string date in ISO 8601 format.

func RedactSensitiveData added in v0.0.13

func RedactSensitiveData(client *Client, key string, value string) string

RedactSensitiveData redacts sensitive data if the HideSensitiveData flag is set to true.

Types

type APIHandler

type APIHandler interface {
	ConstructAPIResourceEndpoint(instanceName string, endpointPath string, log logger.Logger) string
	ConstructAPIAuthEndpoint(instanceName string, endpointPath string, log logger.Logger) string
	MarshalRequest(body interface{}, method string, endpoint string, log logger.Logger) ([]byte, error)
	MarshalMultipartRequest(fields map[string]string, files map[string]string, log logger.Logger) ([]byte, string, error)
	UnmarshalResponse(resp *http.Response, out interface{}, log logger.Logger) error
	GetContentTypeHeader(method string, log logger.Logger) string
	//GetAcceptHeader() string
	GetDefaultBaseDomain() string
	GetOAuthTokenEndpoint() string
	GetBearerTokenEndpoint() string
	GetTokenRefreshEndpoint() string
	GetTokenInvalidateEndpoint() string
	GetAPIBearerTokenAuthenticationSupportStatus() bool
	GetAPIOAuthAuthenticationSupportStatus() bool
	GetAPIOAuthWithCertAuthenticationSupportStatus() bool
}

APIHandler is an interface for encoding, decoding, and implenting contexual api functions for different API implementations. It encapsulates behavior for encoding and decoding requests and responses.

func LoadAPIHandler

func LoadAPIHandler(apiType string, log logger.Logger) (APIHandler, error)

LoadAPIHandler returns an APIHandler based on the provided API type. 'apiType' parameter could be "jamf" or "graph" to specify which API handler to load.

type AuthConfig

type AuthConfig struct {
	Username     string `json:"Username,omitempty"`
	Password     string `json:"Password,omitempty"`
	ClientID     string `json:"ClientID,omitempty"`
	ClientSecret string `json:"ClientSecret,omitempty"`
}

AuthConfig represents the structure to read authentication details from a JSON configuration file.

type BearerTokenAuthCredentials

type BearerTokenAuthCredentials struct {
	Username string
	Password string
}

BearerTokenAuthCredentials represents the username and password for basic authentication.

type Client

type Client struct {
	APIHandler                 APIHandler                 // APIHandler interface used to define which API handler to use
	InstanceName               string                     // Website Instance name without the root domain
	AuthMethod                 string                     // Specifies the authentication method: "bearer" or "oauth"
	Token                      string                     // Authentication Token
	OverrideBaseDomain         string                     // Base domain override used when the default in the api handler isn't suitable
	OAuthCredentials           OAuthCredentials           // ClientID / Client Secret
	BearerTokenAuthCredentials BearerTokenAuthCredentials // Username and Password for Basic Authentication
	Expiry                     time.Time                  // Expiry time set for the auth token

	Logger         logger.Logger
	ConcurrencyMgr *ConcurrencyManager
	PerfMetrics    PerformanceMetrics
	// contains filtered or unexported fields
}

Client represents an HTTP client to interact with a specific API.

func BuildClient

func BuildClient(config ClientConfig) (*Client, error)

BuildClient creates a new HTTP client with the provided configuration.

func (*Client) AdjustConcurrencyBasedOnMetrics

func (c *Client) AdjustConcurrencyBasedOnMetrics()

AdjustConcurrencyBasedOnMetrics evaluates the current metrics and adjusts the concurrency limit if required. It checks metrics like average token acquisition time and decides on a new concurrency limit. The method ensures that the new limit respects the minimum and maximum allowed concurrency bounds.

func (*Client) AverageAcquisitionTime

func (c *Client) AverageAcquisitionTime() time.Duration

Returns the average Acquisition Time to get a token from the semaphore

func (*Client) DoMultipartRequest

func (c *Client) DoMultipartRequest(method, endpoint string, fields map[string]string, files map[string]string, out interface{}, log logger.Logger) (*http.Response, error)

DoMultipartRequest creates and executes a multipart HTTP request. It is used for sending files and form fields in a single request. This method handles the construction of the multipart message body, setting the appropriate headers, and sending the request to the given endpoint.

Parameters: - method: The HTTP method to use (e.g., POST, PUT). - endpoint: The API endpoint to which the request will be sent. - fields: A map of form fields and their values to include in the multipart message. - files: A map of file field names to file paths that will be included as file attachments. - out: A pointer to a variable where the unmarshaled response will be stored.

Returns: - A pointer to the http.Response received from the server. - An error if the request could not be sent or the response could not be processed.

The function first validates the authentication token, then constructs the multipart request body based on the provided fields and files. It then constructs the full URL for the request, sets the required headers (including Authorization and Content-Type), and sends the request.

If debug mode is enabled, the function logs all the request headers before sending the request. After the request is sent, the function checks the response status code. If the response is not within the success range (200-299), it logs an error and returns the response and an error. If the response is successful, it attempts to unmarshal the response body into the 'out' parameter.

Note: The caller should handle closing the response body when successful.

func (*Client) DoRequest

func (c *Client) DoRequest(method, endpoint string, body, out interface{}, log logger.Logger) (*http.Response, error)

DoRequest constructs and executes a standard HTTP request with support for retry logic. It is intended for operations that can be encoded in a single JSON or XML body such as creating or updating resources. This method includes token validation, concurrency control, performance metrics, dynamic header setting, and structured error handling.

Parameters: - method: The HTTP method to use (e.g., GET, POST, PUT, DELETE, PATCH). - endpoint: The API endpoint to which the request will be sent. - body: The payload to send in the request, which will be marshaled based on the API handler rules. - out: A pointer to a variable where the unmarshaled response will be stored.

Returns: - A pointer to the http.Response received from the server. - An error if the request could not be sent, the response could not be processed, or if retry attempts fail.

The function starts by validating the client's authentication token and managing concurrency using a token system. It then determines the appropriate API handler for marshaling the request body and setting headers. The request is sent to the constructed URL with all necessary headers including authorization, content type, and user agent.

If configured for debug logging, the function logs all request headers before sending. The function then enters a loop to handle retryable HTTP methods, implementing a retry mechanism for transient errors, rate limits, and other retryable conditions based on response status codes.

The function also updates performance metrics to track total request count and cumulative response time. After processing the response, it handles any API errors and unmarshals the response body into the provided 'out' parameter if the response is successful.

Note: The function assumes that retryable HTTP methods have been properly defined in the retryableHTTPMethods map. It is the caller's responsibility to close the response body when the request is successful to avoid resource leaks.

func (*Client) EvaluateMetricsAndAdjustConcurrency

func (c *Client) EvaluateMetricsAndAdjustConcurrency()

EvaluateMetricsAndAdjustConcurrency evaluates the performance metrics and makes necessary adjustments to the concurrency limit. The method assesses the average response time and adjusts the concurrency based on how it compares to the historical average acquisition time. If the average response time has significantly increased compared to the historical average, the concurrency limit is decreased, and vice versa. The method ensures that the concurrency limit remains within the bounds defined by the system's best practices.

func (*Client) GetPerformanceMetrics

func (c *Client) GetPerformanceMetrics() *PerformanceMetrics

Returns performance metrics from the http client

func (*Client) HistoricalAverageAcquisitionTime

func (c *Client) HistoricalAverageAcquisitionTime() time.Duration

func (*Client) ObtainOAuthToken

func (c *Client) ObtainOAuthToken(credentials AuthConfig, log logger.Logger) error

ObtainOAuthToken fetches an OAuth access token using the provided OAuthCredentials (Client ID and Client Secret). It updates the client's Token and Expiry fields with the obtained values.

func (*Client) ObtainToken

func (c *Client) ObtainToken(log logger.Logger) error

ObtainToken fetches and sets an authentication token using the stored basic authentication credentials.

func (*Client) RefreshToken

func (c *Client) RefreshToken(log logger.Logger) error

RefreshToken refreshes the current authentication token.

func (*Client) SetBearerTokenAuthCredentials

func (c *Client) SetBearerTokenAuthCredentials(credentials BearerTokenAuthCredentials)

SetBearerTokenAuthCredentials sets the BearerTokenAuthCredentials (Username and Password) for the client instance. These credentials are used for obtaining and refreshing bearer tokens for authentication.

func (*Client) SetOAuthCredentials

func (c *Client) SetOAuthCredentials(credentials OAuthCredentials)

SetOAuthCredentials sets the OAuth credentials (Client ID and Client Secret) for the client instance. These credentials are used for obtaining and refreshing OAuth tokens for authentication.

func (*Client) StartConcurrencyAdjustment

func (c *Client) StartConcurrencyAdjustment()

StartConcurrencyAdjustment launches a periodic checker that evaluates current metrics and adjusts concurrency limits if needed. It uses a ticker to periodically trigger the adjustment logic.

func (*Client) StartMetricEvaluation

func (c *Client) StartMetricEvaluation()

StartMetricEvaluation continuously monitors the client's interactions with the API and adjusts the concurrency limits dynamically. The function evaluates metrics at regular intervals to detect burst activity patterns. If a burst activity is detected (e.g., many requests in a short period), the evaluation interval is reduced for more frequent checks. Otherwise, it reverts to a default interval for regular checks. After each evaluation, the function calls EvaluateMetricsAndAdjustConcurrency to potentially adjust the concurrency based on observed metrics.

The evaluation process works as follows: 1. Sleep for the defined evaluation interval. 2. Check if there's a burst in activity using the isBurstActivity method. 3. If a burst is detected, the evaluation interval is shortened to more frequently monitor and adjust the concurrency. 4. If no burst is detected, it maintains the default evaluation interval. 5. It then evaluates the metrics and adjusts the concurrency accordingly.

func (*Client) ValidAuthTokenCheck

func (c *Client) ValidAuthTokenCheck(log logger.Logger) (bool, error)

ValidAuthTokenCheck checks if the current token is valid and not close to expiry. If the token is invalid, it tries to refresh it. It returns a boolean indicating the validity of the token and an error if there's a failure.

type ClientConfig added in v0.0.12

type ClientConfig struct {
	Auth          AuthConfig        // User can either supply these values manually or pass from LoadAuthConfig/Env vars
	Environment   EnvironmentConfig // User can either supply these values manually or pass from LoadAuthConfig/Env vars
	ClientOptions ClientOptions     // Optional configuration options for the HTTP Client
}

Config holds configuration options for the HTTP Client.

type ClientOptions added in v0.0.12

type ClientOptions struct {
	LogLevel                  string // Field for defining tiered logging level.
	LogOutputFormat           string // Field for defining the output format of the logs. Use "JSON" for JSON format, "console" for human-readable format
	HideSensitiveData         bool   // Field for defining whether sensitive fields should be hidden in logs.
	MaxRetryAttempts          int    // Config item defines the max number of retry request attempts for retryable HTTP methods.
	EnableDynamicRateLimiting bool   // Field for defining whether dynamic rate limiting should be enabled.
	MaxConcurrentRequests     int    // Field for defining the maximum number of concurrent requests allowed in the semaphore
	TokenRefreshBufferPeriod  time.Duration
	TotalRetryDuration        time.Duration
	CustomTimeout             time.Duration
}

ClientOptions holds optional configuration options for the HTTP Client.

type ConcurrencyManager

type ConcurrencyManager struct {
	AcquisitionTimes []time.Duration
	// contains filtered or unexported fields
}

ConcurrencyManager controls the number of concurrent HTTP requests.

func NewConcurrencyManager

func NewConcurrencyManager(limit int, logger logger.Logger, debugMode bool) *ConcurrencyManager

NewConcurrencyManager initializes a new ConcurrencyManager with the given concurrency limit, logger, and debug mode. The ConcurrencyManager ensures no more than a certain number of concurrent requests are made. It uses a semaphore to control concurrency.

func (*ConcurrencyManager) Acquire

func (c *ConcurrencyManager) Acquire(ctx context.Context) (uuid.UUID, error)

Acquire attempts to get a token to allow an HTTP request to proceed. It blocks until a token is available or the context expires. Returns a unique request ID upon successful acquisition.

func (*ConcurrencyManager) AdjustConcurrencyLimit

func (c *ConcurrencyManager) AdjustConcurrencyLimit(newLimit int)

AdjustConcurrencyLimit dynamically modifies the maximum concurrency limit based on the newLimit provided. This function helps in adjusting the concurrency limit in real-time based on observed system performance and other metrics. It transfers the tokens from the old semaphore to the new one, ensuring that there's no loss of tokens during the transition.

func (*ConcurrencyManager) AverageAcquisitionTime

func (c *ConcurrencyManager) AverageAcquisitionTime() time.Duration

AverageAcquisitionTime computes the average time taken to acquire a token from the semaphore. It helps in understanding the contention for tokens and can be used to adjust concurrency limits.

func (*ConcurrencyManager) HistoricalAverageAcquisitionTime

func (c *ConcurrencyManager) HistoricalAverageAcquisitionTime() time.Duration

HistoricalAverageAcquisitionTime computes the average time taken to acquire a token from the semaphore over a historical period (e.g., the last 5 minutes). It helps in understanding the historical contention for tokens and can be used to adjust concurrency limits.

func (*ConcurrencyManager) Release

func (c *ConcurrencyManager) Release(requestID uuid.UUID)

Release returns a token back to the pool, allowing other requests to proceed. It uses the provided requestID for logging and debugging purposes.

type EnvironmentConfig added in v0.0.5

type EnvironmentConfig struct {
	InstanceName       string `json:"InstanceName,omitempty"`
	OverrideBaseDomain string `json:"OverrideBaseDomain,omitempty"`
	APIType            string `json:"APIType,omitempty"`
}

EnvironmentConfig represents the structure to read authentication details from a JSON configuration file.

type OAuthCredentials

type OAuthCredentials struct {
	ClientID     string
	ClientSecret string
}

OAuthCredentials contains the client ID and client secret required for OAuth authentication.

type OAuthResponse

type OAuthResponse struct {
	AccessToken  string `json:"access_token"`
	ExpiresIn    int64  `json:"expires_in"`
	TokenType    string `json:"token_type"`
	RefreshToken string `json:"refresh_token,omitempty"`
	Error        string `json:"error,omitempty"`
}

OAuthResponse represents the response structure when obtaining an OAuth access token.

type PerformanceMetrics

type PerformanceMetrics struct {
	TotalRequests        int64
	TotalRetries         int64
	TotalRateLimitErrors int64
	TotalResponseTime    time.Duration
	TokenWaitTime        time.Duration
	// contains filtered or unexported fields
}

ClientPerformanceMetrics captures various metrics related to the client's interactions with the API, providing insights into its performance and behavior.

type TokenResponse

type TokenResponse struct {
	Token   string    `json:"token"`
	Expires time.Time `json:"expires"`
}

TokenResponse represents the structure of a token response from the API.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL