79e0f542be
问题分析:
直接让客户端调用FastAPI后端会遇到:
1. CORS跨域限制
2. Cookie无法在跨域情况下传递
3. 安全性降低
正确架构(三层代理):
浏览器 → Remix /api/* → FastAPI /dify/* → Dify
流程说明:
1. 浏览器:fetch('/api/chat-messages', { credentials: 'include' })
- 相对路径,同域请求,无CORS问题
- Cookie自动携带
2. Remix API routes (app/routes/api.chat-messages.tsx)
- 从session获取JWT
- 调用 difyClient.createChatMessage(..., jwt)
3. dify-client.server.ts
- 使用 API_BASE_URL (根据端口配置)
- 调用 FastAPI: http://baseUrl/dify/chat-messages
- 携带JWT: Authorization: Bearer {jwt}
4. FastAPI /dify 路由
- 验证JWT,提取username
- 调用Dify: http://nas.7bm.co:12980/v1/chat-messages
baseUrl配置(服务端使用):
- 端口51703 → http://172.16.0.55:8073
- 端口51704 → http://10.79.97.17:8001
- ...
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
79 lines
2.2 KiB
TypeScript
79 lines
2.2 KiB
TypeScript
import type { AppInfo } from '../types/dify_chat';
|
||
|
||
// 在客户端获取环境变量的辅助函数
|
||
const getEnvVar = (name: string, defaultValue: string = '') => {
|
||
// 在服务端
|
||
if (typeof window === 'undefined') {
|
||
return process.env[name] || defaultValue;
|
||
}
|
||
// 在客户端,从window.__ENV获取
|
||
return (window as any).__ENV?.[name] || defaultValue;
|
||
};
|
||
|
||
// 从完整的APP URL中提取APP ID
|
||
const extractAppId = (appUrl: string): string => {
|
||
if (!appUrl) return '';
|
||
|
||
// 如果是完整的URL,提取最后的UUID部分
|
||
const match = appUrl.match(/\/app\/([a-f0-9-]{36})/);
|
||
if (match) {
|
||
return match[1];
|
||
}
|
||
|
||
// 如果已经是UUID格式,直接返回
|
||
if (/^[a-f0-9-]{36}$/.test(appUrl)) {
|
||
return appUrl;
|
||
}
|
||
|
||
return appUrl;
|
||
};
|
||
|
||
// 获取API基础URL
|
||
// 客户端调用Remix API routes(/api),由Remix服务端代理到FastAPI后端
|
||
const getApiBaseUrl = () => {
|
||
// 客户端使用相对路径调用Remix API routes
|
||
return '/api';
|
||
};
|
||
|
||
// 聊天应用配置
|
||
export const CHAT_CONFIG = {
|
||
// API相关配置 - 客户端调用Remix API routes
|
||
// 客户端 → Remix /api/* → FastAPI /dify/* → Dify
|
||
API_URL: getApiBaseUrl(),
|
||
|
||
// 应用ID - 用于localStorage key(固定值)
|
||
APP_ID: 'docreview-chat',
|
||
|
||
// API_KEY 不再需要 - 服务端通过JWT处理认证
|
||
API_KEY: '', // 保留字段以兼容旧代码
|
||
|
||
// 应用信息
|
||
APP_INFO: {
|
||
title: '大模型对话',
|
||
description: '大模型对话',
|
||
copyright: '大模型对话',
|
||
privacy_policy: '大模型对话',
|
||
default_language: 'zh-Hans',
|
||
},
|
||
|
||
// 功能配置
|
||
isShowPrompt: false,
|
||
promptTemplate: 'I want you to act as a javascript console.',
|
||
|
||
// 本地化
|
||
LOCALE_COOKIE_NAME: 'locale',
|
||
|
||
// 限制
|
||
DEFAULT_VALUE_MAX_LEN: 48,
|
||
};
|
||
|
||
// SSE超时设置
|
||
export const SSE_TIMEOUT = 100000;
|
||
|
||
// 内容类型
|
||
export const ContentType = {
|
||
json: 'application/json',
|
||
stream: 'text/event-stream',
|
||
form: 'application/x-www-form-urlencoded; charset=UTF-8',
|
||
download: 'application/octet-stream',
|
||
};
|