以下内容基本上是 AI 生成的,我还没校对,可能质量不高
Cached Proxy¶
轻量级 HTTP 缓存代理服务器。用 Python 实现,支持响应内容修改和递归防循环。
Warning
这是一个周末 hack,代码简洁但功能实用。适合本地站点镜像或缓存。
功能¶
- 代理 HTTP 请求,缓存响应
- 修改响应内容,如替换域名
- 支持递归代理和循环检测
实现¶
用 Python 写,依赖 pydantic 和 httpx。启动时设置 baseurl 和缓存时间,代理请求时检查缓存,必要时转发并缓存。
cached-proxy 把代理、缓存与响应改写做成了耦合良好的小工具:主程序用 httpx.AsyncClient(http2=True) 发起请求、把响应写入 diskcache 并通过 x-diskcache-hits/misses/age 等 header 报告缓存元数据,decorate_body / decorate_headers 则负责把返回体或 Location 头内的 base URL 做可配置替换,方便做镜像或内嵌资源替换。递归抓取逻辑由 recursion.py 实现,使用 visited_urls 避免循环爬取。配置使用 pydantic-settings 驱动(env.py 定义了 baseurl、min_age、replace 等字段),整体设计适合轻量站点镜像或开发时的缓存代理场景。
代理核心逻辑¶
main.py 中的缓存和响应处理:
# main.py
async def fetch(url: str):
cache_key = url
hit = cache.get(cache_key)
hits, misses = cache.stats()
common_headers = {"x-diskcache-hits": str(hits), "x-diskcache-misses": str(misses)}
if not hit or env.min_age and (age := time() - hit["timestamp"]) > env.min_age:
res = await client.get(url)
res_body = res.read()
cache.set(
cache_key,
{
"body": compress(res_body, 1, 9, Filter.NOFILTER, Codec.LZ4),
"headers": dict(res.headers),
"status": res.status_code,
"timestamp": time(),
},
)
return make_response(res_body, res_status, res_headers)
return make_response(decompress(hit["body"]), hit["status"], hit["headers"])
使用 blosc2 的 LZ4 压缩算法实现高效存储。
递归爬虫¶
recursion.py 中的链接提取和并发控制:
# recursion.py
from bs4 import BeautifulSoup
client = AsyncClient(http2=True, base_url=base_url, timeout=60)
sem = Semaphore(500)
visited_urls = set()
async def crawl(url: str, visited_urls: set):
if url in visited_urls:
return
visited_urls.add(url)
links = await get_links(url)
tasks = []
for i in links:
if i and is_same_origin(i) and not i.startswith("#"):
tasks.append(create_task(crawl(i, visited_urls)))
await gather(*tasks)
使用 BeautifulSoup 解析 HTML,提取所有资源链接。
我的巧思¶
- 响应内容重写:用正则替换域名,实现自包含镜像。
- 递归保护:跟踪
visited_urls,避免无限循环。 - 轻量无依赖:除了
pydantic,几乎纯标准库。
深入洞见¶
这个项目是一个极简的 ASGI 反向代理,专注于缓存和重写单个上游网站。通过 diskcache 的 Blosc2 压缩实现高效存储,httpx 支持 HTTP/2。响应体重写使用简单字符串替换,适合静态站点,但对动态内容可能失效。预缓存爬虫使用 BeautifulSoup 递归抓取资源,限制并发和深度。
缓存统计头(x-diskcache-hits/misses/age)提供可观测性,但无驱逐策略可能导致磁盘增长。