Use different API route according the ENV (#13597)

### What problem does this PR solve?

1. Fix go server date precision
2. Use API_SCHEME_PROXY to control the web API route

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
This commit is contained in:
Jin Hai
2026-03-13 19:05:30 +08:00
committed by GitHub
parent 1569ed82f8
commit cc7e94ffb6
14 changed files with 140 additions and 73 deletions

View File

@@ -14,7 +14,8 @@ PROJECT_ROOT="$SCRIPT_DIR"
# Build directories
CPP_DIR="$PROJECT_ROOT/internal/cpp"
BUILD_DIR="$CPP_DIR/cmake-build-release"
OUTPUT_BINARY="$PROJECT_ROOT/bin/server_main"
RAGFLOW_SERVER_BINARY="$PROJECT_ROOT/bin/server_main"
ADMIN_SERVER_BINARY="$PROJECT_ROOT/bin/admin_server"
echo -e "${GREEN}=== RAGFlow Go Server Build Script ===${NC}"
@@ -90,16 +91,22 @@ build_go() {
sudo apt -y install libpcre2-dev
fi
echo "Building Go binary: $OUTPUT_BINARY"
GOPROXY=${GOPROXY:-https://goproxy.cn,https://proxy.golang.org,direct} CGO_ENABLED=1 go build -o "$OUTPUT_BINARY" ./cmd/server_main.go
GOPROXY=${GOPROXY:-https://goproxy.cn,https://proxy.golang.org,direct} CGO_ENABLED=1 go build -o "$OUTPUT_BINARY" ./cmd/admin_server.go
echo "Building API server binary: $RAGFLOW_SERVER_BINARY and $ADMIN_SERVER_BINARY"
GOPROXY=${GOPROXY:-https://goproxy.cn,https://proxy.golang.org,direct} CGO_ENABLED=1 go build -o "$RAGFLOW_SERVER_BINARY" ./cmd/server_main.go
GOPROXY=${GOPROXY:-https://goproxy.cn,https://proxy.golang.org,direct} CGO_ENABLED=1 go build -o "$ADMIN_SERVER_BINARY" ./cmd/admin_server.go
if [ ! -f "$OUTPUT_BINARY" ]; then
echo -e "${RED}Error: Failed to build Go binary${NC}"
if [ ! -f "$RAGFLOW_SERVER_BINARY" ]; then
echo -e "${RED}Error: Failed to build RAGFlow server binary${NC}"
exit 1
fi
echo -e "${GREEN}✓ Go server built successfully: $OUTPUT_BINARY${NC}"
if [ ! -f "$ADMIN_SERVER_BINARY" ]; then
echo -e "${RED}Error: Failed to build Admin server binary${NC}"
exit 1
fi
echo -e "${GREEN}✓ Go server_main built successfully: $RAGFLOW_SERVER_BINARY${NC}"
echo -e "${GREEN}✓ Go admin_server built successfully: $ADMIN_SERVER_BINARY${NC}"
}
# Clean build artifacts
@@ -107,14 +114,24 @@ clean() {
print_section "Cleaning build artifacts"
rm -rf "$BUILD_DIR"
rm -f "$OUTPUT_BINARY"
rm -f "$RAGFLOW_SERVER_BINARY"
rm -f "$ADMIN_SERVER_BINARY"
echo -e "${GREEN}✓ Build artifacts cleaned${NC}"
}
# Run the server
run() {
if [ ! -f "$OUTPUT_BINARY" ]; then
if [ ! -f "$ADMIN_SERVER_BINARY" ]; then
echo -e "${RED}Error: Binary not found. Build first with --all or --go${NC}"
exit 1
fi
print_section "Starting ADMIN server"
cd "$PROJECT_ROOT"
./admin_server
if [ ! -f "$RAGFLOW_SERVER_BINARY" ]; then
echo -e "${RED}Error: Binary not found. Build first with --all or --go${NC}"
exit 1
fi
@@ -184,7 +201,7 @@ main() {
build_cpp
build_go
echo -e "\n${GREEN}=== Build completed successfully! ===${NC}"
echo "Binary: $OUTPUT_BINARY"
echo "Binary: $RAGFLOW_SERVER_BINARY, $ADMIN_SERVER_BINARY"
;;
*)
echo -e "${RED}Unknown option: $1${NC}"

View File

@@ -155,6 +155,9 @@ SVR_MCP_PORT=9382
GO_HTTP_PORT=9384
GO_ADMIN_PORT=9385
# API_PROXY_SCHEME=hybrid # go and python hybrid deploy mode
API_PROXY_SCHEME=python # use pure python server deployment
# The RAGFlow Docker image to download. v0.22+ doesn't include embedding models.
RAGFLOW_IMAGE=infiniflow/ragflow:v0.24.0

View File

@@ -34,6 +34,8 @@ services:
- ${SVR_HTTP_PORT}:9380
- ${ADMIN_SVR_HTTP_PORT}:9381
- ${SVR_MCP_PORT}:9382 # entry for MCP (host_port:docker_port). The docker_port must match the value you set for `mcp-port` above.
- ${GO_HTTP_PORT}:9384
- ${GO_ADMIN_PORT}:9385
volumes:
- ./ragflow-logs:/ragflow/logs
- ./nginx/ragflow.conf:/etc/nginx/conf.d/ragflow.conf

View File

@@ -230,7 +230,11 @@ if [[ "${ENABLE_WEBSERVER}" -eq 1 ]]; then
echo "Starting ragflow_server..."
while true; do
"$PY" api/ragflow_server.py ${INIT_SUPERUSER_ARGS} &
bin/server_main &
if [[ "${API_PROXY_SCHEME}" == "hybrid" ]]; then
echo "Starting RAGFlow server in hybrid mode..."
bin/server_main &
fi
wait;
sleep 1;
done &
@@ -249,7 +253,10 @@ if [[ "${ENABLE_ADMIN_SERVER}" -eq 1 ]]; then
echo "Starting admin_server..."
while true; do
"$PY" admin/server/admin_server.py &
bin/admin_server &
if [[ "${API_PROXY_SCHEME}" == "hybrid" ]]; then
echo "Starting Admin server in hybrid mode..."
bin/admin_server &
fi
wait;
sleep 1;
done &

View File

@@ -183,7 +183,7 @@ func (s *Service) CreateUser(username, password, role string) (map[string]interf
isSuperuser := role == "admin"
now := time.Now().Unix()
nowDate := time.Now()
nowDate := time.Now().Truncate(time.Second)
user := &model.User{
ID: userID,
@@ -440,7 +440,7 @@ func (s *Service) getInitTenantLLM(userID string) ([]*model.TenantLLM, error) {
llmName := llm.LLMName
modelType := llm.ModelType
now := time.Now().Unix()
nowDate := time.Now()
nowDate := time.Now().Truncate(time.Second)
tenantLLM := &model.TenantLLM{
TenantID: userID,
@@ -1559,7 +1559,7 @@ func (s *Service) InitDefaultAdmin() error {
if len(users) == 0 {
now := time.Now().Unix()
nowDate := time.Now()
nowDate := time.Now().Truncate(time.Second)
userID := utility.GenerateToken()
accessToken := utility.GenerateToken()
status := "1"
@@ -1635,7 +1635,7 @@ func (s *Service) InitDefaultAdmin() error {
// addTenantForAdmin add tenant for admin user
func (s *Service) addTenantForAdmin(userID, nickname string) error {
now := time.Now().Unix()
nowDate := time.Now()
nowDate := time.Now().Truncate(time.Second)
status := "1"
role := "owner"
tenantName := nickname + "'s Kingdom"

View File

@@ -293,7 +293,7 @@ func (dao *KnowledgebaseDAO) DuplicateName(name, tenantID string) string {
// This matches the Python atomic_increase_doc_num_by_id method
func (dao *KnowledgebaseDAO) AtomicIncreaseDocNumByID(kbID string) error {
now := time.Now().Unix()
nowDate := time.Now()
nowDate := time.Now().Truncate(time.Second)
return DB.Model(&model.Knowledgebase{}).
Where("id = ?", kbID).
Updates(map[string]interface{}{
@@ -307,7 +307,7 @@ func (dao *KnowledgebaseDAO) AtomicIncreaseDocNumByID(kbID string) error {
// This matches the Python decrease_document_num_in_delete method
func (dao *KnowledgebaseDAO) DecreaseDocumentNum(kbID string, docNum, chunkNum, tokenNum int64) error {
now := time.Now().Unix()
nowDate := time.Now()
nowDate := time.Now().Truncate(time.Second)
return DB.Model(&model.Knowledgebase{}).
Where("id = ?", kbID).
Updates(map[string]interface{}{

View File

@@ -59,7 +59,7 @@ func (d *SystemSettingsDAO) GetByName(name string) ([]model.SystemSettings, erro
// Updates the setting with the given name using the provided data
func (d *SystemSettingsDAO) UpdateByName(name string, setting *model.SystemSettings) error {
now := time.Now().Unix()
nowDate := time.Now()
nowDate := time.Now().Truncate(time.Second)
return DB.Model(&model.SystemSettings{}).
Where("name = ?", name).
@@ -76,7 +76,7 @@ func (d *SystemSettingsDAO) UpdateByName(name string, setting *model.SystemSetti
// Inserts a new system setting record into database
func (d *SystemSettingsDAO) Create(setting *model.SystemSettings) error {
now := time.Now().Unix()
nowDate := time.Now()
nowDate := time.Now().Truncate(time.Second)
setting.CreateTime = &now
setting.CreateDate = &nowDate
@@ -161,7 +161,7 @@ func (d *SystemSettingsDAO) Transaction(fn func(tx *gorm.DB) error) error {
// CreateWithTx create setting within transaction
func (d *SystemSettingsDAO) CreateWithTx(tx *gorm.DB, setting *model.SystemSettings) error {
now := time.Now().Unix()
nowDate := time.Now()
nowDate := time.Now().Truncate(time.Second)
setting.CreateTime = &now
setting.CreateDate = &nowDate
@@ -174,7 +174,7 @@ func (d *SystemSettingsDAO) CreateWithTx(tx *gorm.DB, setting *model.SystemSetti
// UpdateByNameWithTx update setting within transaction
func (d *SystemSettingsDAO) UpdateByNameWithTx(tx *gorm.DB, name string, setting *model.SystemSettings) error {
now := time.Now().Unix()
nowDate := time.Now()
nowDate := time.Now().Truncate(time.Second)
return tx.Model(&model.SystemSettings{}).
Where("name = ?", name).

View File

@@ -67,7 +67,7 @@ func (h *AuthHandler) AuthMiddleware() gin.HandlerFunc {
if *user.IsSuperuser {
c.JSON(http.StatusForbidden, gin.H{
"code": common.CodeForbidden,
"message": "Super user should access the URL",
"message": "Super user shouldn't access the URL",
})
return
}

View File

@@ -336,14 +336,6 @@ func (h *UserHandler) Logout(c *gin.Context) {
return
}
if *user.IsSuperuser {
c.JSON(http.StatusForbidden, gin.H{
"code": common.CodeForbidden,
"message": "Super user should access the URL",
})
return
}
// Logout user
code, err = h.userService.Logout(user)
if err != nil {

View File

@@ -434,7 +434,7 @@ func (s *ChatService) SetDialog(userID string, req *SetDialogRequest) (*SetDialo
}
// Get current time
now := time.Now()
now := time.Now().Truncate(time.Second)
createTime := now.UnixMilli()
// Set default language
@@ -479,7 +479,7 @@ func (s *ChatService) SetDialog(userID string, req *SetDialogRequest) (*SetDialo
}
// Update existing chat - also update update_time
now := time.Now()
now := time.Now().Truncate(time.Second)
updateTime := now.UnixMilli()
updateData := map[string]interface{}{
"name": name,

View File

@@ -113,8 +113,8 @@ func (s *ChatSessionService) SetChatSession(userID string, req *SetChatSessionRe
}
}
now := time.Now()
createTime := now.UnixMilli()
now := time.Now().Truncate(time.Second)
createTime := time.Now().UnixMilli()
// Create initial message - store as JSON object with messages array
messagesObj := map[string]interface{}{

View File

@@ -146,7 +146,7 @@ func (s *KnowledgebaseService) CreateKB(req *CreateKBRequest, tenantID string) (
// Create knowledge base model
now := time.Now().Unix()
nowDate := time.Now()
nowDate := time.Now().Truncate(time.Second)
kb := &model.Knowledgebase{
ID: kbID,
Name: duplicateName,
@@ -256,7 +256,7 @@ func (s *KnowledgebaseService) UpdateKB(req *UpdateKBRequest, userID string) (ma
}
now := time.Now().Unix()
nowDate := time.Now()
nowDate := time.Now().Truncate(time.Second)
updates["update_time"] = now
updates["update_date"] = nowDate

View File

@@ -150,7 +150,7 @@ func (s *UserService) Register(req *RegisterRequest) (*model.User, common.ErrorC
now := time.Now().Unix()
user.CreateTime = &now
user.UpdateTime = &now
now_date := time.Now()
now_date := time.Now().Truncate(time.Second)
user.CreateDate = &now_date
user.UpdateDate = &now_date
user.LastLoginTime = &now_date
@@ -343,7 +343,7 @@ func (s *UserService) LoginByEmail(req *EmailLoginRequest, adminLogin bool) (*mo
now := time.Now().Unix()
user.UpdateTime = &now
now_date := time.Now()
now_date := time.Now().Truncate(time.Second)
user.UpdateDate = &now_date
if err := s.userDAO.Update(user); err != nil {
return nil, common.CodeServerError, fmt.Errorf("failed to update user: %w", err)

View File

@@ -30,6 +30,83 @@ const inspectorBabelPlugin = (): import('vite').Plugin => ({
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '');
const proxySchemes = {
python: {
'/api/v1/admin': {
target: 'http://127.0.0.1:9381/',
changeOrigin: true,
ws: true,
},
'/api': {
target: 'http://127.0.0.1:9380/',
changeOrigin: true,
ws: true,
},
'/v1': {
target: 'http://127.0.0.1:9380/',
changeOrigin: true,
ws: true,
},
},
hybrid: {
'/v1/system/config': {
target: 'http://127.0.0.1:9384/',
changeOrigin: true,
ws: true,
},
'/v1/user/login': {
target: 'http://127.0.0.1:9384/',
changeOrigin: true,
ws: true,
},
'/v1/user/logout': {
target: 'http://127.0.0.1:9384/',
changeOrigin: true,
ws: true,
},
'/api/v1/admin/sandbox': {
target: 'http://127.0.0.1:9381/',
changeOrigin: true,
ws: true,
},
'/api/v1/admin': {
target: 'http://127.0.0.1:9385/',
changeOrigin: true,
ws: true,
},
'/api': {
target: 'http://127.0.0.1:9380/',
changeOrigin: true,
ws: true,
},
'/v1': {
target: 'http://127.0.0.1:9380/',
changeOrigin: true,
ws: true,
},
},
go: {
'/api/v1/admin': {
target: 'http://127.0.0.1:9385/',
changeOrigin: true,
ws: true,
},
'/api': {
target: 'http://127.0.0.1:9384/',
changeOrigin: true,
ws: true,
},
'/v1': {
target: 'http://127.0.0.1:9384/',
changeOrigin: true,
ws: true,
},
},
};
const proxy =
proxySchemes[env.API_PROXY_SCHEME || 'python'] || proxySchemes.python;
return {
plugins: [
inspectorBabelPlugin(),
@@ -85,38 +162,7 @@ export default defineConfig(({ mode }) => {
hmr: {
overlay: false,
},
proxy: {
'/api/v1/admin': {
target: 'http://127.0.0.1:9381/',
changeOrigin: true,
ws: true,
},
'/api': {
target: 'http://127.0.0.1:9380/',
changeOrigin: true,
ws: true,
},
// '/v1/system/config': {
// target: 'http://127.0.0.1:9382/',
// changeOrigin: true,
// ws: true,
// },
// '/v1/user/login': {
// target: 'http://127.0.0.1:9382/',
// changeOrigin: true,
// ws: true,
// },
// '/v1/user/logout': {
// target: 'http://127.0.0.1:9382/',
// changeOrigin: true,
// ws: true,
// },
'/v1': {
target: 'http://127.0.0.1:9380/',
changeOrigin: true,
ws: true,
},
},
proxy,
},
assetsInclude: ['**/*.md'],
base: env.VITE_BASE_URL,