Feature 08 task 2: OpenAI-compatible adapter #35

2 changed files with 9 additions and 7 deletions
Showing only changes of commit 095c03f112 - Show all commits
+7 -5
View File
@@ -90,8 +90,8 @@ func New(cfg Config) (*Provider, error) {
if u.User != nil || strings.ContainsAny(cfg.BaseURL, "?#") { if u.User != nil || strings.ContainsAny(cfg.BaseURL, "?#") {
return nil, errors.New("openai: base URL must not carry credentials, a query or a fragment") return nil, errors.New("openai: base URL must not carry credentials, a query or a fragment")
} }
// Every other error that names caller-supplied text has the API key // An error that names caller-supplied text has the API key redacted from
// redacted from that text before it is quoted. // it before it is quoted.
switch cfg.StructuredOutput { switch cfg.StructuredOutput {
case JSONSchema, JSONObject, PromptOnly: case JSONSchema, JSONObject, PromptOnly:
default: default:
@@ -99,8 +99,10 @@ func New(cfg Config) (*Provider, error) {
} }
headers := make(http.Header, len(cfg.Headers)+1) headers := make(http.Header, len(cfg.Headers)+1)
for name, value := range cfg.Headers { for name, value := range cfg.Headers {
// Invalid names and all values are never echoed: either may carry a // Caller-supplied names and values are never echoed: either may carry
// credential. // a credential, and canonicalising a name changes its case, which
// defeats redaction. Only a managed name, which is a fixed known
// string, is named.
if !validHeaderName(name) { if !validHeaderName(name) {
return nil, errors.New("openai: an extra header name is not a valid HTTP token") return nil, errors.New("openai: an extra header name is not a valid HTTP token")
} }
@@ -109,7 +111,7 @@ func New(cfg Config) (*Provider, error) {
return nil, fmt.Errorf("openai: extra header %q is set by the adapter", canonical) return nil, fmt.Errorf("openai: extra header %q is set by the adapter", canonical)
} }
if !validHeaderValue(value) { if !validHeaderValue(value) {
return nil, fmt.Errorf("openai: extra header %q has a control character in its value", redactKey(canonical, cfg.APIKey)) return nil, errors.New("openai: an extra header value has a control character")
} }
headers.Set(canonical, value) headers.Set(canonical, value)
} }
+2 -2
View File
@@ -373,7 +373,7 @@ func TestVerify(t *testing.T) {
func assertNoSecret(t *testing.T, err error) { func assertNoSecret(t *testing.T, err error) {
t.Helper() t.Helper()
for _, secret := range []string{testKey, "Bearer " + testKey, testKey[:12]} { for _, secret := range []string{testKey, "Bearer " + testKey, testKey[:12]} {
if strings.Contains(err.Error(), secret) { if strings.Contains(strings.ToLower(err.Error()), strings.ToLower(secret)) {
t.Fatalf("error leaks %q: %v", secret, err) t.Fatalf("error leaks %q: %v", secret, err)
} }
} }
@@ -633,7 +633,7 @@ func TestNewConfigErrorsNeverLeakKey(t *testing.T) {
cases := map[string]Config{ cases := map[string]Config{
"key in invalid header name": {Headers: map[string]string{"Bearer " + testKey: "a"}}, "key in invalid header name": {Headers: map[string]string{"Bearer " + testKey: "a"}},
"key as invalid header name": {Headers: map[string]string{testKey + ":": "a"}}, "key as invalid header name": {Headers: map[string]string{testKey + ":": "a"}},
"key in name, bad value": {Headers: map[string]string{"X-" + testKey: "a\nb"}}, "key in name, bad value": {Headers: map[string]string{"x-" + testKey: "a\nb"}},
"key in structured output": {StructuredOutput: StructuredOutput("Bearer " + testKey)}, "key in structured output": {StructuredOutput: StructuredOutput("Bearer " + testKey)},
"key with quote in mode": {StructuredOutput: StructuredOutput(testKey + "\"\x00")}, "key with quote in mode": {StructuredOutput: StructuredOutput(testKey + "\"\x00")},
} }