博客 • 分享机制
用 URL Hash 分享 JSON:不上传服务器的原理、限制与用法
同事说「你那边 JSON 一格式化就对,我这边报错」。把文件传来传去很烦,截图又没法继续改。
URL Hash 分享把当前工具和输入写进地址栏的#后面。对方打开同一条链接,浏览器在本地还原左右栏;普通页面请求不会把这份数据发给服务器。
这和「贴到某个在线格式化网站再点分享」不是一回事。后者通常先把原文 POST 到别人的后端,再给你一个短链。Hash 分享没有这一步。
本文将说明:
- URL Hash 为什么通常不会出现在服务器日志里
- JSONNote 的
#tool=…&data=…怎么编码 - 为什么 Base64 不是加密
- 链接会膨胀多少、哪些软件会截断
- 什么时候该用分享,什么时候必须停手
先记住这一点:Hash 能用,是因为浏览器默认不把#后面发给服务器。但这既不是加密,也挡不住聊天软件把链接截断。下面按「原理 → 编码 → 长度 → 边界」把这件事拆开。
URL Hash 分享是什么
完整 URL 可以拆成两段:服务器会看到的部分,和只留在浏览器里的部分。
请求发给服务器 fragment / Hash(只留在浏览器)
JSONNote 的「分享」做的就是:把当前工具 id 和左侧输入编码进 Hash,再把整段location.href复制到剪贴板。对方打开后,页面脚本读location.hash,在他自己的浏览器里还原工具和文本。
-
1
你在浏览器里点「分享」
输入先转成 UTF-8,再编成 Base64,写成
#tool=&data=。 -
2
把完整 URL 发给同事
对方打开同一站点后,页面脚本读
location.hash。 -
3
在对方浏览器里还原
本地格式化、校验或 Diff。服务器只收到页面本身,没有这份 JSON。
这和把 JSON 处理放在浏览器里是同一条原则:计算发生在本地,分享也不经过我们的数据库。隐私边界写在隐私声明第 3 节。
为什么 Hash 不会上传到服务器
Fragment 不会进入 HTTP 请求
按MDN 对 URL.hash 的说明和WHATWG URL 标准里的 fragment,#之后是 fragment identifier。浏览器导航时,HTTP 请求的 path / query 里不包含这段。
所以访问日志里通常只有:
GET /json/format.html HTTP/1.1
而不是:
GET /json/format.html#data=……
这也是为什么 Hash 适合「我不想让站点存一份我的粘贴」,却不适合当保密通道:数据仍在完整 URL 里,只是默认不走这一跳网络。
和 Query String 的区别
| 写法 | 例子 | 服务器看不看得到 | 适合做什么 |
|---|---|---|---|
| Query | ?tool=json-format&data=… |
会。出现在请求行、反向代理和 CDN 日志里 | 需要服务端读的参数 |
| Hash | #tool=json-format&data=… |
普通页面请求不会带上 | 只给前端脚本用的状态 |
如果有人把同样的 Base64 放到?后面,效果看起来一样,数据却已经进了服务器日志。JSONNote 只写 Hash,就是为了避开这一层。
另外:Referer 通常也不带 fragment。你从分享页点到外链,对方站点一般拿不到 Hash 里的 JSON。这是浏览器默认行为,不是我们额外做的加密。
JSONNote 的分享链接长什么样
点「分享」后,Hash 是一组URLSearchParams:
#tool=json-format&data=<Base64>
tool
当前工具 id。打开链接后会切到对应工作区,而不是一律落到「JSON 格式化」。常见值包括json-format、json-validate、json5、json-path、json-diff。
只切换工具、不点分享时,地址栏会更新成#tool=…,不含 data。这是为了记住你在用哪个工具,不会把编辑器里的内容写进历史记录。
data
左侧输入的 UTF-8 文本,再做 Base64。实现上等价于:
btoa(unescape(encodeURIComponent(input)))
先encodeURIComponent是为了让中文和 Emoji 能过btoa。还原时走相反路径。这和 MDN 讨论的Unicode 字符串的 Base64 编码是同一类问题。
编码不是加密
Base64 的目的是「任意字节都能放进 URL」,不是「只有受信方能读」。任何人拿到链接,都可以在控制台还原:
const data = new URLSearchParams(location.hash.slice(1)).get("data");
decodeURIComponent(escape(atob(data)));
也可以把data=后面的字符串丢进本站的Base64 解码。没有口令,没有一次性链接,也没有过期时间。
一个完整示例
假设你在「JSON 格式化」里输入:
{
"name": "Ada",
"role": "dev"
}
压缩成一行后是 27 字节:
{"name":"Ada","role":"dev"}
UTF-8 → Base64 得到 36 个 ASCII 字符(这段里没有+ / /,放进 URL 时不会再被百分号编码拉长):
eyJuYW1lIjoiQWRhIiwicm9sZSI6ImRldiJ9
完整 Hash:
#tool=json-format&data=eyJuYW1lIjoiQWRhIiwicm9sZSI6ImRldiJ9
对方打开后看到同一段 JSON,可以继续格式化、做JSONPath 抽取,或和自己的响应做 Diff。若原文其实是带注释的配置,应改用JSON5 解析再分享输出,而不是把无法JSON.parse的文本直接丢给对方。
含中文时体积更明显。例如{"msg":"格式化后两边一致"}是 34 字节 UTF-8,Base64 后 48 字符;其中的/和=再被 URL 编码,参数值会变成 54 字符。
链接会变多长
Hash 分享的硬限制不是「服务器上传上限」,而是整段 URL 还能不能完整送达对方浏览器。
对一段近似纯 ASCII 的 JSON,实测数量级如下(含tool=json-format&data=的膨胀后长度):
| 原文大约 | 编码后 Hash 大约 | 经验限制 |
|---|---|---|
| 200 B | 330 字符 | 聊天软件几乎都能完整送达 |
| 1 KB | 1.4 KB | 多数 IM 没问题,仍建议自己点开确认 |
| 8 KB | 11 KB | 浏览器通常能打开;部分客户端会截断 |
| 32 KB | 44 KB | 不要指望微信 / 邮件原文转发还能用 |
Chrome 能消化很长的地址栏,但中间还有一层:IM、邮件、短链服务、二维码。它们各自有更短的上限,而且很少告诉你「我把尾巴切掉了」。所以流程应是:
-
1
点「分享」
复制完整地址,不要只抄
#后面一截。 -
2
先在本机新标签打开
确认工具和输入都在,再发给同事。
整份访问日志、数兆的导出文件,请本机粘贴或点「下载」。Hash 分享解决的是「复现一小段输入」,不是当网盘。
Hash 分享和其他方式比什么
| 方式 | 数据去哪 | 对方怎么接着干 | 适合 | 不适合 |
|---|---|---|---|---|
| URL Hash | 停在双方地址栏 | 打开同一站点即可继续处理 | 小段 JSON、复现报错 | 密钥、超大文件 |
| 聊天原文 | 聊天服务器 | 再复制一次 | 几行配置 | 进永久会话记录的内部数据 |
| 截图 | 图片 | 只能看,不能 parse | 讲结构 | 还要继续格式化 / Diff |
| 附件 / 网盘 | 第三方存储 | 下载后再贴 | 大文件 | 想避免多一份副本 |
| 在线 Paste | 别人的后端 | 打开短链 | 需要公开、长期存放 | 任何不该离开本机的内容 |
团队里若已经有内网 paste 或工单附件,大段日志走原有通道更稳。Hash 的价值是:同一条链接同时带上「用哪个工具」和「输入是什么」,对方不用猜你点的是格式化还是校验。
使用时必须记住的边界
- 链接等于明文。能打开页面的人就能还原内容。不要分享密钥、生产 Token、客户名单或未公开接口。
- 发出去之前自己点开。聊天软件截断超长 URL 时,对方会打开一个残缺 Hash,表现为空白输入或解码失败。
- 对方必须能打开同一个 JSONNote 站点。Hash 不能脱离页面单独解析;把
#后面一段丢进记事本没有用。 - 浏览器历史会留下完整地址。本机历史、同步的账号、屏幕共享都能看到。不点分享、只切换工具时,Hash 里没有 data,就是为了少写一份。
- 扩展和调试工具可能读到
location.href。本地计算降低的是「我们站点存一份」的风险,不是「这台电脑上谁都看不见」。 - 「从 URL 拉取」是另一条路。工作区填写远程地址并点「拉取」时,浏览器会向那个地址发请求。分享 Hash 里如果带了
url=,打开的人也会发起这次请求。只信你自己核对过的来源。
涉及真实隐私时,用离线或内网工具。这和「站点有没有登录框」无关。
常见问题
URL Hash 分享是什么?
把当前工具和输入编码进地址栏#后面。对方打开同一站点的同一条链接,浏览器在本地还原内容,而不把这份数据作为页面请求发给服务器。
Hash 里的数据服务器看得到吗?
普通页面请求不会把 fragment 发给服务器,访问日志里通常只有路径。但这不等于保密:拿到完整链接的人都能解码。
编码和加密有什么区别?
编码(这里是 Base64)保证文本能放进 URL,任何人都能反向还原。加密需要密钥,没有密钥就不能读。JSONNote 分享做的是前者。
Hash 分享可以用于密钥或 Token 吗?
不可以。链接一旦发出就无法收回,历史记录里也还在。密钥请走你们团队的密钥管理系统,不要进任何网页地址栏。
对方打开是空白的?
先检查 URL 是否在data=中间被截断;再确认打开的是同一个 JSONNote 站点,而不是只复制了#后面一截。超大文本请改用本机粘贴。
和 JSON 格式化、校验是什么关系?
分享只负责「原样带走当前输入和工具」。格式化、语法校验、JSON5、JSONPath、Diff 仍在对方浏览器里本地执行。需要先看结构,用JSON 格式化;需要定位Unexpected token,用校验或JSON5。
总结
URL Hash 分享本质上是:
本地工具状态 + 可逆编码 + 浏览器 fragment 不随请求上传。
它适合复现一小段 JSON 或配置,不适合当网盘,更不适合传秘密。用对了,你和同事对着同一左右栏说话;用错了,等于把明文贴进一条谁都能打开的地址。