【免费下载链接】OctoPrint
OctoPrint is the snappy web interface for your 3D printer!
导读
本文围绕 OctoPrint 的 Settings API(/api/settings 及 /api/settings/templates)展开,系统讲解如何通过 REST 接口读取当前配置、增量更新设置、获取 UI 模板组件排序,以及 API 数据模型与 config.yaml 之间的映射关系。你将掌握三个端点的完整请求/响应格式、基于权限的敏感字段脱敏规则、条件请求缓存(ETag/Last-Modified)、敏感设置重新认证要求,以及插件设置经由 SettingsPlugin 挂载到该 API 的实现原理,可直接用于编写第三方客户端或自动化运维脚本。
一、Settings API 概览与定位
OctoPrint 的 Settings API 是 Web 界面“设置”对话框与后端配置之间的桥梁,提供三个核心端点:
| 端点 | 方法 | 用途 |
|---|---|---|
/api/settings | GET | 检索 OctoPrint 当前配置,返回 JSON 对象 |
/api/settings | POST | 保存(部分或完整)设置树,返回生效后的完整配置 |
/api/settings/templates | GET | 获取系统中所有已注册模板组件的排序数据(Beta) |
其实现位于 src/octoprint/server/api/settings.py,路由由 src/octoprint/server/api/init.py 中的 Flask Blueprint 注册。该 API 返回的 JSON 数据模型基本与 config.yaml 一一对应(详见下文第四节映射表),但并不是所有 config.yaml 字段都会暴露,且暴露程度取决于请求用户的权限。
调用该 API 前需要具备 OctoPrint 通用 API 认证知识:在非会话场景下,请求必须携带 API Key(通过 X-Api-Key 请求头、Authorization: Bearer <key> 或 apikey 查询参数),详见 docs/api/general.rst 的授权章节。
二、GET /api/settings:检索当前配置
GET /api/settings HTTP/1.1
Host: example.com
X-Api-Key: abcdef...
成功时返回 200,响应体为当前设置构成的 JSON 对象,结构与 config.yaml 基本一致。关键设计要点如下。
2.1 三级权限控制(2.0.0 起更细粒度)
从 2.0.0 版本开始,GET /api/settings 的权限检查被细化(对应文档中的 versionchanged:: 2.0.0 说明),由源码 getSettings() 中的检查体现:
SETTINGS_READ权限:可读取前端相关设置;SETTINGS权限:可读取后端相关设置;ADMIN权限:可读取访问控制(accessControl)与(已废弃的)全局 API Key 设置。
源码中对应的路径限制表 PATH_RESTRICTIONS(src/octoprint/server/api/settings.py)明确了各权限能接触到的子树:
| 权限 | 可访问路径 |
|---|---|
ADMIN | accessControl、api |
SETTINGS | devel、feature.pollWatched、folder、gcodeAnalysis.runAt、server、system、scripts、webcam.bitrate、webcam.ffmpegPath、webcam.ffmpegCommandline、webcam.ffmpegVideoCodec、webcam.ffmpegThreads、webcam.watermark |
CONTROL | controls |
TIMELAPSE_ADMIN | webcam.ffmpegPathConfigured |
此外,webcam.* 子树仅在请求用户拥有 WEBCAM 权限时返回(首次运行且未自定义用户时除外,见源码 getSettings() 中的分支判断)。
2.2 脱敏规则:null 与空列表
权限受限时,数据模型的整体结构仍然完整返回,只是受限字段的值被替换为脱敏默认值:
- 单值字段(singular values)→ 替换为
null; - 列表字段(lists)→ 替换为
[](空列表); - 字典字段 → 替换为
{}。
这一行为由 src/octoprint/server/util/flask.py 中的 apply_path_restrictions() 实现,其核心逻辑是:根据传入的 restrictions(权限 → 路径列表)逐路径判定,若当前用户不满足对应权限,则对叶节点执行替换(None / [] / {})。测试 tests/http_api/test_settings_api.py 的 test_user 用例验证了这一点:普通用户请求后,accessControl、api、devel、folder、server、system、scripts 等子树被整体脱敏,feature.pollWatched、gcodeAnalysis.runAt、webcam.bitrate、webcam.ffmpegPath 等敏感字段均被替换为 null。
2.3 条件请求缓存(ETag / Last-Modified)
GET /api/settings 通过 with_revalidation_checking 装饰器(实现见 src/octoprint/server/util/flask.py)提供 HTTP 缓存协商能力:
- Last-Modified:取
settings().last_modified时间戳; - ETag:由以下因素计算 SHA1 哈希(见源码
_etag())——最后修改时间、config.yaml生效配置、插件注入的额外设置、已启用插件列表、当前用户权限集合、用户最近凭据检查状态、以及SETTINGS_API_VERSION(当前为1)。
因此只要配置、插件列表、用户权限任一变化,ETag 就会失效,客户端可安全使用 If-None-Match / If-Modified-Since 头做增量同步。当配置未变化时,服务器返回 304 Not Modified(NOT_MODIFIED 响应)。
2.4 匿名与首次运行的特殊处理
若请求未携带有效凭据(匿名),且服务器正处于首次运行(server.firstRun 为 true)或用户管理器尚未自定义(userManager.has_been_customized() 为 false),则 GET /api/settings 仍允许访问(对应源码中 Permissions.SETTINGS_READ.can() 之外的豁免条件);否则匿名请求会收到 403。
三、数据模型:API 字段与 config.yaml 的映射
API 数据模型绝大部分直接映射 config.yaml 的内容,但存在以下例外与重映射(下表完整继承自官方文档,并结合源码 getSettings() 的构造逻辑核实):
| 字段 | 说明 |
|---|---|
accessControl.* | 仅映射 autologinLocal 和 autologinHeadsupAcknowledged,且仅对拥有 ADMIN 权限的用户返回。源码中还额外暴露了 defaultReauthenticationTimeout |
api.* | 仅映射 key 和 allowCrossOrigin,其中 key 仅对拥有 ADMIN 权限且通过近期凭据检查的用户返回 |
appearance.components | 不映射 |
controls.* | 仅对拥有 CONTROL 权限的用户返回 |
devel.* | 仅映射 pluginTimings |
estimation | 不映射 |
events.* | 不映射(但 events.subscriptions 由内置 EventManager 插件在自己的子树中映射) |
feature.gcodeViewer | 映射 config.yaml 中的 gcodeViewer.enabled |
feature.sizeThreshold | 映射 config.yaml 中的 gcodeViewer.sizeThreshold |
feature.mobileSizeThreshold | 映射 config.yaml 中的 gcodeViewer.mobileSizeThreshold |
folder.* | 仅映射 uploads、timelapse、watched |
gcodeAnalysis.* | 仅映射 runAt 和 bedZ |
gcodeViewer.enabled | 映射 feature.gcodeViewer |
gcodeViewer.sizeThreshold | 映射 feature.sizeThreshold |
gcodeViewer.mobileSizeThreshold | 映射 feature.mobileSizeThreshold |
plugins.* | 插件设置,来自 config.yaml 及 SettingsPlugin 实现;plugins._*(如 plugins._disabled)一律不映射 |
printerProfiles.* | 不映射,请使用专门的 printer profiles API |
serial.timeout.* | 映射 serial.timeout*(仅 API 版本 < 2.0.0 时返回,见下文) |
serial.maxCommunicationTimeouts.* | 映射 serial.maxTimeouts*(同上,仅旧版本) |
server.* | 仅映射 server.commands、server.diskspace、server.onlineCheck、server.pluginBlocklist、server.allowFraming;修改 server.commands 需要近期凭据检查 |
slicing.* | 仅映射 slicing.defaultslicer |
webcam.* | 仅对拥有 WEBCAM 权限的用户返回,大体映射 webcam.* |
webcam.ffmpeg | 映射 webcam.ffmpegPath |
webcam.ffmpegThumbnailCommandline | 不映射 |
webcam.timelapse | 不映射,请使用专门的 timelapse API |
webcam.cleanTmpAfterDays | 不映射 |
| 可用 webcam 提供商信息 | 映射 webcam.webcams[],每条目字段为:provider、name、displayName、canSnapshot、snapshotDisplay、flipH、flipV、rotate90、extras、compat.* |
默认 webcam 的 flipH、flipV、rotate90、name | 映射 webcam.flipH、webcam.flipV、webcam.rotate90、webcam.defaultWebcam |
默认 webcam 兼容层的 stream、streamRatio、streamTimeout、streamWebrtcIceServers、snapshot、snapshotTimeout、snapshotSslValidation、cacheBuster | 映射 webcam.* |
快照 webcam 的 name | 映射 webcam.snapshotWebcam |
注意:由于 2.0.0 起引入 API 版本协商(见 docs/api/general.rst),
getSettings()会根据请求头X-OctoPrint-Api-Version决定返回结构:请求版本 ≥ 2.0.0 时返回printerConnection.autoconnect,并提供feature.autoUppercaseBlocklist、server.pluginBlocklist;未声明版本(旧行为)时返回serial.*兼容子树、feature.autoUppercaseBlacklist、server.pluginBlacklist及system.events。这一分支行为同样被 tests/http_api/test_settings_api.py 的test_user与test_user_pre_2_0_0用例覆盖验证。
四、POST /api/settings:保存设置
POST /api/settings HTTP/1.1
Host: example.com
X-Api-Key: abcdef...
Content-Type: application/json
请求体为 JSON 对象,可以是完整的设置树,也可以是仅包含待更新字段的局部树——OctoPrint 只对出现过的字段做更新,未出现的字段保持原值。成功时返回 200 与当前生效的完整设置。
官方示例——仅把界面颜色改为黑色:
POST /api/settings HTTP/1.1
Host: example.com
X-Api-Key: abcdef...
Content-Type: application/json
{
"appearance": {
"color": "black"
}
}
响应(局部示例):
HTTP/1.1 200 OK
Content-Type: application/json
{
"api": {
"enabled": true
},
"appearance": {
"color": "black"
}
}
4.1 权限与基本校验
POST /api/settings 要求 SETTINGS 权限,且不允许首次运行(no_firstrun_access)状态下调用;请求体必须是 JSON 对象(dict),否则返回 400 Malformed JSON body in request(源码 setSettings())。
4.2 保存路径与字段级校验
_saveSettings()(src/octoprint/server/api/settings.py)按子树逐字段校验并写入,以下是值得注意的校验规则(可直接用于客户端参数校验):
folder:只接受uploads、timelapse、watched三类路径,且三者的目标路径不得两两重复,否则返回400;webcam.ffmpegCommandline:必须同时包含{ffmpeg}、{input}、{output}占位符,且能通过str.format求值,否则400;webcam.bitrate:必须匹配 ffmpeg 码率格式(正则\d+[KMGTPEZY]?i?B?,见源码常量TIMELAPSE_BITRATE_PATTERN),例如10M;webcam.ffmpegVideoCodec:仅接受mpeg2video或libx264;appearance.thumbnails.filelistAlignment:仅接受left、right、center;feature.notifySuppressedCommands:仅接受info、warn、never;temperature.profiles:bed与extruder会被尝试转为整数;cutoff必须大于1才写入;sendAutomaticallyAfter取值限定0–30;server.commands:写操作前需要近期凭据检查(见下一节);serial.*(旧 API 版本):supportResendsWithoutOk限always/detect/never,useParityWorkaround同理;各timeout*有min下限约束;controls:必须是列表,且每条目经 Pydantic 模型CustomControl/CustomControlContainer(src/octoprint/schema/config/controls.py)验证,存在无效条目时整批拒绝保存并记录错误日志。
所有校验通过后,最终调用 s.save(trigger_event=True) 持久化到 config.yaml 并触发相应事件。
4.3 旧版 webcam 字段的废弃提示
webcam.streamUrl、webcam.snapshotUrl、webcam.flipH 等旧字段(源码常量 DEPRECATED_WEBCAM_KEYS)已不再支持通过 API 直接设置——写入时仅记录 warning 日志,提示改用默认 webcam 的独立设置项;读取时这些键会以 null 占位,真实值从默认 webcam 的配置与兼容层(compat)映射而来(见 getSettings() 中 DEPRECATED_WEBCAM_KEYS 循环后的 defaultWebcam.config / compatWebcam 分支)。
五、敏感设置的重新认证要求
为保护 server.commands(关机/重启命令)、webcam.ffmpeg*(ffmpeg 路径与命令行)、accessControl.defaultReauthenticationTimeout、system.actions 等高危设置,POST 保存时若请求体包含这些路径,OctoPrint 会强制要求近期凭据检查(ensure_credentials_checked_recently()),未通过则拒绝写入。判定依据为源码中的 REAUTHED_SETTINGS 字典与 _reauth_requirements():
REAUTHED_SETTINGS = {
"accessControl": {"defaultReauthenticationTimeout": True},
"server": {"commands": True},
"webcam": {
"ffmpegPath": True,
"ffmpegCommandline": True,
"ffmpegThumbnailCommandline": True,
},
"system": {"actions": True},
}
插件可通过 SettingsPlugin.get_settings_reauth_requirements()(src/octoprint/plugin/types.py)声明自己的敏感路径,这些要求会与内置列表合并。客户端可先请求 GET /api/settings/reauthReq 查询当前需要重新认证的路径集合,再决定是否引导用户重新输入密码。
六、GET /api/settings/templates:模板组件数据(Beta)
GET /api/settings/templates HTTP/1.1
Host: example.com
X-Api-Key: abcdef...
该端点返回系统中所有已注册模板组件的排序数据(目前仅含排序顺序),可用于获取核心 OctoPrint 及所有已激活插件提供的 UI 组件标识符全集。请求支持 refresh 查询参数(?refresh=true 时强制重新扫描模板)。
需要管理员权限,否则返回 403。响应示例(完整结构):
HTTP/1.1 200 OK
Content-Type: application/json
{
"order": {
"about": [
{ "id": "about", "name": "About OctoPrint" },
{ "id": "supporters", "name": "Supporters" },
{ "id": "authors", "name": "Authors" },
{ "id": "changelog", "name": "Changelog" },
{ "id": "license", "name": "OctoPrint License" },
{ "id": "thirdparty", "name": "Third Party Licenses" },
{ "id": "plugin_pluginmanager", "name": "Plugin Licenses", "plugin_id": "pluginmanager", "plugin_name": "Plugin Manager" }
],
"generic": [
{ "id": "plugin_announcements", "name": "plugin_announcements", "plugin_id": "announcements", "plugin_name": "Announcement Plugin" }
],
"navbar": [
{ "id": "settings", "name": "settings" },
{ "id": "systemmenu", "name": "systemmenu" },
{ "id": "plugin_announcements", "name": "plugin_announcements", "plugin_id": "announcements", "plugin_name": "Announcement Plugin" },
{ "id": "login", "name": "login" }
],
"plugin_pluginmanager_about_thirdparty": [],
"settings": [
{ "id": "section_printer", "name": "Printer" },
{ "id": "serial", "name": "Serial Connection" },
{ "id": "printerprofiles", "name": "Printer Profiles" },
{ "id": "temperatures", "name": "Temperatures" },
{ "id": "terminalfilters", "name": "Terminal Filters" },
{ "id": "gcodescripts", "name": "GCODE Scripts" },
{ "id": "section_features", "name": "Features" },
{ "id": "features", "name": "Features" },
{ "id": "webcam", "name": "Webcam & Timelapse" },
{ "id": "accesscontrol", "name": "Access Control" },
{ "id": "gcodevisualizer", "name": "GCODE Visualizer" },
{ "id": "api", "name": "API" },
{ "id": "section_octoprint", "name": "OctoPrint" },
{ "id": "server", "name": "Server" },
{ "id": "folders", "name": "Folders" },
{ "id": "appearance", "name": "Appearance" },
{ "id": "plugin_logging", "name": "Logging", "plugin_id": "logging", "plugin_name": "Logging" },
{ "id": "plugin_pluginmanager", "name": "Plugin Manager", "plugin_id": "pluginmanager", "plugin_name": "Plugin Manager" },
{ "id": "plugin_softwareupdate", "name": "Software Update", "plugin_id": "softwareupdate", "plugin_name": "Software Update" },
{ "id": "plugin_announcements", "name": "Announcements", "plugin_id": "announcements", "plugin_name": "Announcement Plugin" },
{ "id": "section_plugins", "name": "Plugins" },
{ "id": "plugin_action_command_prompt", "name": "Action Command Prompt", "plugin_id": "action_command_prompt", "plugin_name": "Action Command Prompt Support" },
{ "id": "plugin_curalegacy", "name": "Cura Legacy", "plugin_id": "curalegacy", "plugin_name": "Cura Legacy" }
],
"sidebar": [
{ "id": "plugin_printer_safety_check", "name": "Printer Safety Warning", "plugin_id": "printer_safety_check", "plugin_name": "Printer Safety Check" },
{ "id": "connection", "name": "Connection" },
{ "id": "state", "name": "State" },
{ "id": "files", "name": "Files" }
],
"tab": [
{ "id": "temperature", "name": "Temperature" },
{ "id": "control", "name": "Control" },
{ "id": "gcodeviewer", "name": "GCode Viewer" },
{ "id": "terminal", "name": "Terminal" },
{ "id": "timelapse", "name": "Timelapse" }
],
"usersettings": [
{ "id": "access", "name": "Access" },
{ "id": "interface", "name": "Interface" }
],
"wizard": []
}
}
响应中每条目包含 id 与 name;若组件由插件提供,还会附带 plugin_id 与 plugin_name(源码 fetchTemplateData() 通过 pluginManager.get_plugin_info() 解析插件信息)。数据来源于 src/octoprint/server/views.py 的 fetch_template_data()。
⚠️ Beta 警告:官方文档明确提示该端点处于 beta 阶段,接口可能发生不兼容变更。如需基于它开发,建议先与项目维护者沟通,以便在出现向后不兼容变更时获得提前通知。
七、插件如何融入 Settings API
plugins.* 子树是 Settings API 的扩展点:任何实现 SettingsPlugin 的插件,其设置都会自动出现在 GET /api/settings 的 plugins.<plugin_identifier> 下,并接受 POST 的写入。机制如下(src/octoprint/plugin/types.py):
- 读取:
GET时后端遍历所有SettingsPlugin实现并调用on_settings_load(),默认实现返回插件设置全量数据(剔除_config_version键),并通过get_settings_restricted_paths()声明的受限路径执行脱敏——受限字段同样按null/[]/{}规则替换。插件若包含 API Key 等敏感信息,必须通过get_settings_restricted_paths()声明,因为即使匿名客户端也能收到 Settings API 的部分结构; - 写入:
POST时若请求体中含plugins.<id>,后端调用对应插件的on_settings_save(data)。默认实现会与插件默认值做最小差异合并(dict_minimal_mergediff),只持久化与默认值不同的部分; - 重认证:插件可通过
get_settings_reauth_requirements()声明需要近期凭据检查的敏感路径。
这一机制也解释了为什么 GET /api/settings 的 ETag 计算中会包含插件设置与插件列表——插件的增删会直接改变 API 返回结构。
八、快速实战:用 curl 操作 Settings API
以下示例假设 API Key 为 abcdef,服务器位于 http://localhost:8080。
1. 读取当前配置(携带 2.0.0 版本协商头):
curl -H "X-Api-Key: abcdef" \
-H "X-OctoPrint-Api-Version: 2.0.0" \
http://localhost:8080/api/settings
2. 仅修改界面颜色(局部树):
curl -X POST http://localhost:8080/api/settings \
-H "X-Api-Key: abcdef" \
-H "Content-Type: application/json" \
-H "X-OctoPrint-Api-Version: 2.0.0" \
-d '{"appearance": {"color": "black"}}'
3. 启用 CORS(跨域请求支持):
curl -X POST http://localhost:8080/api/settings \
-H "X-Api-Key: abcdef" \
-H "Content-Type: application/json" \
-H "X-OctoPrint-Api-Version: 2.0.0" \
-d '{"api": {"allowCrossOrigin": true}}'
4. 利用 ETag 做条件请求(仅配置变更时才返回完整数据):
curl -H "X-Api-Key: abcdef" \
-H "X-OctoPrint-Api-Version: 2.0.0" \
-I http://localhost:8080/api/settings
# 取出 ETag 后:
curl -H "X-Api-Key: abcdef" \
-H "X-OctoPrint-Api-Version: 2.0.0" \
-H "If-None-Match: <etag值>" \
http://localhost:8080/api/settings
# 配置未变化时返回 304
5. 查询模板组件排序(需管理员):
curl -H "X-Api-Key: abcdef" \
-H "X-OctoPrint-Api-Version: 2.0.0" \
http://localhost:8080/api/settings/templates
九、测试与验证参考
仓库中 tests/http_api/test_settings_api.py 是理解该 API 行为的最佳实证材料,核心覆盖点包括:
- 权限脱敏:
test_user断言普通用户视角下accessControl、api、devel、folder、server、system、scripts子树整体脱敏,且feature.pollWatched、gcodeAnalysis.runAt、webcam.bitrate、webcam.ffmpegPath、webcam.ffmpegCommandline、webcam.ffmpegThreads、webcam.watermark均为null; - 插件子树脱敏:
plugins.serial_connector中仅log与ignoreEmptyPorts对普通用户可见(_not_none),其余字段脱敏;plugins.discovery中仅upnpUuid、model可见; - API 版本协商:
test_user(带X-OctoPrint-Api-Version: 2.0.0)与test_user_pre_2_0_0(不带)分别验证了printerConnectionvsserial、autoUppercaseBlocklistvsautoUppercaseBlacklist、pluginBlocklistvspluginBlacklist、system.events的有无; - 管理员视图:
test_admin验证ADMIN用户可读取accessControl三项与api.allowCrossOrigin,并确认api.key已在 2.1.0 移除。
结语
OctoPrint Settings API 是程序化管理打印机配置的标准化入口:GET /api/settings 提供带权限脱敏与缓存协商的配置读取,POST /api/settings 支持最小化局部更新并内置字段级校验与重认证保护,/api/settings/templates 则暴露 UI 组件注册信息。结合本文的数据模型映射表、权限矩阵与源码级行为说明,你可以安全地构建自己的配置管理客户端、自动化部署脚本或集成到监控系统中,而不必直接解析 config.yaml 文件。
【免费下载链接】OctoPrint
OctoPrint is the snappy web interface for your 3D printer!
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



