Files
cloudpods/pkg/aiproxy/ft/httpclient.go
T
Zexi Li 167682c39b feat(aiproxy): add Anthropic Messages API and migrate functional tests to Go (#25107)
Add /v1/messages handler with Anthropic-to-OpenAI translation, upstream
failover, and probe endpoints. Replace shell-based functional test scripts
with pkg/aiproxy/ft and climc test commands; consolidate documentation.
2026-07-07 20:13:14 +08:00

93 lines
2.5 KiB
Go

// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ft
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/mcclient"
)
func httpClientFromSession(session *mcclient.ClientSession) *http.Client {
return session.GetClient().GetClient()
}
func postJSON(client *http.Client, url, bearer string, payload interface{}) (int, []byte, error) {
body, err := json.Marshal(payload)
if err != nil {
return 0, nil, err
}
req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(body))
if err != nil {
return 0, nil, err
}
req.Header.Set("Authorization", "Bearer "+bearer)
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
return 0, nil, err
}
defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return resp.StatusCode, nil, err
}
return resp.StatusCode, respBody, nil
}
func postJSONStream(client *http.Client, url, bearer string, payload interface{}) (int, io.ReadCloser, error) {
body, err := json.Marshal(payload)
if err != nil {
return 0, nil, err
}
req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(body))
if err != nil {
return 0, nil, err
}
req.Header.Set("Authorization", "Bearer "+bearer)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "text/event-stream")
resp, err := client.Do(req)
if err != nil {
return 0, nil, err
}
if resp.StatusCode != http.StatusOK {
defer resp.Body.Close()
b, _ := io.ReadAll(resp.Body)
return resp.StatusCode, nil, errors.Errorf("HTTP %d: %s", resp.StatusCode, truncateBody(b))
}
return resp.StatusCode, resp.Body, nil
}
func openAIChatURL(baseURL string) string {
return strings.TrimRight(baseURL, "/") + "/ai/openai/v1/chat/completions"
}
func anthropicMessagesURL(baseURL string) string {
return strings.TrimRight(baseURL, "/") + "/ai/anthropic/v1/messages"
}
func Step(msg string) {
fmt.Println()
fmt.Println("==>", msg)
}