static_server.py 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. r"""静态目录服务 (viewer / sim 用) —— 替代 `python -m http.server`, 并接入统一日志格式。
  4. 为什么要单开一个: `python -m http.server` 的请求日志是 `127.0.0.1 - - [date] "GET …" 200 -` (Common Log
  5. 格式), 与其余 5 个服务的日志格式不一样, 也没法给它挂前缀 (那是 stdlib 的 main)。本器自己做三件事:
  6. 1. 每行都走 `src/logfile.py` 的统一格式: `YYYY-MM-DD HH:MM:SS INFO viewer GET /index.html 200 1234`;
  7. 2. 只服务**指定目录**(默认安装根下的相对目录), 不做目录列表以外的任何动态行为 (纯静态, 与原来等价);
  8. 3. `--comp` 指定组件名 (viewer / sim), 日志落到 `logs/<组件>.log`。
  9. 用法:
  10. python scripts/static_server.py --port 64292 --dir release/viewer --comp viewer
  11. python scripts/static_server.py --port 18791 --dir resources/oem_envision_sc1_rudong2014 --comp sim
  12. """
  13. from __future__ import annotations
  14. import argparse
  15. import functools
  16. import pathlib
  17. import sys
  18. from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
  19. ROOT = pathlib.Path(__file__).resolve().parents[1]
  20. sys.path.insert(0, str(ROOT))
  21. from src import logfile as L # noqa: E402
  22. def main() -> int:
  23. ap = argparse.ArgumentParser()
  24. ap.add_argument('--port', type=int, required=True)
  25. ap.add_argument('--host', default='127.0.0.1')
  26. ap.add_argument('--dir', required=True, help='要服务的目录 (相对安装根或绝对路径)')
  27. ap.add_argument('--comp', default='static', help='日志组件名 (viewer / sim …)')
  28. a = ap.parse_args()
  29. L.prefix_stdout(a.comp)
  30. d = pathlib.Path(a.dir)
  31. d = d if d.is_absolute() else (ROOT / d)
  32. if not d.is_dir():
  33. L.write(a.comp, f'目录不存在: {d}', 'ERROR')
  34. print(f'[X] 目录不存在: {d}')
  35. return 2
  36. class H(SimpleHTTPRequestHandler):
  37. def log_message(self, fmt, *args): # 统一格式: 一行一条, 带状态码与字节数
  38. print(f'{self.command} {self.path} {fmt % args}', flush=True)
  39. def log_error(self, fmt, *args):
  40. print(f'ERROR {self.path} {fmt % args}', flush=True)
  41. handler = functools.partial(H, directory=str(d))
  42. print(f'静态服务 → http://{a.host}:{a.port}/ 目录 {d} (组件 {a.comp})', flush=True)
  43. ThreadingHTTPServer((a.host, a.port), handler).serve_forever()
  44. return 0
  45. if __name__ == '__main__':
  46. sys.exit(main())