Nebula 一直有预签名分享链接:给对象签一个带过期时间的临时 URL,谁拿到都能下载,到点自动失效。很适合「发给同事看一下」这种临时场景。

但有些资源你想长期公开——网站的图片、公开的下载包、CDN 回源。给它签一个 24 小时后失效的链接就不合适了。这次补上另一半:把对象设为公开读,拿一个永久直链

两种链接,原理根本不同

它们看着都是「一个能下载的 URL」,底层却是两码事:

预签名链接——URL 里带着签名(?X-Amz-Signature=…&X-Amz-Expires=…)。对象本身是私有的,是这个签名临时授权了访问,过期后签名失效、链接就废了。所以它能给私有对象用,但一定会过期。

公共直链——就是对象的原始 URL,不带任何签名(https://{bucket}.{endpoint}/{key})。它能不能访问,取决于对象本身的权限:对象是「公开读」就能下,是「私有」就 403。所以它不会过期,但前提是对象得公开。

一句话:预签名是「给私有对象临时开个口」,公共直链是「对象本来就开着」。 前者授权在 URL 里,后者授权在对象上。

设为公开读:一个预置 ACL

「设为公开读」落到底层,是给对象设一个预置 ACL(canned ACL)——PUT /{key}?acl 带一个头:

x-amz-acl: public-read      # AWS / MinIO / 七牛
x-oss-object-acl: public-read   # 阿里 OSS
x-obs-acl: public-read      # 华为 OBS
x-cos-acl: public-read      # 腾讯 COS

各家头名不同,但都是「把 public-read 这个预置值塞进 ?acl 这个受签名的子资源」。private 则收回公开。七家统一走 trait 的 set_object_acl(path, public),适配层把布尔映射成对应厂商的头。

有个签名上的坑值得一提:这个请求要同时?acl 子资源和 x-*-acl都计入签名——子资源进 CanonicalizedResource,x-*-acl 进 CanonicalizedHeaders。已有的 set_content_type(签头不签子资源)和分片(签子资源不签头)都只覆盖一半,所以这里是内联把两者拼齐。

公共直链:纯拼接,可测

公共直链没有任何网络请求、也没有签名,就是拼一个 URL:

pub fn public_url(&self, bucket: &str, key: &str) -> String {
    // 路径风格:{scheme}://{endpoint}/{bucket}/{encoded_key},按桶路由到其区域
    let (endpoint, _) = self.route(&object_uri(bucket, key));
    format!("{}://{}{}", self.scheme(), endpoint, object_uri(bucket, key))
}

因为是纯函数,直接单测钉死(含 key 的 URL 编码、按桶区域路由)。它顺带又白捡了按桶区域路由——route 会把 endpoint 解析到桶所在区域,所以跨区域桶的直链也指向对的 host。

界面上,对象右键多了「设为公开读 / 设为私有」和「复制公共链接」,和原来的「分享链接」并列。想临时发一下用分享链接(会过期),想长期公开就设公开读 + 复制直链(不过期)。

走你自己的域名

默认直链是云商的域名({bucket}.oss-cn-…),但公开资源你多半想走自己的域名 / CDN(cdn.example.com)。所以账号可选配一个「公共域名」:配了之后,复制公共链接就拼成 https://{你的域名}/{key}——域名绑定到桶,故省掉路径里的桶名段,key 照常百分号编码。这一步在 app-core 里做,provider 不用知道域名的存在。

批量公开 / 私有

托管一批静态资源时,常常想一次把整批设成公开读(或反过来收回)。所以多选对象后可以批量设 ACL:对选中项逐个调预置 ACL 的接口,带进度与取消,完成后报告改了几项。和批量标签一样,这里没有新机制——只是把单对象的「设为公开读 / 私有」套了个循环,让「上架一整个目录的资源」从逐个点变成一次操作。

小结

「分享一个对象」有两种截然不同的做法,取决于你要的是临时还是长期:预签名把授权写进 URL(会过期、可用于私有对象),公共直链靠对象自身权限(不过期、需公开读)。补齐后者,只是加一个预置 ACL(注意子资源和头都要签)和一个纯拼接的 URL——但它把「分享」这件事从「临时」扩到了「长期」。批量公开 / 私有则让这件事能对一整批对象一次完成。