feat: publish sanitized custom.97 source
This commit is contained in:
1022 files changed
+69903
-19207
No files matched your search
@@ -79,11 +79,13 @@ type responsesWSControl struct {
|
||||
// Only the request worker reads or changes billing state. Socket readers pass
|
||||
// bounded messages to it; cancellation never performs an independent refund.
|
||||
type responsesWSCallState struct {
|
||||
inbox chan responsesWSMessage
|
||||
controls chan responsesWSControl
|
||||
done chan struct{}
|
||||
terminal *responsesWSMessage
|
||||
closeAfter bool
|
||||
inbox chan responsesWSMessage
|
||||
controls chan responsesWSControl
|
||||
done chan struct{}
|
||||
terminal *responsesWSMessage
|
||||
// A nonzero closeCode ends the connection after this request.
|
||||
closeCode int
|
||||
closeReason string
|
||||
}
|
||||
|
||||
type responsesWSSession struct {
|
||||
@@ -95,6 +97,7 @@ type responsesWSSession struct {
|
||||
requestID string
|
||||
nextEventIndex int
|
||||
workers sync.WaitGroup
|
||||
closeOnce sync.Once
|
||||
|
||||
clientWriteMu sync.Mutex
|
||||
targetWriteMu sync.Mutex
|
||||
@@ -129,7 +132,9 @@ func ResponsesWebSocketHelper(c *gin.Context, client *websocket.Conn, runner Res
|
||||
}
|
||||
client.SetReadLimit(int64(maxMB) << 20)
|
||||
defer func() {
|
||||
s.shutdown()
|
||||
// Unless an earlier shutdown ended the read, the client closed or left.
|
||||
// Gorilla already answered a client close frame, so this tells the upstream.
|
||||
s.shutdown(websocket.CloseNormalClosure, "")
|
||||
s.workers.Wait()
|
||||
}()
|
||||
|
||||
@@ -176,17 +181,20 @@ func ResponsesWebSocketHelper(c *gin.Context, client *websocket.Conn, runner Res
|
||||
func (s *responsesWSSession) runRequest(state *responsesWSCallState, message []byte, envelope responsesWSCreateEvent, streamID string, requestID string) {
|
||||
create, parseErr := normalizeResponsesWSCreateEvent(message, envelope, streamID)
|
||||
var apiErr *types.NewAPIError
|
||||
var upstreamURLs []string
|
||||
defer func() {
|
||||
if recovered := recover(); recovered != nil {
|
||||
apiErr = types.NewError(fmt.Errorf("responses websocket request panic: %v", recovered), types.ErrorCodeBadResponse, types.ErrOptionWithSkipRetry())
|
||||
state.closeAfter = true
|
||||
state.closeCode = websocket.CloseInternalServerErr
|
||||
}
|
||||
// Finish the middleware count before publishing the terminal event. Hold
|
||||
// admission while writing it so an immediate next create cannot race
|
||||
// the current request's release; socket close needs neither lock.
|
||||
// the current request's release. A failing request also shuts down
|
||||
// before that release, so a concurrent upstream close cannot report it
|
||||
// as a normal closure; shutdown itself takes neither lock.
|
||||
outgoing := state.terminal
|
||||
if apiErr != nil {
|
||||
if body, err := buildResponsesWSErrorPayload(envelope.EventID, streamID, apiErr); err == nil {
|
||||
if body, err := buildResponsesWSErrorPayload(envelope.EventID, streamID, apiErr, upstreamURLs...); err == nil {
|
||||
outgoing = &responsesWSMessage{kind: websocket.TextMessage, body: body}
|
||||
}
|
||||
}
|
||||
@@ -194,18 +202,18 @@ func (s *responsesWSSession) runRequest(state *responsesWSCallState, message []b
|
||||
s.stateMu.Lock()
|
||||
if outgoing != nil {
|
||||
if err := s.client.SetWriteDeadline(time.Now().Add(responsesWSWriteTimeout)); err != nil {
|
||||
state.closeAfter = true
|
||||
state.closeCode = websocket.CloseInternalServerErr
|
||||
} else if err := s.client.WriteMessage(outgoing.kind, outgoing.body); err != nil {
|
||||
state.closeAfter = true
|
||||
state.closeCode = websocket.CloseInternalServerErr
|
||||
}
|
||||
}
|
||||
if state.closeCode != 0 {
|
||||
s.shutdown(state.closeCode, state.closeReason)
|
||||
}
|
||||
s.current = nil
|
||||
close(state.done)
|
||||
s.stateMu.Unlock()
|
||||
s.clientWriteMu.Unlock()
|
||||
if state.closeAfter {
|
||||
s.shutdown()
|
||||
}
|
||||
}()
|
||||
request := s.request.Clone(s.ctx)
|
||||
request.Body = io.NopCloser(bytes.NewReader(message))
|
||||
@@ -217,10 +225,12 @@ func (s *responsesWSSession) runRequest(state *responsesWSCallState, message []b
|
||||
}
|
||||
c.Request.Body = io.NopCloser(bytes.NewReader(create.Body))
|
||||
c.Request.ContentLength = int64(len(create.Body))
|
||||
return s.runCall(c, state, create)
|
||||
callErr := s.runCall(c, state, create)
|
||||
upstreamURLs = common.UpstreamAddresses(c)
|
||||
return callErr
|
||||
})
|
||||
if apiErr != nil && (apiErr.StatusCode == http.StatusUnauthorized || apiErr.StatusCode == http.StatusForbidden) {
|
||||
state.closeAfter = true
|
||||
state.closeCode = websocket.ClosePolicyViolation
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,7 +243,7 @@ func (s *responsesWSSession) runCall(c *gin.Context, state *responsesWSCallState
|
||||
defer func() {
|
||||
if recovered := recover(); recovered != nil {
|
||||
apiErr = types.NewError(fmt.Errorf("responses websocket call panic: %v", recovered), types.ErrorCodeBadResponse, types.ErrOptionWithSkipRetry())
|
||||
state.closeAfter = true
|
||||
state.closeCode = websocket.CloseInternalServerErr
|
||||
}
|
||||
if info == nil && modelName != "" {
|
||||
info = &relaycommon.RelayInfo{OriginModelName: modelName, UsingGroup: common.GetContextKeyString(c, appconstant.ContextKeyUsingGroup), StartTime: started}
|
||||
@@ -276,7 +286,7 @@ func (s *responsesWSSession) runCall(c *gin.Context, state *responsesWSCallState
|
||||
return apiErr
|
||||
}
|
||||
if err := s.writeTarget(websocket.TextMessage, payload); err != nil {
|
||||
state.closeAfter = true
|
||||
state.closeCode = websocket.CloseInternalServerErr
|
||||
return types.NewError(err, types.ErrorCodeBadResponse, types.ErrOptionWithSkipRetry())
|
||||
}
|
||||
} else {
|
||||
@@ -337,7 +347,7 @@ func (s *responsesWSSession) runCall(c *gin.Context, state *responsesWSCallState
|
||||
return types.NewError(context.Canceled, types.ErrorCodeBadResponse, types.ErrOptionWithSkipRetry())
|
||||
}
|
||||
if err := s.writeTarget(websocket.TextMessage, payload); err != nil {
|
||||
state.closeAfter = true
|
||||
state.closeCode = websocket.CloseInternalServerErr
|
||||
return types.NewError(err, types.ErrorCodeBadResponse, types.ErrOptionWithSkipRetry())
|
||||
}
|
||||
s.lockedModel, s.lockedChannelID, s.lockedGroup = modelName, channel.Id, info.UsingGroup
|
||||
@@ -350,6 +360,7 @@ func (s *responsesWSSession) runCall(c *gin.Context, state *responsesWSCallState
|
||||
appconstant.ContextKeyChannelParamOverride, appconstant.ContextKeyChannelHeaderOverride, appconstant.ContextKeyChannelOrganization,
|
||||
appconstant.ContextKeyChannelAutoBan, appconstant.ContextKeyChannelModelMapping, appconstant.ContextKeyChannelStatusCodeMapping,
|
||||
appconstant.ContextKeyChannelIsMultiKey, appconstant.ContextKeyChannelMultiKeyIndex, appconstant.ContextKeyChannelKey, appconstant.ContextKeyChannelBaseUrl,
|
||||
appconstant.ContextKeyUpstreamRequestOrigin,
|
||||
} {
|
||||
if value, ok := c.Get(string(key)); ok {
|
||||
s.lockedContext[key] = value
|
||||
@@ -385,7 +396,7 @@ func (s *responsesWSSession) runCall(c *gin.Context, state *responsesWSCallState
|
||||
idle.Reset(timeout)
|
||||
if incoming.err != nil {
|
||||
info.StreamStatus.SetEndReason(relaycommon.StreamEndReasonScannerErr, incoming.err)
|
||||
state.closeAfter = true
|
||||
state.closeCode, state.closeReason = websocket.CloseInternalServerErr, "upstream connection closed"
|
||||
ConsumeResponsesQuota(c, info, accumulator.Finish())
|
||||
return nil
|
||||
}
|
||||
@@ -399,7 +410,7 @@ func (s *responsesWSSession) runCall(c *gin.Context, state *responsesWSCallState
|
||||
} else {
|
||||
if event.Type != "error" && event.StreamID != "" && event.StreamID != create.StreamID {
|
||||
if err := s.writeClient(incoming.kind, incoming.body); err != nil {
|
||||
s.shutdown()
|
||||
s.shutdown(websocket.CloseInternalServerErr, "")
|
||||
}
|
||||
continue
|
||||
}
|
||||
@@ -417,7 +428,7 @@ func (s *responsesWSSession) runCall(c *gin.Context, state *responsesWSCallState
|
||||
terminal, ambiguous, controlError := responsesWSErrorEndsRequest(rejection, create.StreamID, responseID, sentControl)
|
||||
if !terminal {
|
||||
if err := s.writeClient(incoming.kind, incoming.body); err != nil {
|
||||
s.shutdown()
|
||||
s.shutdown(websocket.CloseInternalServerErr, "")
|
||||
}
|
||||
// Only a control error in this stream resolves its pending control.
|
||||
if controlError {
|
||||
@@ -433,10 +444,13 @@ func (s *responsesWSSession) runCall(c *gin.Context, state *responsesWSCallState
|
||||
}
|
||||
info.StreamStatus.MarkFailed(code, rejection.Error.Type, rejection.Status)
|
||||
}
|
||||
accumulator.Observe(&event.ResponsesStreamResponse)
|
||||
accumulator.Observe(&event.ResponsesStreamResponse, incoming.body)
|
||||
info.StreamStatus.SetEndReason(relaycommon.StreamEndReasonDone, nil)
|
||||
s.lastResponseID = responseID
|
||||
state.terminal, state.closeAfter = &incoming, ambiguous
|
||||
state.terminal = &incoming
|
||||
if ambiguous {
|
||||
state.closeCode = websocket.CloseInternalServerErr
|
||||
}
|
||||
ConsumeResponsesQuota(c, info, accumulator.Finish())
|
||||
return nil
|
||||
}
|
||||
@@ -461,7 +475,7 @@ func (s *responsesWSSession) runCall(c *gin.Context, state *responsesWSCallState
|
||||
responseID = event.Response.ID
|
||||
}
|
||||
}
|
||||
accumulator.Observe(&event.ResponsesStreamResponse)
|
||||
accumulator.Observe(&event.ResponsesStreamResponse, incoming.body)
|
||||
}
|
||||
switch event.Type {
|
||||
case "response.completed", "response.done", "response.incomplete", "response.failed", "response.cancelled", "response.canceled":
|
||||
@@ -474,11 +488,11 @@ func (s *responsesWSSession) runCall(c *gin.Context, state *responsesWSCallState
|
||||
return nil
|
||||
}
|
||||
if err := s.writeClient(incoming.kind, incoming.body); err != nil {
|
||||
s.shutdown()
|
||||
s.shutdown(websocket.CloseInternalServerErr, "")
|
||||
}
|
||||
if accepted && pendingControl != nil {
|
||||
if err := s.writeTarget(websocket.TextMessage, pendingControl); err != nil {
|
||||
s.shutdown()
|
||||
s.shutdown(websocket.CloseInternalServerErr, "")
|
||||
}
|
||||
sentControl = pendingControl
|
||||
pendingControl = nil
|
||||
@@ -493,12 +507,12 @@ func (s *responsesWSSession) runCall(c *gin.Context, state *responsesWSCallState
|
||||
continue
|
||||
}
|
||||
if err := s.writeTarget(websocket.TextMessage, control.body); err != nil {
|
||||
s.shutdown()
|
||||
s.shutdown(websocket.CloseInternalServerErr, "")
|
||||
}
|
||||
sentControl = control.body
|
||||
case <-idle.C:
|
||||
info.StreamStatus.SetEndReason(relaycommon.StreamEndReasonTimeout, context.DeadlineExceeded)
|
||||
state.closeAfter = true
|
||||
state.closeCode, state.closeReason = websocket.CloseInternalServerErr, "upstream response timed out"
|
||||
ConsumeResponsesQuota(c, info, accumulator.Finish())
|
||||
return nil
|
||||
case <-s.ctx.Done():
|
||||
@@ -642,27 +656,27 @@ func (s *responsesWSSession) startTargetReader(target *websocket.Conn) {
|
||||
if state := s.getCurrent(); state != nil {
|
||||
select {
|
||||
case state.inbox <- incoming:
|
||||
case <-state.done:
|
||||
if err == nil {
|
||||
if writeErr := s.writeClient(kind, body); writeErr != nil {
|
||||
s.shutdown()
|
||||
return
|
||||
}
|
||||
} else {
|
||||
s.shutdown()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
continue
|
||||
case <-state.done:
|
||||
case <-s.ctx.Done():
|
||||
return
|
||||
}
|
||||
} else if err == nil {
|
||||
if writeErr := s.writeClient(kind, body); writeErr != nil {
|
||||
s.shutdown()
|
||||
return
|
||||
}
|
||||
} else {
|
||||
s.shutdown()
|
||||
}
|
||||
// No request owns this message. An idle upstream that closed
|
||||
// normally ends the client session with the same code.
|
||||
if err != nil {
|
||||
code := websocket.CloseInternalServerErr
|
||||
if websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseGoingAway) {
|
||||
code = err.(*websocket.CloseError).Code
|
||||
}
|
||||
s.shutdown(code, "upstream connection closed")
|
||||
return
|
||||
}
|
||||
if writeErr := s.writeClient(kind, body); writeErr != nil {
|
||||
s.shutdown(websocket.CloseInternalServerErr, "")
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -695,6 +709,7 @@ func (s *responsesWSSession) setTarget(target *websocket.Conn) bool {
|
||||
s.connectionMu.Lock()
|
||||
defer s.connectionMu.Unlock()
|
||||
if s.ctx.Err() != nil {
|
||||
_ = target.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""), time.Now().Add(time.Second))
|
||||
_ = target.Close()
|
||||
return false
|
||||
}
|
||||
@@ -734,23 +749,28 @@ func (s *responsesWSSession) sendError(eventID, streamID string, apiErr *types.N
|
||||
}
|
||||
}
|
||||
|
||||
func (s *responsesWSSession) closeTarget() {
|
||||
s.connectionMu.Lock()
|
||||
target, unregister := s.target, s.unregister
|
||||
s.target, s.unregister = nil, nil
|
||||
s.connectionMu.Unlock()
|
||||
if unregister != nil {
|
||||
unregister()
|
||||
}
|
||||
if target != nil {
|
||||
_ = target.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *responsesWSSession) shutdown() {
|
||||
s.cancel()
|
||||
s.closeTarget()
|
||||
_ = s.client.Close()
|
||||
// shutdown ends the connection once. Each peer gets a close frame that says
|
||||
// why, bounded to one second, and both sockets close even if a write failed.
|
||||
// Close frames are control writes, which gorilla allows alongside a blocked
|
||||
// data writer, so shutdown takes no write lock and never waits for workers.
|
||||
func (s *responsesWSSession) shutdown(code int, reason string) {
|
||||
s.closeOnce.Do(func() {
|
||||
s.cancel()
|
||||
s.connectionMu.Lock()
|
||||
target, unregister := s.target, s.unregister
|
||||
s.target, s.unregister = nil, nil
|
||||
s.connectionMu.Unlock()
|
||||
if unregister != nil {
|
||||
unregister()
|
||||
}
|
||||
closeMessage := websocket.FormatCloseMessage(code, reason)
|
||||
_ = s.client.WriteControl(websocket.CloseMessage, closeMessage, time.Now().Add(time.Second))
|
||||
if target != nil {
|
||||
_ = target.WriteControl(websocket.CloseMessage, closeMessage, time.Now().Add(time.Second))
|
||||
_ = target.Close()
|
||||
}
|
||||
_ = s.client.Close()
|
||||
})
|
||||
}
|
||||
|
||||
func (s *responsesWSSession) registerChannelClose(channelID int) {
|
||||
@@ -766,15 +786,9 @@ func (s *responsesWSSession) registerChannelClose(channelID int) {
|
||||
}
|
||||
|
||||
// closeForPolicy tells both peers why the connection ends, like the realtime
|
||||
// relay does; WriteControl is safe alongside a blocked data writer.
|
||||
// relay does.
|
||||
func (s *responsesWSSession) closeForPolicy(reason string) {
|
||||
closeMessage := websocket.FormatCloseMessage(websocket.ClosePolicyViolation, reason)
|
||||
deadline := time.Now().Add(time.Second)
|
||||
_ = s.client.WriteControl(websocket.CloseMessage, closeMessage, deadline)
|
||||
if target := s.getTarget(); target != nil {
|
||||
_ = target.WriteControl(websocket.CloseMessage, closeMessage, deadline)
|
||||
}
|
||||
s.shutdown()
|
||||
s.shutdown(websocket.ClosePolicyViolation, reason)
|
||||
}
|
||||
|
||||
// Stream identity belongs to the WebSocket envelope. For the legacy wrapped
|
||||
@@ -886,7 +900,7 @@ func buildResponsesWSCreateEvent(jsonData []byte, generate common.RawMessage, st
|
||||
return common.Marshal(event)
|
||||
}
|
||||
|
||||
func buildResponsesWSErrorPayload(eventID, streamID string, apiErr *types.NewAPIError) ([]byte, error) {
|
||||
func buildResponsesWSErrorPayload(eventID, streamID string, apiErr *types.NewAPIError, upstreamURLs ...string) ([]byte, error) {
|
||||
if apiErr == nil {
|
||||
return nil, errors.New("api error is nil")
|
||||
}
|
||||
@@ -894,7 +908,7 @@ func buildResponsesWSErrorPayload(eventID, streamID string, apiErr *types.NewAPI
|
||||
if status == 0 {
|
||||
status = http.StatusInternalServerError
|
||||
}
|
||||
openaiErr := apiErr.ToOpenAIError()
|
||||
openaiErr := apiErr.ToOpenAIError(upstreamURLs...)
|
||||
return common.Marshal(&responsesWSErrorEvent{
|
||||
Type: "error",
|
||||
Status: status,
|
||||
|
||||
Reference in new issue
Block a user