feat: implement advanced condition-based heuristic model routing
Upgrades the routing engine to support tag, token limit, multimodal, reasoning, and tool calling conditions. Adds unit tests for the new routing features.
This commit is contained in:
@@ -14,9 +14,21 @@ import (
|
||||
func AuthMiddleware(database *db.DB, requireAuth bool) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
authHeader := c.GetHeader("Authorization")
|
||||
if authHeader == "" {
|
||||
// Fallback to checking "Authentication" header in case the client library used the wrong name
|
||||
authHeader = c.GetHeader("Authentication")
|
||||
}
|
||||
|
||||
if authHeader == "" {
|
||||
if requireAuth {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "missing authorization header"})
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
|
||||
"error": gin.H{
|
||||
"message": "Missing Authorization or Authentication header.",
|
||||
"type": "invalid_request_error",
|
||||
"param": nil,
|
||||
"code": "401",
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
c.Next()
|
||||
@@ -25,23 +37,50 @@ func AuthMiddleware(database *db.DB, requireAuth bool) gin.HandlerFunc {
|
||||
|
||||
token := strings.TrimPrefix(authHeader, "Bearer ")
|
||||
if token == authHeader { // No "Bearer " prefix
|
||||
if requireAuth {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
|
||||
"error": gin.H{
|
||||
"message": "Invalid authorization header format. Bearer token required.",
|
||||
"type": "invalid_request_error",
|
||||
"param": nil,
|
||||
"code": "401",
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
|
||||
// Try to resolve client from database
|
||||
// Try to resolve client from database with a read-only SELECT
|
||||
var clientID string
|
||||
err := database.Get(&clientID, "UPDATE client_tokens SET last_used_at = CURRENT_TIMESTAMP WHERE token = ? AND is_active = 1 RETURNING client_id", token)
|
||||
err := database.Get(&clientID, "SELECT client_id FROM client_tokens WHERE token = ? AND is_active = 1", token)
|
||||
|
||||
if err == nil {
|
||||
c.Set("auth", models.AuthInfo{
|
||||
Token: token,
|
||||
ClientID: clientID,
|
||||
})
|
||||
|
||||
// Update last_used_at asynchronously so that database locks or write delays
|
||||
// do not block or fail the client's request authentication.
|
||||
go func(t string) {
|
||||
if _, updateErr := database.Exec("UPDATE client_tokens SET last_used_at = CURRENT_TIMESTAMP WHERE token = ?", t); updateErr != nil {
|
||||
log.Printf("Warning: failed to update client token last_used_at: %v", updateErr)
|
||||
}
|
||||
}(token)
|
||||
|
||||
c.Next()
|
||||
} else {
|
||||
log.Printf("Token not found or inactive in DB: %s", token)
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "invalid or inactive token"})
|
||||
log.Printf("Token not found, inactive or error in DB: %s (err: %v)", token, err)
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
|
||||
"error": gin.H{
|
||||
"message": "Invalid or inactive client token.",
|
||||
"type": "invalid_request_error",
|
||||
"param": nil,
|
||||
"code": "401",
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user