學會用 curl / wget 模仿一些 request 後,在一些特殊情境上,還是得弄個 proxy 出來,雖然有 man-in-the-middle Proxy: mitmproxy 可以使用,但有時就是想要單純一點,寫點小程式自娛一下 XD
故事的情境:
- 想用 VLC 播放一些 Streaming 來源,但該 streaming 在存取時要求多塞一些request header,直接播會收到 40X 回應
- VLC 預設只吃 OS Level 的 proxy 設定
基於上述情境,雖然靠 curl/wget 添加 request header 可以搞定,但 VLC 這類就無法達成播放指定來源時多添加 request header。
因此,除了靠 OS Level 的 Proxy server 添加 reader header,就剩寫一隻代抓資料,邊抓邊輸出 stream 的小小程式,程式碼:
import http.server
import urllib.parse
import requests
import time
class ProxyHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
protocol_version = 'HTTP/1.0'
def do_GET(self, body=True):
try:
target_url = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query).get('url', None)
print("[INFO] target_url: "+str(target_url))
if target_url != None:
target_url = target_url[0]
req_header = self.parse_headers()
#resp = requests.get(target_url, headers=req_header, verify=False, stream=True)
resp = requests.get(target_url, headers=req_header, verify="certs.pem", stream=True)
print("[INFO] resp.status_code: %d " % resp.status_code)
if resp.status_code == 404:
self.send_response(404)
self.send_header('Content-Type','text/html')
self.end_headers()
self.wfile.write("NOT FOUND".encode())
else:
self.send_response(resp.status_code)
for k in resp.headers.keys():
print("[INFO] resp.headers: [%s][%s]" % (k, resp.headers[k]) )
self.send_header(k, resp.headers[k])
self.end_headers()
for chunk in resp.iter_content(chunk_size=1024):
if chunk:
self.wfile.write(chunk)
self.wfile.flush()
else:
time.sleep(0.05)
else:
self.send_response(404)
self.send_header('Content-Type','text/html')
self.end_headers()
self.wfile.write("NOT FOUND".encode())
finally:
pass
def parse_headers(self):
req_header = {}
for line in self.headers:
line_parts = [o.strip() for o in line.split(':', 1)]
if len(line_parts) == 2:
req_header[line_parts[0]] = line_parts[1]
return self.inject_header(req_header)
def inject_header(self, headers):
headers['Referer'] = 'https://example.com/'
return headers
if __name__ == '__main__':
server_address = ('0.0.0.0', 8081)
httpd = http.server.HTTPServer(server_address, ProxyHTTPRequestHandler)
print('http server is running')
httpd.serve_forever()
如此跑起來後,就可以用 http://localhost:8081/?url=https://exmaple.com/streaming 機制,例如 VLC 軟體直接輸入 http://localhost:8081/?url=https://exmaple.com/streaming 位置來嘗試播放。
沒有留言:
張貼留言