From da1922c7cb6ade90d19bdb75a1ffdd6c21b7dbbe Mon Sep 17 00:00:00 2001 From: xisoul Date: Sun, 10 May 2026 15:28:29 +0800 Subject: [PATCH 1/3] feat: add custom User-Agent configuration support for S3 clients MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增可选自定义User-Agent配置项,默认留空,不影响任何原有功能 - 新增userAgent字段到S3OsProperties,默认空字符串 - 配置表单新增自定义UA输入框,附带中国科技云适配提示 - S3Client构建逻辑添加UA头注入,仅当配置非空时生效 - README文档更新:新增UA配置说明、中国科技云兼容性条目 - 完全向后兼容,默认行为和原版完全一致 --- README.md | 8 +++++++- .../run/halo/s3os/S3OsAttachmentHandler.java | 9 ++++++--- src/main/java/run/halo/s3os/S3OsProperties.java | 6 ++++++ .../extensions/policy-template-s3os.yaml | 17 ++++++++++------- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 6dc35ab..a77b787 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,11 @@ * **加随机字母后缀:** 如遇重名,会在文件名后加上4位的随机字母后缀,例如`image.png`会变成`image_abcd.png`。 * **报错不上传** 如遇重名,会放弃上传,并在用户界面提示 Duplicate filename 错误。 +### 自定义User-Agent +可选配置项,仅当您的S3服务提供商要求校验客户端UA时填写,默认留空不影响任何原有功能。 + +> 例如中国科技云数据胶囊要求密钥必须绑定应用,绑定Rclone应用后此处需要填写`rclone/v1.67.0`才能正常访问。 + ## 部分对象存储服务商兼容性 |服务商|文档|兼容访问风格|兼容性| @@ -149,8 +154,9 @@ |Cloudflare||Virtual Hosted Style /
Path Style|✅| | Oracle Cloud ||Virtual Hosted Style /
Path Style|✅| |又拍云||Virtual Hosted Style /
Path Style|✅| -|自建minio|\-|Path Style|✅| +|自建minio|\\-|Path Style|✅| |华为云|文档未说明是否兼容,工单反馈不保证兼容性,实际测试可以使用|Virtual Hosted Style|❓| +|中国科技云数据胶囊||Path Style|✅| |Ucloud|只支持 8MB 大小的分片,本插件暂不支持
|\-|❌| ## 开发环境 diff --git a/src/main/java/run/halo/s3os/S3OsAttachmentHandler.java b/src/main/java/run/halo/s3os/S3OsAttachmentHandler.java index cf4af2c..df4673a 100644 --- a/src/main/java/run/halo/s3os/S3OsAttachmentHandler.java +++ b/src/main/java/run/halo/s3os/S3OsAttachmentHandler.java @@ -307,7 +307,7 @@ Attachment buildAttachment(S3OsProperties properties, ObjectDetail objectDetail) } S3Client buildS3Client(S3OsProperties properties) { - return S3Client.builder() + var builder = S3Client.builder() .region(Region.of(properties.getRegion())) .endpointOverride( URI.create(properties.getEndpointProtocol() + "://" + properties.getEndpoint())) @@ -316,8 +316,11 @@ S3Client buildS3Client(S3OsProperties properties) { .serviceConfiguration(S3Configuration.builder() .chunkedEncodingEnabled(false) .pathStyleAccessEnabled(properties.getEnablePathStyleAccess()) - .build()) - .build(); + .build()); + if (StringUtils.isNotBlank(properties.getUserAgent())) { + builder.overrideConfiguration(config -> config.putHeader("User-Agent", properties.getUserAgent())); + } + return builder.build(); } private S3Presigner buildS3Presigner(S3OsProperties properties) { diff --git a/src/main/java/run/halo/s3os/S3OsProperties.java b/src/main/java/run/halo/s3os/S3OsProperties.java index 3d10e4a..d096feb 100644 --- a/src/main/java/run/halo/s3os/S3OsProperties.java +++ b/src/main/java/run/halo/s3os/S3OsProperties.java @@ -48,6 +48,12 @@ public class S3OsProperties { private String region = "Auto"; + /** + * Custom User-Agent header for S3 requests, optional. + * Useful for services that validate client application binding like CSTCloud. + */ + private String userAgent = ""; + private List urlSuffixes; private String thumbnailParamPattern; diff --git a/src/main/resources/extensions/policy-template-s3os.yaml b/src/main/resources/extensions/policy-template-s3os.yaml index 25943d7..dc7811f 100644 --- a/src/main/resources/extensions/policy-template-s3os.yaml +++ b/src/main/resources/extensions/policy-template-s3os.yaml @@ -50,9 +50,9 @@ spec: - $formkit: text name: endpoint label: EndPoint - placeholder: 请填写不带 bucket name 的 Endpoint + placeholder: 请填写不带bucket-name的Endpoint validation: required - help: 协议头请在上方设置,此处无需以 "http://" 或"https://"开头,系统会自动拼接 + help: 协议头请在上方设置,此处无需以"http://"或"https://"开头,系统会自动拼接 - $formkit: password name: accessKey label: Access Key ID @@ -68,6 +68,11 @@ spec: label: Region placeholder: 如不填写,则默认为 Auto help: 若 Region 为 Auto 无法使用,才需要填写对应 Region,Cloudflare R2 需要填写均为小写字母的 auto + - $formkit: text + name: userAgent + label: 自定义User-Agent + placeholder: 如Rclone、S3Drive等,留空则使用默认值 + help: 部分对象存储服务(如中国科技云数据胶囊)会校验请求客户端类型,绑定Rclone应用后此处填`rclone/v1.67.0`即可正常使用 - $formkit: text name: location label: 上传目录 @@ -75,8 +80,6 @@ spec: help: 支持的占位符请查阅:https://github.com/halo-dev/plugin-s3#上传目录 - $formkit: select name: randomFilenameMode - key: randomFilenameMode - id: randomFilenameMode label: 上传时重命名文件方式 options: - label: 保留原文件名 @@ -102,13 +105,13 @@ spec: label: 随机字母长度 min: 4 max: 16 - if: "$get(randomFilenameMode).value == 'dateWithString' || $get(randomFilenameMode).value == 'datetimeWithString' || $get(randomFilenameMode).value == 'withString' || $get(randomFilenameMode).value == 'string'" + if: "$randomFilenameMode == 'dateWithString' || $randomFilenameMode == 'datetimeWithString' || $randomFilenameMode == 'withString' || $randomFilenameMode == 'string'" help: 支持4~16位, 默认为8位 - $formkit: text name: customTemplate key: customTemplate label: 自定义文件名模板 - if: "$get(randomFilenameMode).value == 'custom'" + if: "$randomFilenameMode == 'custom'" value: "${origin-filename}" help: 支持的占位符请查阅:https://github.com/halo-dev/plugin-s3#自定义文件名模板 - $formkit: select @@ -135,7 +138,7 @@ spec: name: domain label: 绑定域名(CDN域名) placeholder: 如不设置,那么将使用 Bucket + EndPoint 作为域名 - help: 协议头请在上方设置,此处无需以 "http://" 或 "https://" 开头,系统会自动拼接 + help: 协议头请在上方设置,此处无需以"http://"或"https://"开头,系统会自动拼接 - $formkit: repeater name: urlSuffixes label: 网址后缀 From b3b78b11d12d7b177c3cff2913093448e82894eb Mon Sep 17 00:00:00 2001 From: XiSoul Date: Mon, 11 May 2026 09:26:57 +0800 Subject: [PATCH 2/3] feat: add optional custom User-Agent header for S3 requests Add an optional 'User-Agent' configuration field that allows users to specify a custom User-Agent header for S3 requests. This is needed for S3-compatible services like CSTCloud Data Capsule that validate client application binding on access keys. Changes: - Add 'userAgent' field to S3OsProperties (default: empty, no behavior change) - Inject custom User-Agent header in S3Client when configured - Add User-Agent input to the admin configuration form - Add CSTCloud Data Capsule to compatibility table - Add User-Agent configuration documentation to README --- README.md | 9 +++++---- .../run/halo/s3os/S3OsAttachmentHandler.java | 3 ++- .../extensions/policy-template-s3os.yaml | 18 ++++++++++-------- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index a77b787..2cfecc3 100644 --- a/README.md +++ b/README.md @@ -134,10 +134,11 @@ * **加随机字母后缀:** 如遇重名,会在文件名后加上4位的随机字母后缀,例如`image.png`会变成`image_abcd.png`。 * **报错不上传** 如遇重名,会放弃上传,并在用户界面提示 Duplicate filename 错误。 -### 自定义User-Agent -可选配置项,仅当您的S3服务提供商要求校验客户端UA时填写,默认留空不影响任何原有功能。 +### 自定义 User-Agent -> 例如中国科技云数据胶囊要求密钥必须绑定应用,绑定Rclone应用后此处需要填写`rclone/v1.67.0`才能正常访问。 +可选配置项,仅当您的 S3 服务提供商要求校验客户端 UA 时填写,默认留空不影响任何原有功能。 + +> 例如中国科技云数据胶囊要求密钥必须绑定应用,绑定 Rclone 应用后此处需要填写 `rclone/v1.67.0` 才能正常访问。 ## 部分对象存储服务商兼容性 @@ -154,7 +155,7 @@ |Cloudflare||Virtual Hosted Style /
Path Style|✅| | Oracle Cloud ||Virtual Hosted Style /
Path Style|✅| |又拍云||Virtual Hosted Style /
Path Style|✅| -|自建minio|\\-|Path Style|✅| +|自建minio|\-|Path Style|✅| |华为云|文档未说明是否兼容,工单反馈不保证兼容性,实际测试可以使用|Virtual Hosted Style|❓| |中国科技云数据胶囊||Path Style|✅| |Ucloud|只支持 8MB 大小的分片,本插件暂不支持
|\-|❌| diff --git a/src/main/java/run/halo/s3os/S3OsAttachmentHandler.java b/src/main/java/run/halo/s3os/S3OsAttachmentHandler.java index df4673a..34b1178 100644 --- a/src/main/java/run/halo/s3os/S3OsAttachmentHandler.java +++ b/src/main/java/run/halo/s3os/S3OsAttachmentHandler.java @@ -318,7 +318,8 @@ S3Client buildS3Client(S3OsProperties properties) { .pathStyleAccessEnabled(properties.getEnablePathStyleAccess()) .build()); if (StringUtils.isNotBlank(properties.getUserAgent())) { - builder.overrideConfiguration(config -> config.putHeader("User-Agent", properties.getUserAgent())); + builder.overrideConfiguration(config -> + config.putHeader("User-Agent", properties.getUserAgent())); } return builder.build(); } diff --git a/src/main/resources/extensions/policy-template-s3os.yaml b/src/main/resources/extensions/policy-template-s3os.yaml index dc7811f..4a4a33f 100644 --- a/src/main/resources/extensions/policy-template-s3os.yaml +++ b/src/main/resources/extensions/policy-template-s3os.yaml @@ -50,9 +50,9 @@ spec: - $formkit: text name: endpoint label: EndPoint - placeholder: 请填写不带bucket-name的Endpoint + placeholder: 请填写不带 bucket name 的 Endpoint validation: required - help: 协议头请在上方设置,此处无需以"http://"或"https://"开头,系统会自动拼接 + help: 协议头请在上方设置,此处无需以 "http://" 或"https://"开头,系统会自动拼接 - $formkit: password name: accessKey label: Access Key ID @@ -70,9 +70,9 @@ spec: help: 若 Region 为 Auto 无法使用,才需要填写对应 Region,Cloudflare R2 需要填写均为小写字母的 auto - $formkit: text name: userAgent - label: 自定义User-Agent - placeholder: 如Rclone、S3Drive等,留空则使用默认值 - help: 部分对象存储服务(如中国科技云数据胶囊)会校验请求客户端类型,绑定Rclone应用后此处填`rclone/v1.67.0`即可正常使用 + label: 自定义 User-Agent + placeholder: 如 Rclone、S3Drive 等,留空则使用默认值 + help: 部分对象存储服务(如中国科技云数据胶囊)会校验请求客户端类型,绑定 Rclone 应用后此处填`rclone/v1.67.0` 即可正常使用 - $formkit: text name: location label: 上传目录 @@ -80,6 +80,8 @@ spec: help: 支持的占位符请查阅:https://github.com/halo-dev/plugin-s3#上传目录 - $formkit: select name: randomFilenameMode + key: randomFilenameMode + id: randomFilenameMode label: 上传时重命名文件方式 options: - label: 保留原文件名 @@ -105,13 +107,13 @@ spec: label: 随机字母长度 min: 4 max: 16 - if: "$randomFilenameMode == 'dateWithString' || $randomFilenameMode == 'datetimeWithString' || $randomFilenameMode == 'withString' || $randomFilenameMode == 'string'" + if: "$get(randomFilenameMode).value == 'dateWithString' || $get(randomFilenameMode).value == 'datetimeWithString' || $get(randomFilenameMode).value == 'withString' || $get(randomFilenameMode).value == 'string'" help: 支持4~16位, 默认为8位 - $formkit: text name: customTemplate key: customTemplate label: 自定义文件名模板 - if: "$randomFilenameMode == 'custom'" + if: "$get(randomFilenameMode).value == 'custom'" value: "${origin-filename}" help: 支持的占位符请查阅:https://github.com/halo-dev/plugin-s3#自定义文件名模板 - $formkit: select @@ -138,7 +140,7 @@ spec: name: domain label: 绑定域名(CDN域名) placeholder: 如不设置,那么将使用 Bucket + EndPoint 作为域名 - help: 协议头请在上方设置,此处无需以"http://"或"https://"开头,系统会自动拼接 + help: 协议头请在上方设置,此处无需以 "http://" 或 "https://" 开头,系统会自动拼接 - $formkit: repeater name: urlSuffixes label: 网址后缀 From 0513bcd9cb1e60e116ef626591e3f77645adbf49 Mon Sep 17 00:00:00 2001 From: Ryan Wang Date: Mon, 11 May 2026 18:36:51 +0800 Subject: [PATCH 3/3] Update src/main/resources/extensions/policy-template-s3os.yaml --- src/main/resources/extensions/policy-template-s3os.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/extensions/policy-template-s3os.yaml b/src/main/resources/extensions/policy-template-s3os.yaml index 4a4a33f..26a5e3f 100644 --- a/src/main/resources/extensions/policy-template-s3os.yaml +++ b/src/main/resources/extensions/policy-template-s3os.yaml @@ -72,7 +72,7 @@ spec: name: userAgent label: 自定义 User-Agent placeholder: 如 Rclone、S3Drive 等,留空则使用默认值 - help: 部分对象存储服务(如中国科技云数据胶囊)会校验请求客户端类型,绑定 Rclone 应用后此处填`rclone/v1.67.0` 即可正常使用 + help: 部分对象存储服务(如中国科技云数据胶囊)会校验请求客户端类型,绑定 Rclone 应用后此处填 `rclone/v1.67.0` 即可正常使用 - $formkit: text name: location label: 上传目录