mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-06 07:48:06 +00:00
feat(terraform-provider): support custom HTTP headers on provider
Allow optional custom_headers on the litellm provider so every API request can carry proxy or gateway headers. x-api-key always wins
This commit is contained in:
parent
33d7e3f862
commit
441ec017da
6 changed files with 68 additions and 6 deletions
|
|
@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- **provider**: Optional `custom_headers` map to send extra HTTP headers on every LiteLLM API request (e.g. proxy or gateway headers). `x-api-key` from `api_key` always takes precedence
|
||||
|
||||
## [0.4.0] - 2026-08-06
|
||||
|
||||
### Fixed
|
||||
|
|
|
|||
|
|
@ -16,6 +16,11 @@ terraform {
|
|||
provider "litellm" {
|
||||
api_base = "https://your-litellm-proxy.com"
|
||||
api_key = var.litellm_api_key
|
||||
|
||||
# Optional: extra headers on every API request (e.g. proxy / gateway auth)
|
||||
custom_headers = {
|
||||
"X-Proxy-Auth" = var.proxy_token
|
||||
}
|
||||
}
|
||||
|
||||
# Basic model configuration
|
||||
|
|
@ -94,6 +99,8 @@ The following arguments are supported in the provider block:
|
|||
|
||||
* `api_base` - (Required) The base URL of your LiteLLM instance. This can also be provided via the `LITELLM_API_BASE` environment variable.
|
||||
* `api_key` - (Required) The API key used to authenticate with LiteLLM. This can also be provided via the `LITELLM_API_KEY` environment variable.
|
||||
* `custom_headers` - (Optional) Map of HTTP headers to include on every request to the LiteLLM API. Useful for proxy or gateway authentication headers. Marked sensitive.
|
||||
* `insecure_skip_verify` - (Optional) Skip TLS certificate verification. Defaults to `false`. Can also be set via `LITELLM_INSECURE_SKIP_VERIFY`.
|
||||
|
||||
## Getting Started
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ type Client struct {
|
|||
APIKey string
|
||||
httpClient *http.Client
|
||||
InsecureSkipVerify bool
|
||||
CustomHeaders map[string]string
|
||||
}
|
||||
|
||||
func NewClient(apiBase, apiKey string, insecureSkipVerify bool) *Client {
|
||||
|
|
@ -29,6 +30,7 @@ func NewClient(apiBase, apiKey string, insecureSkipVerify bool) *Client {
|
|||
APIKey: apiKey,
|
||||
httpClient: &http.Client{Transport: tr},
|
||||
InsecureSkipVerify: insecureSkipVerify,
|
||||
CustomHeaders: map[string]string{},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -280,8 +282,11 @@ func (c *Client) sendRequest(method, path string, body interface{}) (map[string]
|
|||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("x-api-key", c.APIKey)
|
||||
req.Header.Set("accept", "application/json")
|
||||
for k, v := range c.CustomHeaders {
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
req.Header.Set("x-api-key", c.APIKey)
|
||||
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,41 @@
|
|||
package litellm
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSendRequestCustomHeaders(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if got := r.Header.Get("X-Proxy-Auth"); got != "proxy-token" {
|
||||
t.Errorf("X-Proxy-Auth = %q, want %q", got, "proxy-token")
|
||||
}
|
||||
if got := r.Header.Get("X-Request-Source"); got != "terraform" {
|
||||
t.Errorf("X-Request-Source = %q, want %q", got, "terraform")
|
||||
}
|
||||
if got := r.Header.Get("x-api-key"); got != "sk-real-key" {
|
||||
t.Errorf("x-api-key = %q, want configured API key (must not be overridden)", got)
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_ = json.NewEncoder(w).Encode(map[string]interface{}{"ok": true})
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
client := NewClient(srv.URL, "sk-real-key", false)
|
||||
client.CustomHeaders = map[string]string{
|
||||
"X-Proxy-Auth": "proxy-token",
|
||||
"X-Request-Source": "terraform",
|
||||
"x-api-key": "should-not-win",
|
||||
}
|
||||
|
||||
if _, err := client.sendRequest("GET", "/health", nil); err != nil {
|
||||
t.Fatalf("sendRequest: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedactSensitiveDataNestedCredentialValues(t *testing.T) {
|
||||
c := NewClient("http://localhost:4000", "sk-test", false)
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,13 @@ func Provider() *schema.Provider {
|
|||
DefaultFunc: schema.EnvDefaultFunc("LITELLM_INSECURE_SKIP_VERIFY", false),
|
||||
Description: "Skip TLS certificate verification. Only use for development or when using self-signed certificates",
|
||||
},
|
||||
"custom_headers": {
|
||||
Type: schema.TypeMap,
|
||||
Optional: true,
|
||||
Sensitive: true,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
Description: "Optional HTTP headers to include on every request to the LiteLLM API (e.g. proxy or gateway headers)",
|
||||
},
|
||||
},
|
||||
ConfigureFunc: providerConfigure,
|
||||
}
|
||||
|
|
@ -53,11 +60,18 @@ func Provider() *schema.Provider {
|
|||
|
||||
// providerConfigure configures the provider with the given schema data.
|
||||
func providerConfigure(d *schema.ResourceData) (interface{}, error) {
|
||||
config := ProviderConfig{
|
||||
APIBase: d.Get("api_base").(string),
|
||||
APIKey: d.Get("api_key").(string),
|
||||
InsecureSkipVerify: d.Get("insecure_skip_verify").(bool),
|
||||
customHeaders := map[string]string{}
|
||||
if v, ok := d.GetOk("custom_headers"); ok {
|
||||
for k, val := range v.(map[string]interface{}) {
|
||||
customHeaders[k] = val.(string)
|
||||
}
|
||||
}
|
||||
|
||||
return NewClient(config.APIBase, config.APIKey, config.InsecureSkipVerify), nil
|
||||
client := NewClient(
|
||||
d.Get("api_base").(string),
|
||||
d.Get("api_key").(string),
|
||||
d.Get("insecure_skip_verify").(bool),
|
||||
)
|
||||
client.CustomHeaders = customHeaders
|
||||
return client, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ type ProviderConfig struct {
|
|||
APIBase string
|
||||
APIKey string
|
||||
InsecureSkipVerify bool
|
||||
CustomHeaders map[string]string
|
||||
}
|
||||
|
||||
// ErrorResponse represents an error response from the API.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue