tanbushi commited on
Commit
543ec94
·
1 Parent(s): 0813f4c

Sun Jun 8 12:09:47 CST 2025

Browse files
.clinerules ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 自定义指令
2
+ CUSTOM_INSTRUCTIONS = """
3
+ # 基本配置
4
+ env_tool(虚拟环境管理工具): conda
5
+ env_name(虚拟环境名称): api-proxy
6
+ env_activate_cmd(激活虚拟环境命令): conda activate {env_tool}
7
+
8
+ # 角色
9
+ 你是一个基于python开发工程师
10
+
11
+ # 项目要求
12
+ - 使用 fastapi 开发一个实现多种 api 代理转发的工具
13
+
14
+ # 知识参考
15
+ 当你需要查询相关源码时,请访问下面的链接:
16
+
17
+ ---
18
+
19
+ # 虚拟环境要求
20
+ - 虚拟环境工具:{env_tool}
21
+ - 使用名为{env_name}的虚拟环境,如果没有则创建,如果有则运行下面的命令行:{env_activate_cmd}
22
+
23
+ # 项目管理
24
+ - 使用 Memory Bank作为项目管理工具
25
+ - 用户可以到当前目录下通过指令进行任务管理
26
+ - Memory Bank 中使用中文记录的项目信息
27
+
28
+ # 交流
29
+ - 如非特别指明,必须使用中文进行交流
30
+ - 如果需求不明确时,必须找用户进行需求调研,调研时,一次只提问一个问题
31
+
32
+ """
33
+ # 自动批准规则
34
+ AUTO_APPROVE = true
35
+
36
+
37
+ ---
38
+ description: Describes Cline's Memory Bank system, its structure, and workflows for maintaining project knowledge across sessions.
39
+ author: https://github.com/nickbaumann98
40
+ version: 1.0
41
+ tags: ["memory-bank", "knowledge-base", "core-behavior", "documentation-protocol"]
42
+ globs: ["memory-bank/**/*.md", "*"]
43
+ ---
44
+ # Cline's Memory Bank
45
+
46
+ I am Cline, an expert software engineer with a unique characteristic: my memory resets completely between sessions. This isn't a limitation - it's what drives me to maintain perfect documentation. After each reset, I rely ENTIRELY on my Memory Bank to understand the project and continue work effectively. I MUST read ALL memory bank files at the start of EVERY task - this is not optional.
47
+
48
+ ## Memory Bank Structure
49
+
50
+ The Memory Bank consists of core files and optional context files, all in Markdown format. Files build upon each other in a clear hierarchy:
51
+
52
+ ```mermaid
53
+ flowchart TD
54
+ PB[projectbrief.md] --> PC[productContext.md]
55
+ PB --> SP[systemPatterns.md]
56
+ PB --> TC[techContext.md]
57
+
58
+ PC --> AC[activeContext.md]
59
+ SP --> AC
60
+ TC --> AC
61
+
62
+ AC --> P[progress.md]
63
+ ```
64
+
65
+ ### Core Files (Required)
66
+ 1. `projectbrief.md`
67
+ - Foundation document that shapes all other files
68
+ - Created at project start if it doesn't exist
69
+ - Defines core requirements and goals
70
+ - Source of truth for project scope
71
+
72
+ 2. `productContext.md`
73
+ - Why this project exists
74
+ - Problems it solves
75
+ - How it should work
76
+ - User experience goals
77
+
78
+ 3. `activeContext.md`
79
+ - Current work focus
80
+ - Recent changes
81
+ - Next steps
82
+ - Active decisions and considerations
83
+ - Important patterns and preferences
84
+ - Learnings and project insights
85
+
86
+ 4. `systemPatterns.md`
87
+ - System architecture
88
+ - Key technical decisions
89
+ - Design patterns in use
90
+ - Component relationships
91
+ - Critical implementation paths
92
+
93
+ 5. `techContext.md`
94
+ - Technologies used
95
+ - Development setup
96
+ - Technical constraints
97
+ - Dependencies
98
+ - Tool usage patterns
99
+
100
+ 6. `progress.md`
101
+ - What works
102
+ - What's left to build
103
+ - Current status
104
+ - Known issues
105
+ - Evolution of project decisions
106
+
107
+ ### Additional Context
108
+ Create additional files/folders within memory-bank/ when they help organize:
109
+ - Complex feature documentation
110
+ - Integration specifications
111
+ - API documentation
112
+ - Testing strategies
113
+ - Deployment procedures
114
+
115
+ ## Core Workflows
116
+
117
+ ### Plan Mode
118
+ ```mermaid
119
+ flowchart TD
120
+ Start[Start] --> ReadFiles[Read Memory Bank]
121
+ ReadFiles --> CheckFiles{Files Complete?}
122
+
123
+ CheckFiles -->|No| Plan[Create Plan]
124
+ Plan --> Document[Document in Chat]
125
+
126
+ CheckFiles -->|Yes| Verify[Verify Context]
127
+ Verify --> Strategy[Develop Strategy]
128
+ Strategy --> Present[Present Approach]
129
+ ```
130
+
131
+ ### Act Mode
132
+ ```mermaid
133
+ flowchart TD
134
+ Start[Start] --> Context[Check Memory Bank]
135
+ Context --> Update[Update Documentation]
136
+ Update --> Execute[Execute Task]
137
+ Execute --> Document[Document Changes]
138
+ ```
139
+
140
+ ## Documentation Updates
141
+
142
+ Memory Bank updates occur when:
143
+ 1. Discovering new project patterns
144
+ 2. After implementing significant changes
145
+ 3. When user requests with **update memory bank** (MUST review ALL files)
146
+ 4. When context needs clarification
147
+
148
+ ```mermaid
149
+ flowchart TD
150
+ Start[Update Process]
151
+
152
+ subgraph Process
153
+ P1[Review ALL Files]
154
+ P2[Document Current State]
155
+ P3[Clarify Next Steps]
156
+ P4[Document Insights & Patterns]
157
+
158
+ P1 --> P2 --> P3 --> P4
159
+ end
160
+
161
+ Start --> Process
162
+ ```
163
+
164
+ Note: When triggered by **update memory bank**, I MUST review every memory bank file, even if some don't require updates. Focus particularly on activeContext.md and progress.md as they track current state.
165
+
166
+ REMEMBER: After every memory reset, I begin completely fresh. The Memory Bank is my only link to previous work. It must be maintained with precision and clarity, as my effectiveness depends entirely on its accuracy.
.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ **/__pycache__/
2
+ README.md
3
+ .env
Dockerfile ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Read the doc: https://huggingface.co/docs/hub/spaces-sdks-docker
2
+ # you will also find guides on how best to write your Dockerfile
3
+
4
+ FROM python:3.9
5
+
6
+ RUN useradd -m -u 1000 user
7
+ USER user
8
+ ENV PATH="/home/user/.local/bin:$PATH"
9
+
10
+ WORKDIR /app
11
+
12
+ COPY --chown=user ./requirements.txt requirements.txt
13
+ RUN pip install --no-cache-dir --upgrade -r requirements.txt
14
+
15
+ COPY --chown=user . /app
16
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py ADDED
@@ -0,0 +1,191 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, Request, HTTPException, Response
2
+ from fastapi.responses import StreamingResponse
3
+ import httpx
4
+ import logging
5
+ import os, json
6
+ import re # 用于URL路径处理
7
+ from pprint import pprint
8
+ from key_selector import KeySelector
9
+
10
+ def get_target_url(url: str) -> str:
11
+ """将url参数变了转换为合法的目标url;from http/ or https/ to http:// or https://"""
12
+ url = re.sub(r"^http/", "http://", url)
13
+ url = re.sub(r"^https/", "https://", url)
14
+ return url
15
+
16
+ app = FastAPI()
17
+
18
+ # 配置日志
19
+ logging.basicConfig(level=logging.INFO)
20
+ logger = logging.getLogger("uvicorn.error")
21
+
22
+ # 从环境变量获取配置
23
+ # UPSTREAM_HOST = os.getenv("UPSTREAM_HOST", "http://127.0.0.1") # 必须包含端口号
24
+ # AUTH_TOKEN = os.getenv("AUTH_TOKEN", "YIG8ANC8q2QxFV_Gf8qwkPdBj2EpsqGqlfc3qvSdg7ksVkZcokOUtQn43XGK0NK3UUdBlIkYzNWefco_Wu4RcKnB0kpNgtZ2nTeqNum0i3fTUEhEcWSlJtT8FQgRK7bi") # 安全认证令牌
25
+ X_Goog_Api_Key = os.getenv("X_Goog_Api_Key", "")
26
+
27
+ @app.get("/")
28
+ async def read_root():
29
+ return {"message": "FastAPI Proxy is running"}
30
+
31
+ @app.post("/v25/{path:path}")
32
+ async def proxy(request: Request, path: str):
33
+ # 添加流式请求判断逻辑
34
+ is_streaming = ":streamGenerateContent" in path.lower()
35
+ print(f"path: {path}")
36
+ # path = "https/generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent"
37
+ # target_url = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent"
38
+ target_url = get_target_url(path)
39
+ # target_url = f"{target_url}?key={X_Goog_Api_Key}"
40
+ print(f"target_url: {target_url}")
41
+ method = request.method
42
+ headers = {k: v for k, v in request.headers.items()
43
+ # if k.lower() not in ["host", "connection", "Postman-Token", "content-length"]}
44
+ if k.lower() not in ["host", "content-length"]}
45
+
46
+ key_selector = KeySelector()
47
+ # print('apikey',key_selector.get_api_key()['key_value'])
48
+
49
+ headers["X-Goog-Api-Key"] = key_selector.get_api_key()['key_value']
50
+ # print(key_selector.api_key_info.key_value)
51
+ # headers["host"] = "generativelanguage.googleapis.com"
52
+
53
+ try:
54
+ # 关键修复:禁用KeepAlive防止连接冲突
55
+ transport = httpx.AsyncHTTPTransport(retries=3, http1=True)
56
+
57
+ async with httpx.AsyncClient(
58
+ transport=transport,
59
+ timeout=httpx.Timeout(300.0, connect=30.0)
60
+ ) as client:
61
+ # 处理请求体
62
+ req_content = await request.body()
63
+ print(f"Request headers: {headers}")
64
+ # print(f"req_content: {req_content}")
65
+ # req_content_str = req_content.decode('utf-8') # 假设内容是 UTF-8 编码
66
+ # print(f"req_content_str: {req_content_str}")
67
+ print(f'target_url: {target_url}')
68
+ print(f'method: {method}')
69
+ # 发送请求到上游服务
70
+ response = await client.request(
71
+ method=method,
72
+ url=target_url,
73
+ headers=headers,
74
+ content=req_content,
75
+ follow_redirects=True # 自动处理重定向
76
+ )
77
+
78
+ if is_streaming:
79
+ # 流式响应处理
80
+ async def stream_generator():
81
+ try:
82
+ async for chunk in response.aiter_bytes():
83
+ yield chunk
84
+ except Exception as e:
85
+ logger.error(f"Stream interrupted: {str(e)}")
86
+ yield json.dumps({"error": "流中断"}).encode()
87
+
88
+ # 移除冲突头部
89
+ headers = dict(response.headers)
90
+ headers.pop("Content-Length", None)
91
+
92
+ return StreamingResponse(
93
+ content=stream_generator(),
94
+ status_code=response.status_code,
95
+ headers=headers,
96
+ media_type="application/x-ndjson" # Gemini流式格式
97
+ )
98
+ else:
99
+
100
+ print(f"response.status_code: {response.status_code}")
101
+ print(f"response.text: {response.text}")
102
+ # 解析 JSON 字符串
103
+ try:
104
+ data = json.loads(response.text)
105
+ # 格式化输出 JSON 数据
106
+ formatted_json = json.dumps(data, ensure_ascii=False, indent=4)
107
+ print('formatted_json')
108
+ print(formatted_json)
109
+ # return formatted_json
110
+ return Response(
111
+ content=formatted_json,
112
+ media_type="application/json"
113
+ )
114
+ except json.JSONDecodeError as e:
115
+ print(f"Error decoding JSON: {e}")
116
+
117
+
118
+ # # 详细记录错误响应
119
+ # if response.status_code >= 400:
120
+ # error_detail = response.text[:1000] # 增加错误详情长度
121
+ # logger.error(f"Upstream error {response.status_code}: {error_detail}")
122
+ # # 可选:记录完整响应到文件
123
+ # # with open("error.log", "a") as f:
124
+ # # f.write(f"\n--- {target_url} ---\n{response.text}\n")
125
+
126
+ # # 流式传输响应
127
+ # return StreamingResponse(
128
+ # content=response.aiter_bytes(),
129
+ # status_code=response.status_code,
130
+ # headers=dict(response.headers)
131
+ # )
132
+
133
+ except httpx.ConnectError as e:
134
+ logger.error(f"Connection failed to {target_url}: {e}")
135
+ raise HTTPException(502, f"无法连接到上游服务: {target_url}") # Modified error message
136
+ except httpx.ReadTimeout as e:
137
+ logger.error(f"Timeout: {e}")
138
+ raise HTTPException(504, "上游服务响应超时")
139
+ except httpx.HTTPError as e: # 捕获所有HTTP异常
140
+ print('111111111111111111111')
141
+
142
+ try:
143
+ # 安全地获取异常信息
144
+ error_type = type(e).__name__
145
+
146
+ # 尝试获取状态码(如果存在)
147
+ status_code = getattr(e, 'response', None) and e.response.status_code
148
+
149
+ # 安全地获取错误详情
150
+ error_detail = ""
151
+ try:
152
+ # 尝试获取文本响应(限制长度)
153
+ if hasattr(e, 'response') and e.response:
154
+ error_detail = e.response.text[:500] # 只取前500个字符
155
+ except Exception as ex:
156
+ error_detail = f"无法获取错误详情: {type(ex).__name__}"
157
+
158
+ # 安全地记录日志
159
+ logger.error(
160
+ "HTTP代理错误 | "
161
+ f"类型: {error_type} | "
162
+ f"状态码: {status_code or 'N/A'} | "
163
+ f"目标URL: {target_url} | "
164
+ f"详情: {error_detail[:200]}" # 日志中只记录前200字符
165
+ )
166
+
167
+ # 打印到控制台以便调试
168
+ print(f"111111111111111111111 - HTTP代理错误: {error_type}")
169
+ print(f"目标URL: {target_url}")
170
+ print(f"状态码: {status_code or 'N/A'}")
171
+ print(f"错误详情: {error_detail[:500]}")
172
+
173
+ except Exception as ex:
174
+ # 如果记录日志本身出错,使用最安全的方式记录
175
+ logger.error(f"记录HTTP错误时发生异常: {type(ex).__name__}")
176
+ print(f"严重错误: 记录HTTP错误时发生异常: {ex}")
177
+
178
+ # 返回用户友好的错误响应
179
+ raise HTTPException(
180
+ status_code=502,
181
+ detail=f"网关服务错误: {error_type} (上游状态: {status_code or '未知'})"
182
+ )
183
+
184
+
185
+ print('111111111111111111111')
186
+ # logger.error(f"HTTP error: {str(e)}")
187
+
188
+ raise HTTPException(502, f"网关错误: {str(e)}")
189
+ except Exception as e:
190
+ logger.exception("Unexpected proxy error")
191
+ raise HTTPException(500, f"内部服务器错误: {str(e)}")
key_selector.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from dotenv import load_dotenv
3
+ load_dotenv()
4
+
5
+ class KeySelector():
6
+ def __init__(self):
7
+ pass
8
+
9
+ def get_api_key(self):
10
+ api_key_info = {
11
+ "key_at": "at_headers",
12
+ "key_name": "X_Goog_Api_Key",
13
+ "key_value": os.getenv("X_Goog_Api_Key", "")
14
+ }
15
+ return api_key_info
memory-bank/activeContext.md ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 当前背景 (Active Context)
2
+
3
+ ## 当前工作重点
4
+ 初始化项目记忆库。
5
+
6
+ ## 最近的变更
7
+ - 创建了 `projectbrief.md` 文件,定义了项目的核心目标和范围。
8
+ - 创建了 `productContext.md` 文件,描述了项目的目的、解决的问题和用户体验目标。
9
+ - 创建了 `systemPatterns.md` 文件,概述了系统架构、设计模式和关键组件。
10
+ - 创建了 `techContext.md` 文件,记录了使用的技术、开发环境设置和技术约束。
11
+
12
+ ## 下一步计划
13
+ - 创建 `progress.md` 文件,记录项目的当前状态、已完成和待完成的工作。
14
+ - 根据项目需求,开始实现 FastAPI 应用的核心代理转发逻辑。
15
+ - 定义和实现代理规则的配置加载机制。
16
+ - 集成 HTTP 客户端库 (`httpx`) 进行后端请求转发。
17
+
18
+ ## 重要的模式和偏好
19
+ - 优先使用异步编程。
20
+ - 保持代码简洁和模块化。
21
+ - 遵循 FastAPI 的最佳实践。
22
+
23
+ ## 学习和项目洞察
24
+ - 项目处于初期阶段,主要任务是搭建基本框架和配置。
25
+ - 需要仔细设计配置文件的结构,以便于灵活地添加和管理代理规则。
memory-bank/productContext.md ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 产品背景 (Product Context)
2
+
3
+ ## 项目目的
4
+ 本项目旨在开发一个灵活的 API 代理转发工具,以解决在微服务架构或集成不同第三方服务时遇到的跨域、认证、请求/响应格式不一致等问题。通过集中管理 API 访问,简化客户端与多个后端服务之间的交互。
5
+
6
+ ## 解决的问题
7
+ - **跨域问题**: 允许客户端通过单一来源访问不同域的 API。
8
+ - **API 集成**: 简化集成多个内部或外部 API 的过程。
9
+ - **请求/响应转换**: 提供一个中心点来标准化或修改请求和响应数据。
10
+ - **配置管理**: 集中管理所有代理目标的配置。
11
+
12
+ ## 用户体验目标
13
+ - **开发者**: 易于配置和扩展新的代理规则。
14
+ - **系统管理员**: 易于部署和管理。
15
+ - **最终用户**: 无感知地通过代理访问后端服务。
16
+
17
+ ## 功能愿景
18
+ - 支持基于路径、请求方法等多种匹配规则进行转发。
19
+ - 支持请求头、请求体、查询参数的修改。
20
+ - 支持响应头、响应体的修改。
21
+ - 易于集成认证和授权机制(未来可能)。
22
+ - 提供基本的日志记录功能。
memory-bank/progress.md ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 项目进度 (Progress)
2
+
3
+ ## 当前状态
4
+ 项目记忆库已初始化。核心记忆文件(projectbrief.md, productContext.md, systemPatterns.md, techContext.md, activeContext.md)已创建。
5
+
6
+ ## 已完成的工作
7
+ - 创建了 Memory Bank 目录。
8
+ - 创建并填充了以下记忆文件:
9
+ - `projectbrief.md`
10
+ - `productContext.md`
11
+ - `systemPatterns.md`
12
+ - `techContext.md`
13
+ - `activeContext.md`
14
+
15
+ ## 待完成的工作
16
+ - 实现 FastAPI 应用的核心代理转发逻辑。
17
+ - 设计和实现代理规则的配置加载机制。
18
+ - 集成 `httpx` 库进行后端请求转发。
19
+ - 添加基本的日志记录功能。
20
+ - 根据需求实现请求/响应转换功能。
21
+ - 编写单元测试和集成测试。
22
+ - 完善 Dockerfile。
23
+ - 编写详细的 README.md 文档。
24
+
25
+ ## 已知问题
26
+ - 暂无已知问题。
27
+
28
+ ## 项目决策演变
29
+ - 决定使用 FastAPI 作为后端框架,因为它提供了高性能和易于使用的异步支持。
30
+ - 决定使用 `httpx` 作为 HTTP 客户端,因为它支持异步请求。
31
+ - 决定使用配置文件来管理代理规则,以提高灵活性。
memory-bank/projectbrief.md ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 项目简报 (Project Brief)
2
+
3
+ ## 项目名称
4
+ API 代理转发工具
5
+
6
+ ## 核心目标
7
+ 使用 FastAPI 开发一个实现多种 API 代理转发的工具。
8
+
9
+ ## 主要需求
10
+ - 能够接收来自客户端的请求。
11
+ - 根据配置将请求转发到不同的后端 API。
12
+ - 处理请求和响应的转换(如果需要)。
13
+ - 支持多种 API 的代理。
14
+
15
+ ## 范围
16
+ 本项目专注于构建核心的代理转发功能。
17
+
18
+ ## 非范围
19
+ - 高级安全功能(如认证、授权)除非明确要求。
20
+ - 复杂的负载均衡策略除非明确要求。
21
+ - 详细的监控和日志分析除非明确要求。
22
+
23
+ ## 成功标准
24
+ - 能够成功代理转发至少两种不同的 API 请求。
25
+ - 代码结构清晰,易于扩展新的代理目标。
26
+ - 满足基本的性能要求。
memory-bank/systemPatterns.md ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 系统模式 (System Patterns)
2
+
3
+ ## 架构概述
4
+ 本项目将采用基于 FastAPI 的微服务架构。核心是一个 FastAPI 应用,负责接收所有进来的请求,并根据配置将请求转发到相应的后端服务。
5
+
6
+ ```mermaid
7
+ graph LR
8
+ Client --> Proxy[FastAPI Proxy]
9
+ Proxy --> BackendA[Backend Service A]
10
+ Proxy --> BackendB[Backend Service B]
11
+ Proxy --> BackendC[Backend Service C]
12
+ ```
13
+
14
+ ## 设计模式
15
+ - **API Gateway Pattern**: FastAPI 应用充当 API 网关,作为客户端访问后端服务的单一入口点。
16
+ - **Configuration Pattern**: 代理规则将通过配置文件进行管理,以便于修改和扩展。
17
+ - **Middleware Pattern**: 利用 FastAPI 的中间件功能处理请求和响应的通用逻辑(如日志、认证等)。
18
+
19
+ ## 关键组件
20
+ - **FastAPI Application**: 核心应用,处理路由和请求转发。
21
+ - **Configuration Loader**: 负责加载和解析代理规则配置文件。
22
+ - **HTTP Client**: 用于向后端服务发起请求(例如使用 `httpx` 库)。
23
+ - **Request/Response Transformer (Optional)**: 根据配置修改请求和响应。
24
+
25
+ ## 数据流
26
+ 1. 客户端发起请求到 FastAPI Proxy。
27
+ 2. FastAPI Proxy 接收请求。
28
+ 3. Configuration Loader 解析配置,查找匹配的代理规则。
29
+ 4. 如果找到匹配规则,HTTP Client 根据规则向后端服务发起请求。
30
+ 5. 后端服务返回响应。
31
+ 6. Request/Response Transformer (如果存在) 修改响应。
32
+ 7. FastAPI Proxy 将响应返回给客户端。
memory-bank/techContext.md ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 技术背景 (Tech Context)
2
+
3
+ ## 使用的技术
4
+ - **后端框架**: FastAPI (Python)
5
+ - **异步 HTTP 客户端**: httpx
6
+ - **配置管理**: 可能使用 `python-dotenv` 或其他配置库来加载配置文件。
7
+ - **依赖管理**: pip 和 requirements.txt
8
+ - **容器化**: Docker
9
+
10
+ ## 开发环境设置
11
+ 1. 克隆仓库。
12
+ 2. 创建并激活 Conda 虚拟环境 (`conda create -n api-proxy python=3.9` 或使用现有环境,然后 `conda activate api-proxy`)。
13
+ 3. 安装依赖 (`pip install -r requirements.txt`)。
14
+ 4. 运行应用 (`uvicorn app:app --reload`)。
15
+
16
+ ## 技术约束
17
+ - 需要 Python 3.7+。
18
+ - 依赖于 FastAPI 和 httpx 库。
19
+
20
+ ## 依赖关系
21
+ - `requirements.txt` 文件列出了所有必要的 Python 依赖。
22
+
23
+ ## 工具使用模式
24
+ - 使用 `uvicorn` 作为 ASGI 服务器运行 FastAPI 应用。
25
+ - 使用 `pip` 管理 Python 包。
26
+ - 使用 Docker 构建和运行容器。
push.sh ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ git add .
2
+ git commit -m "$(date)"
3
+ git push
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ fastapi
2
+ uvicorn[standard]
3
+ httpx