
用本地服务代替网络服务, 使得需要依赖网络运行的一款第三方应用能够脱机运行。
使用 RESTful 架构的 falcon 包实现了基本的网络请求响应,在依赖的资源文件完整的情况下,程序可以脱机运行。 但是遇到资源文件缺失,需要通过网络下载补足的情况就会报错。
本地文件请求:GET http://127.0.0.1:8686/Download/example.zip
文件远程真实地址:GET http://down.domain.com/Download/example.zip
用什么方法能在 python 程序接收到本地文件请求时,由 python重定向连接到文件远程真实地址,并将响应数据原样发回给本地第三方应用。类似于本地应用通过代理的方式取得了文件。
用关键词redirect在 Github 搜索了一些 python 项目,没找到特别适用的。
希望大侠不吝赐教,万分感谢。
最终使用方案, 感谢 @ec0 大侠的不吝赐教
url ='http://down.domain.com/Download/中文文件名示例.zip' #中文文件名编码问题,参见https://github.com/Pylons/waitress/issues/318 resp.downloadable_as = '中文文件名示例.zip'.encode("utf-8").decode("latin1") #设置响应Headers: 'Content-Length', 'Content-Type' resp.set_headers(dict(list(requests.head(url).headers.items())[:2])) chunk = lambda u: (yield from requests.get(u,stream=True).iter_content(chunk_size=8192)) resp.stream = chunk(url) 1 lizenghui Mar 31, 2022 nginx 可以啊。 |
4 cheng6563 Mar 31, 2022 你收到请求后直接改下地址然后 urllib.request 发请求出去就行了啊,把收到的数据直接返回或者临时存盘再返回都行。HTTP 文件下载有几个特殊 Header 表示文件名什么的,你响应的时候填上就行。 |
5 cheng6563 Mar 31, 2022 你先试试写一个提供文件下载接口,随便返回点数据就行。 再写一个用 urllib.request 下载远程文件的用例。 最后把两个方法整合下就行了。 |
6 Puteulanus Mar 31, 2022 听起来像个 cache proxy ,squid transparent proxy 是不是就能做 |
7 xuxuxu123 Mar 31, 2022 如果远程文件的真实地址是确定的,那么 nginx 反向代理就可以了 |
8 ClericPy Mar 31, 2022 这说的是 gost 么... https://github.com/ginuerzh/gost 或者用 Python 随手写个端口转发? https://github.com/ClericPy/ichrome/issues/84 如果我理解错了, 就当没看到我 |
12 lon91ong OP @Puteulanus 感谢提供关键词 squid, 找到个相关的项目, https://github.com/GlobalRadio/squid-redirect 简单看了看 readme, 似乎用得上, 明天再看看 |
13 mingl0280 Mar 31, 2022 ……你就不会检查一下 file exist 然后不存在的文件自动下载了返回么? |
14 Tink PRO 很多办法,上面说的 nginx 反代可以,也可以在你的程序里判断本地文件是否存在,不存在就去下载 |
15 biubiuF Apr 1, 2022 iptables redirect |
16 ec0 Apr 1, 2022 试试这段代码 ``` class ProxyResource: ____def file_generator(self, url): ________with requests.get(url, stream=True) as r: ____________for chunk in r.iter_content(chunk_size=8192): ________________yield chunk ____def on_get(self, req, resp): ________resp.downloadable_as = 'example.zip' ________resp.stream = self.file_generator('http://down.domain.com/Download/example.zip') ``` |
17 lon91ong OP @ec0 太感谢了! 感激涕零了要!!! 另外遇到一点小麻烦, 不知道时这个方法的问题, 还是我用的 WSGI 标准的 waitress 包的问题, 在转发时没有转发 headers 信息, 文件长度、编码等信息全都丢失了 需要用什么方法补救呢? |
18 enrolls Apr 1, 2022 这个需求就跟在腾讯云买了同主机和 cos 一个道理,主机跟 cos 免流量通信,cos 直接下载需要流量。主机返回 cos 的 body 出去。headers 可以一并 yield ,之后自己组装 |
20 ec0 Apr 1, 2022 这样呢? ``` def on_get(self, req, resp): ____resp.downloadable_as = 'example.zip' ____r = requests.head('http://down.domain.com/Download/example.zip') ____resp.content_length = r.headers['content-length'] ____resp.content_type = r.headers['content-type'] ____resp.stream = self.file_generator('http://down.domain.com/Download/example.zip') ``` |
22 macrorules Apr 1, 2022 iptables -A PREROUTING -t nat -i eth1 -d 127.0.0.1:8686 -j DNAT --to-destination ${down.domain.com 的地址} |
23 lon91ong OP @macrorules 这个操作不是只能在路由器上搞吗??程序里面没听说过啊! |
24 macrorules Apr 2, 2022 @lon91ong 这是在本地(你的电脑,笔记本)上操作的 |
25 lon91ong OP @macrorules 应该还要加上 Linux 系统的限制吧, Windows 没有 iptables 命令 |
26 lon91ong OP 使用 lambda 替代了 genreat 函数: ``` url ='http://down.domain.com/Download/example.zip' resp.downloadable_as=labfile.encode("utf-8").decode("latin1") #编码问题,参见 https://github.com/Pylons/waitress/issues/318 r = requests.head(url) resp.content_length = r.headers['content-length'] resp.content_type = r.headers['content-type'] chunk = lambda u: (yield from requests.get(u,stream=True).iter_content(chunk_size=8192)) resp.stream = chunk(url) ``` |