From be37192bf9c75b34d532ca0db4e66233aef05e69 Mon Sep 17 00:00:00 2001 From: Lxy Date: Thu, 12 Mar 2026 21:59:24 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=8E=BB=E9=99=A4akshare=E7=AD=89?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- API_DOCUMENTATION.md | 769 ++++++++++++++++++ API_KLINE_RESPONSE.md | 2 +- QUICKSTART.md | 4 +- app/__pycache__/main.cpython-311.pyc | Bin 64360 -> 64344 bytes app/api/__pycache__/routes.cpython-311.pyc | Bin 15300 -> 15420 bytes app/api/routes.py | 5 +- app/core/__pycache__/config.cpython-311.pyc | Bin 8896 -> 8932 bytes app/core/config.py | 17 +- app/main.py | 4 +- app/models/__pycache__/types.cpython-311.pyc | Bin 22082 -> 22077 bytes app/models/types.py | 4 +- .../__pycache__/database.cpython-311.pyc | Bin 1709 -> 2043 bytes app/repositories/database.py | 14 +- .../adapter_service.cpython-311.pyc | Bin 13553 -> 13556 bytes app/services/adapter_service.py | 2 +- config.json | 31 +- init_mysql.py | 2 +- scripts/migrate_add_kline_fields.py | 2 +- scripts/migrate_add_trade_date.py | 2 +- test_adapters.py | 2 +- test_adapters2.py | 2 +- test_klines_api.py | 2 +- test_klines_extended_fields.py | 4 +- test_source.py | 2 +- tests/test_xysz_integration.py | 4 +- venv/Scripts/activate | 2 +- venv/Scripts/activate.bat | 2 +- venv/pyvenv.cfg | 2 +- 28 files changed, 830 insertions(+), 50 deletions(-) create mode 100644 API_DOCUMENTATION.md diff --git a/API_DOCUMENTATION.md b/API_DOCUMENTATION.md new file mode 100644 index 0000000..5520f11 --- /dev/null +++ b/API_DOCUMENTATION.md @@ -0,0 +1,769 @@ +# 行情数据服务 API 文档 + +> 版本:v1.0.0 +> 更新时间:2026-03-11 + +## 目录 + +- [概述](#概述) +- [认证方式](#认证方式) +- [股票接口](#股票接口) +- [期货接口](#期货接口) +- [管理接口](#管理接口) +- [WebSocket 实时行情](#websocket-实时行情) +- [数据模型](#数据模型) +- [错误码](#错误码) + +--- + +## 概述 + +### 基础信息 + +| 项目 | 说明 | +|------|------| +| 协议 | HTTP/1.1 或 HTTP/2 | +| 数据格式 | JSON | +| 字符编码 | UTF-8 | +| 日期格式 | YYYYMMDD (如:20260301) | +| 时间戳格式 | ISO 8601 (如:2026-03-01T09:30:00) | + +### 基础 URL + +``` +http://:8080/v1 +``` + +### 通用响应结构 + +所有接口返回统一的响应格式: + +```json +{ + "code": 0, // 状态码,0表示成功 + "message": "success", // 提示信息 + "data": {} // 响应数据(具体结构见各接口) +} +``` + +--- + +## 认证方式 + +API 使用 `X-API-Key` 请求头进行认证(健康检查接口除外)。 + +```http +X-API-Key: YOUR_API_KEY +``` + +**响应示例(认证失败):** + +```json +{ + "detail": "Missing API Key" +} +``` + +--- + +## 股票接口 + +### 1. 查询股票K线 + +获取指定股票的K线数据。 + +**请求信息:** + +| 项目 | 说明 | +|------|------| +| 方法 | GET | +| 路径 | `/stock/klines/{symbol}` | +| 认证 | 需要 | + +**路径参数:** + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| symbol | string | 是 | 标的代码,如 `000001.SZ` | + +**查询参数:** + +| 参数 | 类型 | 必填 | 默认值 | 说明 | +|------|------|------|--------|------| +| start | string | 是 | - | 开始日期 YYYYMMDD | +| end | string | 是 | - | 结束日期 YYYYMMDD | +| freq | string | 否 | `1d` | 周期:`1m`, `5m`, `15m`, `30m`, `60m`, `1d`, `1w`, `1month` | +| adjust | string | 否 | - | 复权类型:`qfq`(前复权), `hfq`(后复权),空值为不复权 | + +**请求示例:** + +```bash +curl -X GET "http://localhost:8080/v1/stock/klines/000001.SZ?start=20250301&end=20250310&freq=1d&adjust=qfq" \ + -H "X-API-Key: YOUR_API_KEY" +``` + +**响应示例:** + +```json +{ + "code": 0, + "message": "success", + "data": { + "symbol": "000001.SZ", + "name": "平安银行", + "freq": "1d", + "adjust": "qfq", + "count": 8, + "items": [ + { + "symbol": "000001.SZ", + "time": "2026-03-01T00:00:00", + "open": 10.50, + "high": 10.80, + "low": 10.40, + "close": 10.65, + "volume": 1500000, + "amount": 15975000.00, + "trade_date": "2026-03-01", + "is_limit_up": false, + "is_limit_down": false, + "total_market_cap": 250000000000.00, + "float_market_cap": 200000000000.00, + "inst_holding_ratio": 25.5, + "trading_days": 5200 + } + ] + } +} +``` + +--- + +### 2. 批量查询股票K线 + +批量查询多只股票的K线数据。 + +**请求信息:** + +| 项目 | 说明 | +|------|------| +| 方法 | POST | +| 路径 | `/stock/klines/batch` | +| 认证 | 需要 | + +**请求体:** + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| symbols | array | 是 | 标的代码列表,最多100只 | +| start | string | 是 | 开始日期 YYYYMMDD | +| end | string | 是 | 结束日期 YYYYMMDD | +| freq | string | 否 | 周期,默认 `1d` | +| adjust | string | 否 | 复权类型 | + +**请求示例:** + +```bash +curl -X POST "http://localhost:8080/v1/stock/klines/batch" \ + -H "X-API-Key: YOUR_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "symbols": ["000001.SZ", "000002.SZ"], + "start": "20250301", + "end": "20250310", + "freq": "1d" + }' +``` + +**响应示例:** + +```json +{ + "code": 0, + "message": "success", + "data": { + "results": [ + { + "symbol": "000001.SZ", + "success": true, + "error": null, + "data": { + "count": 8, + "items": [...] + } + }, + { + "symbol": "000002.SZ", + "success": false, + "error": "symbol not found", + "data": null + } + ] + } +} +``` + +--- + +### 3. 查询股票列表 + +获取所有可用股票标的。 + +**请求信息:** + +| 项目 | 说明 | +|------|------| +| 方法 | GET | +| 路径 | `/stock/symbols` | +| 认证 | 需要 | + +**查询参数:** + +| 参数 | 类型 | 必填 | 默认值 | 说明 | +|------|------|------|--------|------| +| exchange | string | 否 | - | 交易所筛选:`SZ`, `SH`, `BJ` | +| keyword | string | 否 | - | 关键词搜索(代码或名称) | +| page | integer | 否 | 1 | 页码 | +| size | integer | 否 | 20 | 每页数量,最大100 | + +**响应示例:** + +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 5000, + "page": 1, + "size": 20, + "items": [ + { + "symbol_id": "000001.SZ", + "symbol_type": "stock", + "exchange": "SZ", + "name": "平安银行", + "name_en": "Ping An Bank", + "list_date": "1991-04-03T00:00:00", + "industry": "银行", + "status": "active" + } + ] + } +} +``` + +--- + +### 4. 查询股票交易日历 + +获取指定日期范围内的交易日。 + +**请求信息:** + +| 项目 | 说明 | +|------|------| +| 方法 | GET | +| 路径 | `/stock/trading-dates` | +| 认证 | 需要 | + +**查询参数:** + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| start | string | 是 | 开始日期 YYYYMMDD | +| end | string | 是 | 结束日期 YYYYMMDD | + +**响应示例:** + +```json +{ + "code": 0, + "message": "success", + "data": { + "start": "20250301", + "end": "20250310", + "total_days": 10, + "trading_days": 7, + "trading_dates": ["20250301", "20250302", "20250303", "20250306", "20250307", "20250310"] + } +} +``` + +--- + +## 期货接口 + +### 1. 查询期货K线 + +获取指定期货合约的K线数据。 + +**请求信息:** + +| 项目 | 说明 | +|------|------| +| 方法 | GET | +| 路径 | `/futures/klines/{symbol}` | +| 认证 | 需要 | + +**路径参数:** + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| symbol | string | 是 | 合约代码,如 `CU2504.SHFE` | + +**查询参数:** + +| 参数 | 类型 | 必填 | 默认值 | 说明 | +|------|------|------|--------|------| +| start | string | 是 | - | 开始日期 YYYYMMDD | +| end | string | 是 | - | 结束日期 YYYYMMDD | +| freq | string | 否 | `1d` | 周期 | + +**响应示例:** + +```json +{ + "code": 0, + "message": "success", + "data": { + "symbol": "CU2504.SHFE", + "name": "沪铜2504", + "freq": "1d", + "adjust": "", + "count": 10, + "items": [ + { + "symbol": "CU2504.SHFE", + "time": "2026-03-01T00:00:00", + "open": 69000.00, + "high": 69500.00, + "low": 68800.00, + "close": 69200.00, + "volume": 12500, + "amount": 865000000.00, + "open_interest": 45000 + } + ] + } +} +``` + +--- + +### 2. 批量查询期货K线 + +**请求信息:** + +| 项目 | 说明 | +|------|------| +| 方法 | POST | +| 路径 | `/futures/klines/batch` | +| 认证 | 需要 | + +**请求体:** 同股票批量查询 + +--- + +### 3. 查询期货列表 + +**请求信息:** + +| 项目 | 说明 | +|------|------| +| 方法 | GET | +| 路径 | `/futures/symbols` | +| 认证 | 需要 | + +**查询参数:** + +| 参数 | 类型 | 必填 | 默认值 | 说明 | +|------|------|------|--------|------| +| exchange | string | 否 | - | 交易所:`CFFEX`, `SHFE`, `DCE`, `CZCE`, `INE`, `GFEX` | +| underlying | string | 否 | - | 品种筛选,如 `CU`, `RB` | +| keyword | string | 否 | - | 关键词搜索 | +| page | integer | 否 | 1 | 页码 | +| size | integer | 否 | 20 | 每页数量 | + +--- + +### 4. 查询期货交易日历 + +**请求信息:** + +| 项目 | 说明 | +|------|------| +| 方法 | GET | +| 路径 | `/futures/trading-dates` | +| 认证 | 需要 | + +--- + +### 5. 获取品种合约列表 + +获取指定品种的所有可交易合约。 + +**请求信息:** + +| 项目 | 说明 | +|------|------| +| 方法 | GET | +| 路径 | `/futures/contracts` | +| 认证 | 需要 | + +**查询参数:** + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| underlying | string | 是 | 品种代码,如 `CU`, `RB` | +| exchange | string | 否 | 交易所筛选 | + +**响应示例:** + +```json +{ + "code": 0, + "message": "success", + "data": { + "underlying": "CU", + "count": 12, + "items": [ + { + "symbol_id": "CU2504.SHFE", + "symbol_type": "futures", + "exchange": "SHFE", + "name": "沪铜2504", + "underlying": "CU", + "contract_month": "2504", + "list_date": "2024-04-16T00:00:00", + "delist_date": "2025-04-15T00:00:00", + "status": "active" + } + ] + } +} +``` + +--- + +### 6. 查询主力连续合约K线(预留) + +**请求信息:** + +| 项目 | 说明 | +|------|------| +| 方法 | GET | +| 路径 | `/futures/continuous/{underlying}` | +| 认证 | 需要 | + +**路径参数:** + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| underlying | string | 是 | 品种代码 | + +**查询参数:** 同期货K线查询 + +> 注:当前返回空数据,功能预留 + +--- + +## 管理接口 + +### 1. 健康检查 + +检查服务健康状态(无需认证)。 + +**请求信息:** + +| 项目 | 说明 | +|------|------| +| 方法 | GET | +| 路径 | `/admin/health` | +| 认证 | 不需要 | + +**响应示例:** + +```json +{ + "status": "healthy", + "timestamp": "2026-03-11T08:30:00" +} +``` + +--- + +### 2. 获取数据源状态 + +获取当前数据源配置和状态。 + +**请求信息:** + +| 项目 | 说明 | +|------|------| +| 方法 | GET | +| 路径 | `/admin/source/status` | +| 认证 | 需要 | + +**响应示例:** + +```json +{ + "code": 0, + "message": "success", + "data": { + "stock": { + "active_source": "custom", + "standby_sources": [], + "status": "healthy" + }, + "futures": { + "active_source": "custom", + "standby_sources": [], + "status": "healthy" + } + } +} +``` + +--- + +### 3. 切换数据源 + +切换股票/期货的数据源。 + +**请求信息:** + +| 项目 | 说明 | +|------|------| +| 方法 | POST | +| 路径 | `/admin/source/switch` | +| 认证 | 需要 | + +**请求体:** + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| asset_class | string | 是 | 资产类别:`stock`, `futures`, `all` | +| source | string | 是 | 目标数据源名称 | +| sync_backfill | boolean | 否 | 是否同步补录 | +| start_date | string | 否 | 补录开始日期 YYYYMMDD | + +**请求示例:** + +```bash +curl -X POST "http://localhost:8080/v1/admin/source/switch" \ + -H "X-API-Key: YOUR_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "asset_class": "all", + "source": "custom", + "sync_backfill": false + }' +``` + +--- + +### 4. 历史数据补录 + +启动历史数据补录任务。 + +**请求信息:** + +| 项目 | 说明 | +|------|------| +| 方法 | POST | +| 路径 | `/admin/backfill` | +| 认证 | 需要 | + +**请求体:** + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| asset_class | string | 是 | 资产类别 | +| symbols | array | 是 | 标的列表,空数组表示全部 | +| start | string | 是 | 开始日期 YYYYMMDD | +| end | string | 是 | 结束日期 YYYYMMDD | +| freqs | array | 是 | 需要补录的周期列表 | +| source | string | 否 | 指定数据源 | + +--- + +## WebSocket 实时行情 + +### 连接信息 + +| 项目 | 说明 | +|------|------| +| URL | `ws://:8080/v1/stream` | +| 协议 | WebSocket | +| 认证 | 通过 `X-API-Key` Header | + +### 连接示例 + +```javascript +const ws = new WebSocket('ws://localhost:8080/v1/stream'); +ws.onopen = () => { + // 订阅股票行情 + ws.send(JSON.stringify({ + action: 'subscribe', + symbols: ['000001.SZ', '000002.SZ'] + })); +}; +ws.onmessage = (event) => { + const data = JSON.parse(event.data); + console.log(data); +}; +``` + +### 消息格式 + +**客户端 → 服务器(订阅):** + +```json +{ + "action": "subscribe", + "symbols": ["000001.SZ", "CU2504.SHFE"] +} +``` + +**客户端 → 服务器(取消订阅):** + +```json +{ + "action": "unsubscribe", + "symbols": ["000001.SZ"] +} +``` + +**服务器 → 客户端(行情推送):** + +```json +{ + "type": "tick", + "symbol": "000001.SZ", + "time": "2026-03-11T09:30:00.123", + "price": 10.65, + "volume": 1000, + "amount": 10650.00 +} +``` + +--- + +## 数据模型 + +### K线周期 (Frequency) + +| 值 | 说明 | +|------|------| +| `1m` | 1分钟 | +| `5m` | 5分钟 | +| `15m` | 15分钟 | +| `30m` | 30分钟 | +| `60m` | 60分钟 | +| `1d` | 日线 | +| `1w` | 周线 | +| `1month` | 月线 | + +### 复权类型 (AdjustType) + +| 值 | 说明 | +|------|------| +| `` | 不复权 | +| `qfq` | 前复权 | +| `hfq` | 后复权 | + +### 交易所 (Exchange) + +**股票交易所:** + +| 值 | 说明 | +|------|------| +| `SZ` | 深交所 | +| `SH` | 上交所 | +| `BJ` | 北交所 | + +**期货交易所:** + +| 值 | 说明 | +|------|------| +| `CFFEX` | 中金所 | +| `SHFE` | 上期所 | +| `DCE` | 大商所 | +| `CZCE` | 郑商所 | +| `INE` | 上期能源 | +| `GFEX` | 广期所 | + +### K线数据字段 (KLineItem) + +| 字段 | 类型 | 说明 | +|------|------|------| +| symbol | string | 标的代码 | +| time | datetime | 时间戳 | +| open | float | 开盘价 | +| high | float | 最高价 | +| low | float | 最低价 | +| close | float | 收盘价 | +| volume | int | 成交量(股/手) | +| amount | float | 成交额(元) | +| open_interest | int | 持仓量(期货特有) | +| settlement | float | 结算价(期货特有) | +| adj_factor | float | 复权系数(股票特有) | +| trade_date | string | 交易日 YYYY-MM-DD | +| is_limit_up | boolean | 是否涨停(股票) | +| is_limit_down | boolean | 是否跌停(股票) | +| total_market_cap | float | 总市值(元) | +| float_market_cap | float | 流通市值(元) | +| inst_holding_ratio | float | 机构持仓占比(%) | +| trading_days | int | 可交易日数 | + +--- + +## 错误码 + +| 状态码 | 说明 | +|--------|------| +| 200 | 成功 | +| 401 | 未认证(缺少 API Key) | +| 422 | 请求参数错误 | +| 500 | 服务器内部错误 | +| 503 | 服务不可用 | + +**业务错误码:** + +| code | 说明 | +|------|------| +| 0 | 成功 | +| 1001 | 标的不存在 | +| 1002 | 日期格式错误 | +| 1003 | 频率不支持 | +| 2001 | 数据源连接失败 | +| 2002 | 数据源切换失败 | + +--- + +## 附录 + +### 常用标的代码示例 + +**股票:** + +| 代码 | 名称 | +|------|------| +| `000001.SZ` | 平安银行 | +| `000002.SZ` | 万科A | +| `600000.SH` | 浦发银行 | +| `600519.SH` | 贵州茅台 | + +**期货:** + +| 代码 | 名称 | +|------|------| +| `CU2504.SHFE` | 沪铜2504 | +| `RB2505.SHFE` | 螺纹钢2505 | +| `M2505.DCE` | 豆粕2505 | +| `CF2505.CZCE` | 棉花2505 | + +--- + +**文档结束** diff --git a/API_KLINE_RESPONSE.md b/API_KLINE_RESPONSE.md index 32203d3..b9bfdb7 100644 --- a/API_KLINE_RESPONSE.md +++ b/API_KLINE_RESPONSE.md @@ -163,5 +163,5 @@ python test_klines_api.py ```bash curl -X GET "http://localhost:8080/v1/stock/klines/000001.SZ?start=20260301&end=20260310&freq=1d" \ - -H "X-API-Key: demo-api-key-2024" + -H "X-API-Key: YOUR_API_KEY" ``` diff --git a/QUICKSTART.md b/QUICKSTART.md index 0840d5f..b74c8a9 100644 --- a/QUICKSTART.md +++ b/QUICKSTART.md @@ -269,13 +269,13 @@ curl http://localhost:8080/v1/admin/health # 查询股票K线 curl "http://localhost:8080/v1/stock/klines/000001.SZ?start=20250301&end=20250307&freq=1d" \ - -H "X-API-Key: demo-api-key-2024" + -H "X-API-Key: YOUR_API_KEY" # 热加载配置 curl -X POST http://localhost:8080/v1/admin/system/reload # WebSocket测试 -wscat -c ws://localhost:8080/v1/stream -H "X-API-Key: demo-api-key-2024" +wscat -c ws://localhost:8080/v1/stream -H "X-API-Key: YOUR_API_KEY" > {"action":"subscribe","symbols":["000001.SZ"]} ``` diff --git a/app/__pycache__/main.cpython-311.pyc b/app/__pycache__/main.cpython-311.pyc index ca6054d5803371cd1c62cf877797f89fdb8b5da7..2a5ef0167b0b302ad9e099d431b49b3755484102 100644 GIT binary patch delta 142 zcmV;90CE55_5;}V0}ZDQ4GI7N005$$v1x;`4QmMjuCsXwp;rPYJCmXG9J5JbK~FMc zb#ruYZ663{G8Xn9fChfyQ@um1EiHYaTu)8pwCho(xGv}Ur z<~!$p=iIxax85!OvZ$zlgWv5t--lnU`>wdPFm(!EKjvh#ZvHNi>{DLmNwSV}2{J(X zxN%N$$@v*O#|`8SSiZ5&f#=s*?@MHy>*IWUvJw2&zM6cn_+IDh-9nEz_VCu^%Ips- zQwwV!Os)R7kiNWINiTe|GP9VTo=Zy^n0{szjfb#GOAE8gepM=DPjiX(M&j%ujP{2PLr^8Yr!2T}m*t-YT zD$%JOV1i3KT$Am~j@orDkKcRGS-Ir&&h#wVy??OIqF;$uaTbq|@&<6Fm;-G>*oV-} zt~wh@6}#(f-EX>%PWusB0MvXW9S(}Bg^DBe5Nj@}aM$2M=}1zfV}41F2Z#N`k#J0u zXeTUq*_&JQp$7pEfHexNwwi4mW*NZ8EuYG$v;~O@ej)7v1 zoehHPoiOmQZ_$N;jG3ML!$Od;`C$A~CszH*{B=i;%`9CrQzib|*xam~{vpgKSIL#t&O$HjzO` zNKUeQ!av%vs@7N_Dr!?h<%98LOjh}@EJmeVYx*o|K_HQ6jK&8`cv0J_IkfnN$-c9_4<`333`oy?Lj>LiSL~(CajU$)V6Q zuweKmOL?mK3t(SnpL?#5b4p9?DN?QR*Q8-8XEy&#i*XulCarDCrD`^V9!-uEOjU61Rn&PynL*wwO!G<#8`-PN1n{o7cfbbmLQ80^p>T4g3t_==D;vKL_GDN2s z4Z+To`imr?G(X!#99u{IM1#<6Aa6c6@!r=5z*b44F`0o1WvyY3z>PQEwCkWDs70@c zc0?VpL9zfq9rP-UVhDsf<$jZekRg`d*O#KzXl_S<*5yOTv41Hx8bxJORGfCcdbPEpXr%FrH#q9Sb-bN6>}}9r$%uG_zRz*W&F168 bV<+Y79KcLyR=O6|9*y8uJT2GkRt)nW!8YTH delta 2134 zcma)7UuauZ7|&UH+t4O4?b6z=n%pf7@%B&bR^4=|b| ze}3oYo43yTuljtQF8t!(Y-hK$8~%jXJBrf_uD4yh+hF4F;gGoK?bzE^^`ZEe>+k;j z$;MOjv+A6_CVuqB4>M3ut}z(EfinbkXMXzVa)u|*mLSK=skFXaNI_0F##T~BYK-gf zMpi8Pjs?QFxt~r&5zf257dL%hv55JOzruPo6u~gT2m!eSVAhGJWPMhKc z4^oGe>$BnKn(rX9!LZ%nOi-;D>3(#`|{#R8KEoJ!Xmj0gw&m6Ir(5|hE(EMfY411xZl^>|-2(Q19G zy{6h`u3@Qt*Aj%pdwn70ITS3JH~K6VZq&&+*z5h;jLn>zVbIXUn#9uEsDjSx zef1J9y(R7pUSf0R#se9)F01}BIr4ux2lws9(L;x337q2Ss`ZnT=H_6I<8fQc9q&jm zpXElf9t>YAyjIF{ID^(d5Z6MN*_1gKj{C@$UP0-$ z_)a~?=Ea%)f5}=~ZN*eUmwaF;=~A_5SW4E=3%qf~G`H26DwpGh(u$5AChJBu56E0J zx>d4DBNuWfbv$qFIh0uUSE}Oc1AWR0PCgUA9Vjr>T#n4J7oR8f|JiXt+O^2~ xR9d39aK|%=7pI!nr+{skmTvWg8a2ZzqvWF>1iV^{{VLFk~RPU diff --git a/app/api/routes.py b/app/api/routes.py index 2189e05..7621c19 100644 --- a/app/api/routes.py +++ b/app/api/routes.py @@ -22,7 +22,10 @@ config = get_config() # 认证依赖 def verify_api_key(x_api_key: Optional[str] = Header(None)): - """验证API Key""" + """验证API Key,根据配置决定是否启用""" + if not config.server.auth_enabled: + # 认证已禁用,跳过验证 + return x_api_key or "anonymous" if not x_api_key: raise HTTPException(status_code=401, detail="Missing API Key") # TODO: 验证API Key有效性 diff --git a/app/core/__pycache__/config.cpython-311.pyc b/app/core/__pycache__/config.cpython-311.pyc index 51ef055881cd83f24f93b75a58e6a1ec8ab924fa..b3995bf21964d8d44d974678141eb3def51a4d18 100644 GIT binary patch delta 2420 zcmbtWUuauZ7|%^^Z_@m2yR>P$rp?$|cb(}bYiS#6Yu9#D=GscOwK_H2ZAHOwVW6NQ2-?C#5Cy;Q+=g_qdk~X*e>vy- z&iVeI@8rwLA13`D_1i8>{FS%V`UXoT&w3BVMSg+i9iJLZHrHs%bm zZyk}IX5++4{EpZR&xY7sZVMYvuN}A}hT+-Z2m{)&?h}6%2KS?+0|@&NdV_h%f~@H#o+AJj?*cCOD*w2iKd7)UdX32^S#4aC6`o{ktcyyG3=55Wf&U@ z1ZMGgn9g)bFHxdR$@RNd0hS-dU|0d;2lg49)}(y`X$V8?-N34q%n8=p@SC4kngp4F zs-r#ZP~(}{{bg@96br>tR?$f!xs>4fs}UYY;d1~lvdYlFYgrC zQTS=3XK=*rJ&PkQd^d&2n1xrn1yHG9_+@iVA6pK_!NE4xz31U%{1S%96ZNdEfL|Nb-CqDA&AYz6pM zvPjen)o2zsJ7LJnA&=_{ND|dju4uY*1(jqIIF=n&TSOZu1*p-lDHljZzX9xvxTFkV z*nSkHS598Hzu|l3+^z;9b{O9hVHWnJEw1{!6duIJD5bA=b2)kk^fpTH?UQd~2?Ke%HCGI)S_ zRbl`shJ>Oo+=!ZZ|LGcrG?%hugkEKLyH*~q6FN6-|Aw`pEu`M7vKrQ3k3{Vv9+rOq D@n;Na delta 2246 zcmbtVO>7%g5Z<-7>wh~xc4DWF?I>;NMsez-L~$LOmeLSV8;2yNG!>P#jW@=P9b0dm zKq5#CsA{4H1bPCM0}?mrg&$c$y?~GqclQF;9uP>t1%VtXsDcwSZxh)u=75NIzs#HW zX6BoD@6G-+@zsR$Lx;o4!QU%Cf13WY}V!`#+q>{~r z<$OB4q^yO9Bg2nsCKx4P6ql^jZ=4fazzf|lUge*n-x)`b_7x|$=E_1JJP#OxKzy)< z*l5n;E6oaJJ{rPt4?+OJfzS&e88tywGK-`i2AWA(UQMi!jB12YC=?=H^qM%xchPNe zc@tg6B`0Zx|D+9}9l?#joOYtrfxz5*PzoWixEM_{=SeQFkir@n#0f6~quPa%{{Yat zdKaKr`_Wa?n<885$Fyj#IltMB1{gd2E4X4|wf%4g&}xR{jksj{Z;Tn)Q|P#X-4N;! zj=`(W0Z@a#mhXFQ<}nLDochp^#oxNEB9ULME*i;*z~-zGu|Qm4HmZ{=`%Qs zFbuCc1v%fcy4u@|)0MVh@yV?x%0dvH2SSjF_OMR%4BMVr`@`Tk*l0#IxkS)f6QYr5 zWZg4(az6u_as);FOwt|4i7+b_Rz)%pM)w@Z_Y5pNt4DpI=#P%$30$mB0~EP0>=l>) z2fOe6*heE3e*hnESH&Bs1V$>oQq^IKIjfuwe%CH%^1JpBsz!^`T0LSvE$(svdkDq- zGa03dbFKRVxF;788cK5sbo6(JcXJYi0~Q1Si^UkS7(*6g2P`zx;!0tKC~91?G~HM; zJD0FC`abCw5Np!N_dMzlqV#Lmw!T;AX{6mpms-AcvJ)h#3W3u^dg*lQv$ne9Oh0Mu z@HON=gZ{1nT&Lf+2KU>8t2swpYD1VsU_F9ec5DjlP7%CMj2*d*5_8@xAWmRV^*%s- zdw99+V?C#tQl!0uclV(i>@u3^@n@b+T%4FEE%cgu=1^Lny8}(rN`PI8{^sssX)!jE zupCcKD%((ubU<`j}r(oyy`uGx`eoj;4cgG4bOXeTJv zyIHpu@^aw?O;lcjYp;?S`mpl^zd%D?PbYR$&6df@$;3i#c`=c*E1mMC zcySRFBt<{yI-X|E%vpI!Nv4TPZlbXX#AP|FkPNQNqDn}vWb>Len@cL01j>?8?_mqL zBo9#gY~XsEDz7RB@i##8VrlT`eg5PoE=N8jjc|CAHET*K92mU{^RH1)_bBh9Q{5NN zqNT*MpeheCe4hX{t6DR89Ta!qRdGv-Tvg;;p5i3_h>w=LQxO(;-w_h8cjO>Sea&vc z^xHHQ2txSVf$Pt)?P{QFN4gNd03BH+x545rI&}gRxj#hC?%s~=#L9w)edd7t4VaOF z`d1UnO8V(o@cEnUHVomIbz#`fb+^|dp6DP=+k!YyuU*^YP m+g38lIN70mXsch~AE|Qxgtt!bqIRz~