| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 |
- #!/usr/bin/env python3
- """极简静态服务器(带 SPA 路由回退)—— 用户空间,CentOS 自带 Python 3.6 即可。
- 托管前端构建产物(deploy 分支的 dist),供内网访问。客户端路由(如
- /behavior/funnel/group)刷新时回退到 index.html,避免 404。
- 兼容 Python 3.6(不用 3.7+ 的 `directory=` 参数,改 os.chdir)。
- 用法:
- python3 serve.py <静态目录> [端口]
- 例:
- nohup python3 ~/serve-hs.py ~/hs-data 6666 > ~/hs-web.log 2>&1 &
- """
- import os
- import sys
- from http.server import SimpleHTTPRequestHandler
- from socketserver import ThreadingTCPServer
- ROOT = os.path.abspath(sys.argv[1] if len(sys.argv) > 1 else ".")
- PORT = int(sys.argv[2]) if len(sys.argv) > 2 else 6666
- os.chdir(ROOT)
- class SpaHandler(SimpleHTTPRequestHandler):
- # 覆盖 send_head(GET 与 HEAD 都走它),统一做 SPA 回退。
- def send_head(self):
- rel = self.path.split("?", 1)[0].split("#", 1)[0].lstrip("/")
- if rel and not os.path.isfile(os.path.join(ROOT, rel)):
- last = rel.rsplit("/", 1)[-1]
- # 仅"看起来像路由"的路径(末段无扩展名)回退到 index.html;
- # 缺失的资源文件(如 /assets/x.js)让其正常 404,避免返回 HTML 触发 MIME 错误。
- if "." not in last:
- self.path = "/index.html"
- return SimpleHTTPRequestHandler.send_head(self)
- def end_headers(self):
- # index.html 不缓存(构建产物自带 hash,可长缓存)。
- if self.path.split("?", 1)[0] in ("/", "/index.html"):
- self.send_header("Cache-Control", "no-cache")
- SimpleHTTPRequestHandler.end_headers(self)
- class Server(ThreadingTCPServer):
- allow_reuse_address = True
- daemon_threads = True
- if __name__ == "__main__":
- print("serving %s on 0.0.0.0:%d (SPA fallback)" % (ROOT, PORT))
- Server(("0.0.0.0", PORT), SpaHandler).serve_forever()
|