import http.server
import socketserver
import os
import sys
from pathlib import Path
import socket
DEFAULT_PORT = 8000
DOCS_OUTPUT = "core/docs.rustdoc/"
def find_docs_dir():
bazel_bin = os.environ.get("BUILD_WORKING_DIRECTORY")
if bazel_bin:
candidate = Path(bazel_bin) / "bazel-bin" / DOCS_OUTPUT
else:
candidate = Path("bazel-bin") / DOCS_OUTPUT
if candidate.is_dir():
return candidate
runfiles = Path(sys.argv[0]).parent
for p in [runfiles / DOCS_OUTPUT, Path.cwd() / DOCS_OUTPUT]:
if p.is_dir():
return p
print("Could not locate docs directory. Please run: bazel build //core:docs", file=sys.stderr)
sys.exit(1)
def choose_redirect(docs_dir: Path):
if (docs_dir / "index.html").exists():
return None
candidates = []
for p in docs_dir.iterdir():
if p.is_dir() and (p / "index.html").exists():
candidates.append(p.name + "/index.html")
if len(candidates) == 1:
return candidates[0]
return None
def main():
port = int(sys.argv[1]) if len(sys.argv) > 1 else DEFAULT_PORT
docs_dir = find_docs_dir()
redirect_target = choose_redirect(docs_dir)
os.chdir(docs_dir)
class RedirectingHandler(http.server.SimpleHTTPRequestHandler):
def do_GET(self): if redirect_target and (self.path == "/" or self.path == "/index.html"):
self.send_response(302)
self.send_header("Location", "/" + redirect_target)
self.end_headers()
return
super().do_GET()
def log_message(self, format, *args): sys.stderr.write("[docs] " + (format % args) + "\n")
class DocTCPServer(socketserver.TCPServer):
allow_reuse_address = True
def server_bind(self):
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
except (AttributeError, OSError):
pass
return super().server_bind()
handler = RedirectingHandler
original_port = port
while True:
try:
with DocTCPServer(("", port), handler) as httpd:
if redirect_target:
print(f"Serving docs from {docs_dir} (redirecting / to /{redirect_target}) at http://localhost:{port}/ (Ctrl+C to stop)")
else:
print(f"Serving docs from {docs_dir} at http://localhost:{port}/ (Ctrl+C to stop)")
try:
httpd.serve_forever()
except KeyboardInterrupt:
pass
finally:
print("Stopping server")
break
except OSError as e:
if getattr(e, "errno", None) == 48: port += 1
if port - original_port > 20:
print("Could not find a free port after 20 increments.", file=sys.stderr)
sys.exit(1)
else:
raise
if __name__ == "__main__":
main()