8.5 KiB
Client Configuration
The UniFi Go SDK client is highly configurable to cater to different needs and environments. This document explains the various configuration options available in the client.
Authentication Methods
The client supports two authentication protocols:
API Key Authentication
Use this method for better security and dedicated access. Example:
c, err := unifi.NewClient(&unifi.ClientConfig{
BaseURL: "https://unifi.localdomain",
APIKey: "your-api-key",
})
if err != nil {
log.Fatalf("Error creating client: %v", err)
}
Username/Password Authentication
Alternatively, you can use username and password:
c, err := unifi.NewClient(&unifi.ClientConfig{
BaseURL: "https://unifi.localdomain",
Username: "your-username",
Password: "your-password",
RememberMe: true, // Optional: prolong the session validity. Might be needed for long-running applications.
})
if err != nil {
log.Fatalf("Error creating client: %v", err)
}
Validation Modes
The client has three modes of validation for the API models. The modes help to ensure that the data sent to the controller is correct.
- Soft Validation (
unifi.SoftValidation): Logs warnings for invalid fields, but does not fail the request (default). - Hard Validation (
unifi.HardValidation): Returns an error for invalid fields, preventing the request from being sent. - Disable Validation (
unifi.DisableValidation): Disables all validations.
Configure the validation mode as follows:
c, err := unifi.NewClient(&unifi.ClientConfig{
BaseURL: "https://unifi.localdomain",
APIKey: "your-api-key",
ValidationMode: unifi.HardValidation,
})
if err != nil {
log.Fatalf("Error creating client: %v", err)
}
Customizing the HTTP Client
There are two ways to customize the HTTP client used by the UniFi client:
- Using the
HttpTransportCustomizer. - Using the
HttpRoundTripperProvider.
Those methods are mutually exclusive, and only one can be used at a time. If both are provided, the HttpRoundTripperProvider takes precedence,
unless it returns nil, in which case the HttpTransportCustomizer is used if defined (or default transport is used).
Using HttpTransportCustomizer
You can provide your own HTTP client transport configuration using the HttpTransportCustomizer callback. This is useful if you need to tweak connection settings like timeouts, idle connection settings,
or TLS configurations:
c, err := unifi.NewClient(&unifi.ClientConfig{
BaseURL: "https://unifi.localdomain",
APIKey: "your-api-key",
HttpTransportCustomizer: func(transport *http.Transport) (*http.Transport, error) {
transport.MaxIdleConns = 10
// Customize TLS settings, proxy, etc. as needed
// You can also create new instance of transport and return it, instead of customizing pre-configured
return transport, nil
},
})
if err != nil {
log.Fatalf("Error creating client: %v", err)
}
Using HttpRoundTripperProvider
You can provide your own HTTP client configuration using the HttpRoundTripperProvider callback. This is useful if you need to create a custom round tripper, when http.Transport is not enough:
c, err := unifi.NewClient(&unifi.ClientConfig{
BaseURL: "https://unifi.localdomain",
APIKey: "your-api-key",
HttpRoundTripperProvider: func() http.RoundTripper {
// Create a custom HTTP Round Tripper instance
return &http.Transport{}, nil
},
})
Using Interceptors
Interceptors let you hook into the request and response flow. They can be used for logging, metrics, or modifying requests/responses.
Implement the ClientInterceptor interface:
// LoggingInterceptor logs each request and response
type LoggingInterceptor struct{}
func (l *LoggingInterceptor) InterceptRequest(req *http.Request) error {
log.Printf("Request: %s %s", req.Method, req.URL)
return nil
}
func (l *LoggingInterceptor) InterceptResponse(resp *http.Response) error {
log.Printf("Response status: %d", resp.StatusCode)
return nil
}
c, err := unifi.NewClient(&unifi.ClientConfig{
BaseURL: "https://unifi.localdomain",
APIKey: "your-api-key",
Interceptors: []unifi.ClientInterceptor{&LoggingInterceptor{}},
})
if err != nil {
log.Fatalf("Error creating client: %v", err)
}
This flexibility allows you to modify client behavior to suit your application's needs.
Comprehensive Client Configuration Example
The ClientConfig struct is the central configuration for initializing the UniFi client. It allows you to
fine-tune every aspect of the client's behavior such as the controller URL, authentication credentials, HTTP timeout,
SSL verification, custom HTTP transport settings, interceptors, error handling, concurrency locking, and request validation modes.
Below is a full example demonstrating how to configure and use all available properties of ClientConfig when
initializing the client with unifi.NewClient:
package main
import (
"context"
"crypto/tls"
"fmt"
"log"
"net/http"
"time"
"github.com/filipowm/go-unifi/unifi"
)
// customTransportCustomizer customizes the HTTP transport, e.g., setting idle connection limits and TLS options.
func customTransportCustomizer(transport *http.Transport) (*http.Transport, error) {
transport.MaxIdleConns = 50
transport.IdleConnTimeout = 120 * time.Second
// Set a custom TLS configuration
transport.TLSClientConfig = &tls.Config{
MinVersion: tls.VersionTLS12,
}
return transport, nil
}
// myErrorHandler implements a custom error handler for HTTP responses.
type myErrorHandler struct{}
func (h *myErrorHandler) HandleError(resp *http.Response) error {
if resp.StatusCode >= 400 {
return fmt.Errorf("custom error: received status code %d", resp.StatusCode)
}
return nil
}
// customInterceptor is a simple interceptor that adds a custom header to each request.
type customInterceptor struct{}
func (ci *customInterceptor) InterceptRequest(req *http.Request) error {
req.Header.Set("X-Custom-Header", "CustomValue")
return nil
}
func (ci *customInterceptor) InterceptResponse(resp *http.Response) error {
// Additional response processing can be added here if needed.
return nil
}
func main() {
// Create a comprehensive client configuration.
config := &unifi.ClientConfig{
URL: "https://unifi.example.com", // Base URL of the UniFi controller (without trailing '/api')
APIKey: "your-api-key", // API key for authentication. Alternatively, use User and Pass for user/password auth.
// User: "username", // Uncomment and provide if using user/password authentication
// Password: "password", // Uncomment and provide if using user/password authentication
Timeout: 30 * time.Second, // Maximum duration to wait for a response
VerifySSL: true, // Enable SSL certificate verification
Interceptors: []unifi.ClientInterceptor{&customInterceptor{}}, // Custom interceptors for request/response manipulation
HttpTransportCustomizer: customTransportCustomizer, // Function to customize the underlying HTTP transport
UserAgent: "MyCustomAgent/1.0", // Custom User-Agent string
ErrorHandler: &myErrorHandler{}, // Custom error handler for processing HTTP response errors
UseLocking: true, // Enable internal locking for safe concurrent request processing
ValidationMode: unifi.SoftValidation, // Validation mode: SoftValidation, HardValidation, or DisableValidation
}
// Initialize the UniFi client with the specified configuration.
client, err := unifi.NewClient(config)
if err != nil {
log.Fatalf("Error creating UniFi client: %v", err)
}
// Example operation: Retrieve system information from the UniFi controller.
sysInfo, err := client.GetSystemInformation()
if err != nil {
log.Fatalf("Error retrieving system information: %v", err)
}
log.Printf("Connected to UniFi Controller version: %s", sysInfo.Version)
// Further client operations can be performed using the 'client' instance.
// For example: creating networks, retrieving device information, etc.
}
This example demonstrates how to utilize the full range of configuration options provided by ClientConfig to create
a highly customizable UniFi client.