✨ feat(api): 统一响应格式并完善参数体系与文档
- 正文参数支持语义值(plain/html/keep/remove)与别名(img_mode/review_mode),URL 参数优先于配置 - 修复纯文本被段评强制包回 HTML、HTML 模式段评注入失效的问题 - 修复 PKCS7 填充弱校验导致漫画/正文偶发解密乱码返回 200 的问题 - 搜索结果展平:去 search_tabs 层与 selected_tab_idx/server_ab_params,提升 has_more/next_offset - 全接口解包字符串形式的 JSON 字段(category_schema 等),缓存出口幂等处理 - 序列化关闭 HTML 转义,video/audio 播放链接可直接复制播放 - video 响应透传 CENC 加密状态(key_seed/kid/encryption_method) - 新增 gzip 中间件,JSON/文本响应压缩约 81%,二进制透传 - 漫画默认输出模式改为 proxy(url 模式链接 404 且内容加密不可用) - openapi.yaml:补全 23 个路径参数定义、tab_type 完整枚举、CDN 签名说明,示例更新
This commit is contained in:
1 parent
bfb4290c15
commit
1a4997e031
25 files changed
+489
-199
No files matched your search
+167
-31
@@ -98,7 +98,7 @@ paths:
|
||||
required: true
|
||||
description: 搜索关键字(别名 `key`)
|
||||
schema: { type: string }
|
||||
example: 斗罗大陆
|
||||
example: 综漫
|
||||
- name: key
|
||||
in: query
|
||||
description: "`query` 的别名,`query` 为空时生效"
|
||||
@@ -110,17 +110,38 @@ paths:
|
||||
example: 0
|
||||
- name: tab_type
|
||||
in: query
|
||||
description: 搜索类型,默认 3;响应 search_tabs 仅保留匹配该值的 tab
|
||||
schema: { type: integer, default: 3 }
|
||||
description: |
|
||||
搜索类型,默认 3;仅返回匹配该值的 tab:
|
||||
* `1` 综合(混合:书籍 + 运营位 cell_data + 猜你喜欢 guess_you_like_data)
|
||||
* `2` 听书(book_data)
|
||||
* `3` 书籍(book_data,默认)
|
||||
* `4` 社区(topic_data)
|
||||
* `5` 全文(book_data)
|
||||
* `6` 用户(search_user_data)
|
||||
* `8` 漫画(book_data)
|
||||
* `11` 短剧(video_data)
|
||||
schema: { type: integer, default: 3, enum: [1, 2, 3, 4, 5, 6, 8, 11] }
|
||||
example: 3
|
||||
responses:
|
||||
"200":
|
||||
description: 搜索结果(search_tabs 已按请求的 tab_type 过滤,仅保留匹配项)
|
||||
description: 搜索结果(tab 已展平:结果块在顶层 data,并提升 has_more/next_offset 分页字段)
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/UpstreamResponse"
|
||||
example: { code: 0, msg: success, data: { search_book_data_list: [], has_more: 1 } }
|
||||
$ref: "#/components/schemas/SearchResponse"
|
||||
example:
|
||||
code: 0
|
||||
message: SUCCESS
|
||||
data:
|
||||
- book_data:
|
||||
- book_id: "7668727260244872254"
|
||||
book_name: 综漫:今天的告白,我也很期待哦
|
||||
author: 一念1浮生
|
||||
abstract: (评分五天从7.5涨到9.0,真的不看看吗,前期有点青涩,往后会好一点)……
|
||||
category: 动漫衍生
|
||||
word_number: "357281"
|
||||
has_more: 1
|
||||
next_offset: 10
|
||||
|
||||
"400":
|
||||
$ref: "#/components/responses/BadRequest"
|
||||
@@ -165,13 +186,18 @@ paths:
|
||||
/catalog:
|
||||
get:
|
||||
tags: [书籍]
|
||||
summary: 获取章节目录
|
||||
summary: 获取章节目录(book_id → 每章 item_id)
|
||||
description: |
|
||||
传入 book_id,返回全部章节列表 `data.item_data_list[]`,
|
||||
每项含 `item_id`、`title`、`chapter_word_number`、`volume_name`。
|
||||
item_id 用于调用 /content、/multi-content、/item-summary、/audio、/manga、/video 等
|
||||
需要 item_id 的接口;漫画/短剧的每集(话)item_id 也从这里获取。
|
||||
operationId: getBookCatalog
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/BookId"
|
||||
responses:
|
||||
"200":
|
||||
description: 章节目录(上游转发)
|
||||
description: 章节目录(上游转发,含每章 item_id)
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/UpstreamResponse" }
|
||||
@@ -226,8 +252,10 @@ paths:
|
||||
tags: [内容]
|
||||
summary: 获取章节正文
|
||||
description: |
|
||||
返回章节正文。启用段评(`review=1` 或配置 `fanqie.content.enable_review: true`)时,
|
||||
正文 HTML 中会注入段评标记。
|
||||
返回章节正文。启用段评(`review=keep` 或配置 `fanqie.content.enable_review: true`)时,
|
||||
正文 HTML 中会注入段评标记;纯文本输出(text_mode=plain 或配置 remove_html_tags: true)
|
||||
时不注入段评标记(<comment> 为 XML 标签,纯文本无法承载)。
|
||||
URL 参数优先于配置文件。
|
||||
operationId: getItemContent
|
||||
parameters:
|
||||
- name: item_id
|
||||
@@ -238,18 +266,18 @@ paths:
|
||||
example: "7271032589123412345"
|
||||
- name: text_mode
|
||||
in: query
|
||||
description: 纯文本模式,1/true=纯文本,0/false=HTML
|
||||
schema: { type: string, enum: ["0", "1", "true", "false"] }
|
||||
example: "0"
|
||||
description: 文本模式,plain/1/true=纯文本,html/0/false=HTML;缺省用配置 remove_html_tags
|
||||
schema: { type: string, enum: ["plain", "html", "0", "1", "true", "false"] }
|
||||
example: "plain"
|
||||
- name: image_mode
|
||||
in: query
|
||||
description: 图片处理,1/true=保留图片,0/false=移除图片
|
||||
schema: { type: string, enum: ["0", "1", "true", "false"] }
|
||||
example: "1"
|
||||
description: 图片处理,keep/1/true=保留,remove/0/false=移除(别名 `img_mode`);缺省用配置 remove_images 取反
|
||||
schema: { type: string, enum: ["keep", "remove", "0", "1", "true", "false"] }
|
||||
example: "keep"
|
||||
- name: review
|
||||
in: query
|
||||
description: 段评开关,1=启用,0=禁用;缺省时使用配置文件
|
||||
schema: { type: string, enum: ["0", "1"] }
|
||||
description: 段评开关,keep/1=启用,remove/0=禁用(别名 `review_mode`);缺省用配置 enable_review
|
||||
schema: { type: string, enum: ["keep", "remove", "0", "1"] }
|
||||
responses:
|
||||
"200":
|
||||
description: 章节正文
|
||||
@@ -291,12 +319,12 @@ paths:
|
||||
example: "7271032589123412345,7271032589123412346"
|
||||
- name: text_mode
|
||||
in: query
|
||||
description: 纯文本模式,1/true=纯文本
|
||||
schema: { type: string, enum: ["0", "1", "true", "false"] }
|
||||
description: 文本模式,plain/1/true=纯文本,html/0/false=HTML;缺省用配置 remove_html_tags
|
||||
schema: { type: string, enum: ["plain", "html", "0", "1", "true", "false"] }
|
||||
- name: image_mode
|
||||
in: query
|
||||
description: 图片处理,1/true=保留
|
||||
schema: { type: string, enum: ["0", "1", "true", "false"] }
|
||||
description: 图片处理,keep/1/true=保留,remove/0/false=移除(别名 `img_mode`);缺省用配置 remove_images 取反
|
||||
schema: { type: string, enum: ["keep", "remove", "0", "1", "true", "false"] }
|
||||
- name: ignore_failed
|
||||
in: query
|
||||
description: 忽略失败章节,1/true=在结果中跳过而非报错
|
||||
@@ -381,12 +409,24 @@ paths:
|
||||
example: 0
|
||||
- name: book_id
|
||||
in: query
|
||||
description: 书籍 ID
|
||||
description: 书籍 ID(实际必传,缺省时上游返回 101003 错误)
|
||||
schema: { type: string }
|
||||
- name: comment_id
|
||||
in: query
|
||||
description: 评论 ID(获取回复时需要)
|
||||
schema: { type: string }
|
||||
- name: sort
|
||||
in: query
|
||||
description: 排序方式,默认 1(热门)
|
||||
schema: { type: integer, default: 1 }
|
||||
- name: offset
|
||||
in: query
|
||||
description: 分页偏移量,默认 0
|
||||
schema: { type: integer, default: 0, minimum: 0 }
|
||||
- name: count
|
||||
in: query
|
||||
description: 每页数量,默认 20
|
||||
schema: { type: integer, default: 20, minimum: 1 }
|
||||
responses:
|
||||
"200":
|
||||
description: 评论/回复数据
|
||||
@@ -416,6 +456,22 @@ paths:
|
||||
description: 段落索引(从 0 开始)
|
||||
schema: { type: integer, minimum: 0 }
|
||||
example: 0
|
||||
- name: book_id
|
||||
in: query
|
||||
description: 书籍 ID
|
||||
schema: { type: string }
|
||||
- name: page
|
||||
in: query
|
||||
description: 页码,默认 1
|
||||
schema: { type: integer, default: 1, minimum: 1 }
|
||||
- name: page_size
|
||||
in: query
|
||||
description: 每页数量,默认 20
|
||||
schema: { type: integer, default: 20, minimum: 1 }
|
||||
- name: sort
|
||||
in: query
|
||||
description: 排序方式,默认 1(热门)
|
||||
schema: { type: integer, default: 1 }
|
||||
responses:
|
||||
"200":
|
||||
description: 评论 HTML 页面
|
||||
@@ -492,12 +548,17 @@ paths:
|
||||
get:
|
||||
tags: [多媒体]
|
||||
summary: 获取视频信息
|
||||
description: |
|
||||
短剧视频流为 CENC 加密(encrypt=true, cenc-aes-ctr, HEVC+AAC):
|
||||
播放 URL 可直接下载,但文件本身加密,通用播放器无法解码。
|
||||
响应透传加密状态字段:顶层 key_seed(Base64,每次请求变化)、
|
||||
video_list.*.encrypt/encryption_method/kid,供需要对接官方播放器的调用方使用。
|
||||
operationId: getVideo
|
||||
parameters:
|
||||
- name: item_ids
|
||||
in: query
|
||||
required: true
|
||||
description: 章节 ID
|
||||
description: 视频 ID,多个用逗号分隔;短剧每集的 item_id 从 /catalog 获取
|
||||
schema: { type: string }
|
||||
responses:
|
||||
"200":
|
||||
@@ -517,9 +578,15 @@ paths:
|
||||
description: |
|
||||
返回漫画章节内容,图片经解密处理。
|
||||
输出模式 `output` 优先于配置 `fanqie.manga.output_mode`:
|
||||
- `url`: 返回原始图片 URL 数组
|
||||
- `proxy`: 返回本地代理 URL(/manga/image/{item_id}/{index})
|
||||
- `url`: 返回原始图片 URL 数组(不可用:链接 404 且内容加密,仅作上游原始信息展示)
|
||||
- `proxy`: 返回本地代理 URL(/manga/image/{item_id}/{index})——推荐,先调本接口再访问代理 URL(缓存 5 分钟)
|
||||
- `data_uri`: 返回 Base64 编码(data:image/jpeg;base64,...)
|
||||
|
||||
CDN 链接说明(全接口通用):带 `x-signature` 签名的图片/音视频 URL 可直接 GET,
|
||||
但不可修改 URL 任何部分(改尺寸模板/去参数即 403,签名覆盖整个 path)。
|
||||
`x-expires` 为过期时间戳:图片约 30 天,音频约 2 小时,短剧视频约 6 小时,
|
||||
过期后重新调用相应接口获取新 URL。无签名的 `audio_thumb_uri`/`horiz_thumb_url` 字段
|
||||
为上游占位链接,不可用;封面请使用 `thumb_url`/`audio_thumb_url_hd`。
|
||||
operationId: getManga
|
||||
parameters:
|
||||
- name: item_ids
|
||||
@@ -619,22 +686,30 @@ paths:
|
||||
get:
|
||||
tags: [分类]
|
||||
summary: 获取分类详情页
|
||||
description: 支持按分类筛选、排序与分页的书籍列表。
|
||||
description: 支持按分类筛选、排序与分页的书籍列表(每页固定 20 条)。
|
||||
operationId: getCategoryLanding
|
||||
parameters:
|
||||
- name: category_id
|
||||
in: query
|
||||
required: true
|
||||
description: 分类 ID
|
||||
description: 分类 ID(可从 /category-front 或搜索结果 book_data.category_schema 中解析)
|
||||
schema: { type: string }
|
||||
- name: offset
|
||||
in: query
|
||||
description: 偏移量,默认 0
|
||||
schema: { type: integer, default: 0, minimum: 0 }
|
||||
- name: limit
|
||||
- name: word_number
|
||||
in: query
|
||||
description: 每页数量,默认 20
|
||||
schema: { type: integer, default: 20, minimum: 1 }
|
||||
description: 字数筛选,透传上游(0=不限)
|
||||
schema: { type: integer, default: 0 }
|
||||
- name: book_status
|
||||
in: query
|
||||
description: 连载状态筛选,透传上游(0=不限)
|
||||
schema: { type: integer, default: 0 }
|
||||
- name: sort_by
|
||||
in: query
|
||||
description: 排序方式,透传上游(0=默认)
|
||||
schema: { type: integer, default: 0 }
|
||||
responses:
|
||||
"200":
|
||||
description: 分类书籍列表(上游转发)
|
||||
@@ -736,6 +811,67 @@ components:
|
||||
type: string
|
||||
description: 错误信息
|
||||
|
||||
SearchResponse:
|
||||
type: object
|
||||
description: |
|
||||
搜索响应(已展平:原上游 `search_tabs[0]` 中的 `data` 提升为顶层 `data`,
|
||||
并提升分页字段 `has_more`/`next_offset`;`search_tabs` 字段不再返回)。
|
||||
required: [code, data]
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
description: 0=成功
|
||||
example: 0
|
||||
message:
|
||||
type: string
|
||||
example: SUCCESS
|
||||
data:
|
||||
type: array
|
||||
description: |
|
||||
搜索结果块,单个元素的 *_data 字段由 tab_type 决定:
|
||||
`book_data`(tab_type 1/2/3/5/8:书籍/听书/全文/漫画,含 book_id/book_name/author/abstract 等)、
|
||||
`topic_data`(tab_type 4 社区,含 title/comment)、
|
||||
`search_user_data`(tab_type 6 用户,含 encode_user_id/is_author)、
|
||||
`video_data`(tab_type 11 短剧)、
|
||||
`cell_data`/`guess_you_like_data`(tab_type 1 的运营位与猜你喜欢)。
|
||||
所有元素均附带 book_hot_content_data 等上游字段,以实际返回为准。
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
book_data:
|
||||
type: array
|
||||
description: 书籍结果(tab_type 1/2/3/5)
|
||||
items: { type: object }
|
||||
topic_data:
|
||||
type: array
|
||||
description: 话题结果(tab_type 4)
|
||||
items: { type: object }
|
||||
search_user_data:
|
||||
type: array
|
||||
description: 用户结果(tab_type 6)
|
||||
items: { type: object }
|
||||
video_data:
|
||||
type: array
|
||||
description: 短剧结果(tab_type 11)
|
||||
items: { type: object }
|
||||
cell_data:
|
||||
type: array
|
||||
description: 运营位(tab_type 1 混合出现)
|
||||
items: { type: object }
|
||||
guess_you_like_data:
|
||||
type: array
|
||||
description: 猜你喜欢(tab_type 1 混合出现)
|
||||
items: { type: object }
|
||||
has_more:
|
||||
type: integer
|
||||
description: 是否还有更多结果(1=有)
|
||||
example: 1
|
||||
next_offset:
|
||||
type: integer
|
||||
description: 下一页 offset 值
|
||||
example: 10
|
||||
log_id:
|
||||
type: string
|
||||
UpstreamResponse:
|
||||
type: object
|
||||
description: |
|
||||
|
||||
Reference in new issue
Block a user