Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions core/providers/mistral/mistral.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,11 +321,11 @@ func (provider *MistralProvider) Transcription(ctx context.Context, key schemas.
var mistralResponse MistralTranscriptionResponse
if err := sonic.Unmarshal(copiedResponseBody, &mistralResponse); err != nil {
if providerUtils.IsHTMLResponse(resp, copiedResponseBody) {
errorMessage := providerUtils.ExtractHTMLErrorMessage(copiedResponseBody)
return nil, &schemas.BifrostError{
IsBifrostError: false,
Error: &schemas.ErrorField{
Message: errorMessage,
Message: schemas.ErrProviderResponseHTML,
Error: errors.New(string(copiedResponseBody)),
},
}
}
Expand Down
4 changes: 2 additions & 2 deletions core/providers/openai/openai.go
Original file line number Diff line number Diff line change
Expand Up @@ -2006,11 +2006,11 @@ func HandleOpenAITranscriptionRequest(
if err := sonic.Unmarshal(copiedResponseBody, response); err != nil {
// Check if it's an HTML response
if providerUtils.IsHTMLResponse(resp, copiedResponseBody) {
errorMessage := providerUtils.ExtractHTMLErrorMessage(copiedResponseBody)
return nil, &schemas.BifrostError{
IsBifrostError: false,
Error: &schemas.ErrorField{
Message: errorMessage,
Message: schemas.ErrProviderResponseHTML,
Error: errors.New(string(copiedResponseBody)),
},
}
}
Expand Down
8 changes: 4 additions & 4 deletions core/providers/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -357,12 +357,12 @@ func HandleProviderAPIError(resp *fasthttp.Response, errorResp any) *schemas.Bif

// JSON parsing failed - now check if it's an HTML response (expensive operation)
if IsHTMLResponse(resp, decodedBody) {
errorMessage := ExtractHTMLErrorMessage(decodedBody)
return &schemas.BifrostError{
IsBifrostError: false,
StatusCode: &statusCode,
Error: &schemas.ErrorField{
Message: errorMessage,
Message: schemas.ErrProviderResponseHTML,
Error: errors.New(string(decodedBody)),
},
}
}
Expand Down Expand Up @@ -435,12 +435,11 @@ func HandleProviderResponse[T any](responseBody []byte, response *T, requestBody
if structuredErr != nil {
// JSON parsing failed - check if it's an HTML response (expensive operation)
if IsHTMLResponse(nil, responseBody) {
errorMessage := ExtractHTMLErrorMessage(responseBody)
return nil, nil, &schemas.BifrostError{
IsBifrostError: false,
Error: &schemas.ErrorField{
Message: schemas.ErrProviderResponseHTML,
Error: errors.New(errorMessage),
Error: errors.New(string(responseBody)),
},
}
}
Expand Down Expand Up @@ -594,6 +593,7 @@ const maxBodySize = 32 * 1024 // 32KB

// ExtractHTMLErrorMessage extracts meaningful error information from an HTML response.
// It attempts to find error messages from title tags, headers, and visible text.
// UNUSED for now but could be useful in the future
func ExtractHTMLErrorMessage(body []byte) string {
if len(body) > maxBodySize {
body = body[:maxBodySize]
Expand Down
5 changes: 3 additions & 2 deletions core/providers/vertex/errors.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package vertex

import (
"errors"
"strings"

"github.com/bytedance/sonic"
Expand Down Expand Up @@ -53,12 +54,12 @@ func parseVertexError(resp *fasthttp.Response, meta *providerUtils.RequestMetada

// Check for HTML error response before attempting JSON parsing
if providerUtils.IsHTMLResponse(resp, decodedBody) {
errorMsg := providerUtils.ExtractHTMLErrorMessage(decodedBody)
bifrostErr := &schemas.BifrostError{
IsBifrostError: false,
StatusCode: schemas.Ptr(resp.StatusCode()),
Error: &schemas.ErrorField{
Message: errorMsg,
Message: schemas.ErrProviderResponseHTML,
Error: errors.New(string(decodedBody)),
},
}
if meta != nil {
Expand Down
26 changes: 10 additions & 16 deletions ui/app/_fallbacks/enterprise/components/api-keys/APIKeysView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ curl --location 'http://localhost:8080/v1/chat/completions'
<Alert variant="default">
<InfoIcon className="text-muted h-4 w-4" />
<AlertDescription>
<p className="text-md text-gray-600">
<p className="text-md text-muted-foreground">
To generate API keys, you need to set up admin username and password first.{" "}
<Link href="/workspace/config/security" className="text-md text-primary underline">
Configure Security Settings
Expand All @@ -67,14 +67,15 @@ curl --location 'http://localhost:8080/v1/chat/completions'
const isInferenceAuthDisabled = bifrostConfig?.auth_config?.disable_auth_on_inference ?? false;

return (
<div className="space-y-4 mx-auto w-full max-w-4xl">
<div className="mx-auto w-full max-w-4xl space-y-4">
<Alert variant="default">
<InfoIcon className="text-muted h-4 w-4" />
<AlertDescription>
<p className="text-md text-gray-600">
<p className="text-md text-muted-foreground">
{isInferenceAuthDisabled ? (
<>
Authentication is currently <strong>disabled for inference API calls</strong>. You can make inference requests without authentication. Dashboard and admin API calls still require Basic auth with your admin credentials encoded in the standard{" "}
Authentication is currently <strong>disabled for inference API calls</strong>. You can make inference requests without
authentication. Dashboard and admin API calls still require Basic auth with your admin credentials encoded in the standard{" "}
<code className="bg-muted rounded px-1 py-0.5 text-sm">username:password</code> format with base64 encoding.
</>
) : (
Expand All @@ -87,30 +88,23 @@ curl --location 'http://localhost:8080/v1/chat/completions'
{!isInferenceAuthDisabled && (
<>
<br />
<p className="text-md text-gray-600">
<p className="text-md text-muted-foreground">
<strong>Example:</strong>
</p>

<div className="relative mt-2 w-full min-w-0 overflow-x-auto">
<Button
variant="ghost"
size="sm"
onClick={() => copyToClipboard(curlExample)}
className="absolute right-2 top-2 h-8 z-10"
>
<Button variant="ghost" size="sm" onClick={() => copyToClipboard(curlExample)} className="absolute top-2 right-2 z-10 h-8">
<Copy className="h-4 w-4" />
</Button>
<pre className="bg-muted min-w-max rounded p-3 pr-12 font-mono text-sm whitespace-pre">
{curlExample}
</pre>
<pre className="bg-muted min-w-max rounded p-3 pr-12 font-mono text-sm whitespace-pre">{curlExample}</pre>
</div>
</>
)}
</AlertDescription>
</Alert>

<ContactUsView
className=" mt-4 rounded-md border px-3 py-8"
className="mt-4 rounded-md border px-3 py-8"
icon={<KeyRound size={48} />}
title="Scope Based API Keys"
description="Need granular access control with scope-based API keys? Enterprise customers can create multiple API keys with specific permissions for different services, teams, or environments."
Expand Down