下载 URL 没错,但共享代理里仍存着一份响应。如果这次操作需要与源站核验过的响应,就把这个要求写在请求上:

from urllib.request import ProxyHandler, Request, build_opener
import shutil

opener = build_opener(ProxyHandler({
    "https": "http://proxy.example:8080",
}))
request = Request(download_url, headers={"Cache-Control": "no-cache"})
with opener.open(request, timeout=15) as response:
    shutil.copyfileobj(response, output)

这段代码假定应用自己持有二进制输出流,并提供 HTTPS 的 download_url。若要在没有代理认证的情况下试一次获准的公开下载,可在 opener 中使用HTTP 代理列表里的 HTTP 端点候选;请求的缓存要求保持不变。它保留原始资源 URL,同时要求请求路径上的缓存先做验证再复用。

验证可以复用已存储的字节

收到 no-cache 的合规缓存,若未与源站成功验证,就不能用已存储的响应满足这个请求。源站可以确认所存储的表示仍然有效,因此这次操作不必从源站重传未变化的文件。

请求中的 max-age=0 表达的是一条年龄上限。当应用想要不早于该上限的响应时它很有用,但它并不是禁止存储。刚刚生成的响应就能满足它。

追加一个随机查询参数,等于请求另一个目标 URI。这可能产生另一条缓存条目,甚至改变应用的响应。只有当查询参数属于该资源既定接口的一部分时才使用它。

对普通的 HTTPS CONNECT 而言,隧道代理看不到 TLS 内部的这个头部。该策略仍能到达源站以及处理解密后 HTTP 交换的缓存。把已存储的响应归因于隧道之前,先确认它实际存放在哪里。

相关文章