Documentation
¶
Overview ¶
Package nethttp provides a middleware for the net/http package, which adds multi-tenancy support.
Example usage:
import (
"net/http"
nethttpmw "github.com/bartventer/gorm-multitenancy/v6/middleware/nethttp"
"github.com/bartventer/gorm-multitenancy/v6/tenantcontext"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
tenant := r.Context().Value(tenantcontext.TenantKey).(string)
fmt.Fprintf(w, "Hello, %s", tenant)
})
handler := nethttpmw.WithTenant(nethttpmw.DefaultWithTenantConfig)(mux)
http.ListenAndServe(":8080", handler)
}
Index ¶
- Constants
- Variables
- func DefaultSkipper(r *http.Request) bool
- func DefaultTenantFromHeader(r *http.Request) (string, error)
- func DefaultTenantFromSubdomain(r *http.Request) (string, error)
- func ExtractSubdomain(domainURL string) (string, error)
- func WithTenant(config WithTenantConfig) func(http.Handler) http.Handler
- type WithTenantConfig
Examples ¶
Constants ¶
const (
// XTenantHeader is the header key for the tenant.
XTenantHeader = "X-Tenant"
)
Variables ¶
var ( // DefaultWithTenantConfig is the default configuration for the WithTenant middleware. // It uses the default skipper, tenant getters, context key, and error handler. DefaultWithTenantConfig = WithTenantConfig{ Skipper: DefaultSkipper, TenantGetters: []func(r *http.Request) (string, error){ DefaultTenantFromSubdomain, DefaultTenantFromHeader, }, ContextKey: tenantcontext.TenantKey, ErrorHandler: func(w http.ResponseWriter, r *http.Request, _ error) { http.Error(w, ErrTenantInvalid.Error(), http.StatusInternalServerError) }, } )
var ( // ErrTenantInvalid represents an error when the tenant is invalid or not found. ErrTenantInvalid = errors.New("invalid tenant or tenant not found") )
var ( // TenantKey is the key that holds the tenant in a request context. TenantKey = tenantcontext.TenantKey )
Functions ¶
func DefaultSkipper ¶
DefaultSkipper represents the default skipper.
func DefaultTenantFromHeader ¶
DefaultTenantFromHeader extracts the tenant from the XTenantHeader header in the HTTP request. It returns the extracted tenant as a string and an error if the header is empty or missing.
Example ¶
// Create a new HTTP request
req, err := http.NewRequest(http.MethodGet, "http://test.domain.com", nil)
if err != nil {
fmt.Println("Error creating request:", err)
return
}
// Set the XTenantHeader of the request
req.Header.Set(XTenantHeader, "test-tenant")
// Extract the tenant from the request
tenant, err := DefaultTenantFromHeader(req)
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("Tenant:", tenant)
}
Output: Tenant: test-tenant
func DefaultTenantFromSubdomain ¶
DefaultTenantFromSubdomain extracts the subdomain from the given HTTP request's host. It removes the port from the host if present and adds a scheme to the host for parsing. The function then parses the URL and extracts the subdomain. It returns the extracted subdomain as a string and any error encountered during the process.
This function calls the ExtractSubdomain function to extract the subdomain from the host.
Example ¶
// Create a new HTTP request
req, err := http.NewRequest(http.MethodGet, "http://test.domain.com", nil)
if err != nil {
fmt.Println("Error creating request:", err)
return
}
// Set the host of the request
req.Host = "test.domain.com"
// Extract the subdomain from the request
subdomain, err := DefaultTenantFromSubdomain(req)
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("Subdomain:", subdomain)
}
Output: Subdomain: test
func ExtractSubdomain ¶
ExtractSubdomain extracts the first part of the subdomain from a given domain URL. If the URL has multiple subdomains, it only returns the first part.
Example ¶
subdomain, err := ExtractSubdomain("http://test.domain.com")
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("Subdomain:", subdomain)
}
subdomain, err = ExtractSubdomain("http://test.sub.domain.com")
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("Subdomain:", subdomain)
}
Output: Subdomain: test Subdomain: test
func WithTenant ¶
func WithTenant(config WithTenantConfig) func(http.Handler) http.Handler
WithTenant is a middleware function that adds multi-tenancy support to a net/http application. It takes a WithTenantConfig struct as input and returns a http.Handler. The WithTenantConfig struct allows customization of the middleware behavior. The middleware checks if the request should be skipped based on the Skipper function. It retrieves the tenant information using the TenantGetters functions. If an error occurs while retrieving the tenant, the ErrorHandler function is called. The retrieved tenant is then set in the request context using the ContextKey. Finally, the SuccessHandler function is called if provided, and the next handler is invoked.
Example ¶
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
tenant := r.Context().Value(tenantcontext.TenantKey).(string)
fmt.Println("Tenant:", tenant)
})
handler := WithTenant(DefaultWithTenantConfig)(mux)
req := httptest.NewRequest(http.MethodGet, "/", nil)
req.Host = "tenant.example.com"
rec := httptest.NewRecorder()
// Execute the request
handler.ServeHTTP(rec, req)
Output: Tenant: tenant
Types ¶
type WithTenantConfig ¶
type WithTenantConfig struct {
// Skipper defines a function to skip the middleware.
Skipper func(r *http.Request) bool
// TenantGetters is a list of functions that retrieve the tenant from the request.
// Each function should return the tenant as a string and an error if any.
// The functions are executed in order until a valid tenant is found.
TenantGetters []func(r *http.Request) (string, error)
// ContextKey is the key used to store the tenant in the context.
ContextKey tenantcontext.ContextKey
// ErrorHandler is a callback function that is called when an error occurs during the tenant retrieval process.
ErrorHandler func(w http.ResponseWriter, r *http.Request, err error)
// SuccessHandler is a callback function that is called after the tenant is successfully set in the http context.
// It can be used to perform additional operations, such as modifying the database connection based on the tenant.
SuccessHandler func(w http.ResponseWriter, r *http.Request)
}
WithTenantConfig represents the configuration options for the tenant middleware in net/http.