main.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import os
  2. import shutil
  3. from fastapi import FastAPI, Request, File, UploadFile, Form
  4. from fastapi.responses import HTMLResponse, RedirectResponse
  5. from fastapi.templating import Jinja2Templates
  6. from fastapi.staticfiles import StaticFiles
  7. # =====================================================================
  8. # MODIFICATION START: REMOVED ROOT_PATH
  9. # Reason: We removed the `root_path="/patch-manager"` argument.
  10. # Because Nginx already strips the prefix before passing traffic to
  11. # this container, setting it here was causing FastAPI to double-process
  12. # the route and throw internal 404s. Standard FastAPI initialization is best.
  13. # =====================================================================
  14. app = FastAPI()
  15. # =====================================================================
  16. # MODIFICATION END
  17. # =====================================================================
  18. # Failsafe: Create the directory inside the container if it somehow gets missed
  19. os.makedirs("static", exist_ok=True)
  20. app.mount("/static", StaticFiles(directory="static"), name="static")
  21. templates = Jinja2Templates(directory="templates")
  22. # The persistent directory for your custom code
  23. OVERLAY_DIR = "/srv"
  24. @app.get("/", response_class=HTMLResponse)
  25. async def index(request: Request):
  26. files = []
  27. if os.path.exists(OVERLAY_DIR):
  28. for root, dirs, filenames in os.walk(OVERLAY_DIR):
  29. for filename in filenames:
  30. rel_path = os.path.relpath(os.path.join(root, filename), OVERLAY_DIR)
  31. files.append(rel_path)
  32. return templates.TemplateResponse("index.html", {"request": request, "files": sorted(files)})
  33. @app.post("/upload")
  34. async def upload_file(file: UploadFile = File(...), target_path: str = Form("")):
  35. save_dir = os.path.join(OVERLAY_DIR, target_path.strip("/"))
  36. os.makedirs(save_dir, exist_ok=True)
  37. file_location = os.path.join(save_dir, file.filename)
  38. with open(file_location, "wb+") as file_object:
  39. shutil.copyfileobj(file.file, file_object)
  40. # =====================================================================
  41. # MODIFICATION START: EXPLICIT NGINX REDIRECTS
  42. # Reason: Since we removed root_path, we must explicitly tell the
  43. # user's browser to redirect back to the Nginx URL ("/patch-manager/")
  44. # after a successful action, otherwise it redirects to the internal "/"
  45. # and gets lost on the main ArduPilot page.
  46. # =====================================================================
  47. return RedirectResponse(url="/patch-manager/", status_code=303)
  48. # =====================================================================
  49. # MODIFICATION END
  50. # =====================================================================
  51. @app.post("/delete")
  52. async def delete_file(filepath: str = Form(...)):
  53. target = os.path.join(OVERLAY_DIR, filepath)
  54. if os.path.exists(target):
  55. os.remove(target)
  56. target_dir = os.path.dirname(target)
  57. if not os.listdir(target_dir) and target_dir != OVERLAY_DIR:
  58. os.rmdir(target_dir)
  59. return RedirectResponse(url="/patch-manager/", status_code=303)
  60. @app.get("/edit", response_class=HTMLResponse)
  61. async def edit_file(request: Request, filepath: str):
  62. target = os.path.join(OVERLAY_DIR, filepath)
  63. content = ""
  64. if os.path.exists(target):
  65. with open(target, "r", encoding="utf-8", errors="ignore") as f:
  66. content = f.read()
  67. return templates.TemplateResponse("edit.html", {"request": request, "filepath": filepath, "content": content})
  68. @app.post("/edit")
  69. async def save_file(filepath: str = Form(...), content: str = Form(...)):
  70. target = os.path.join(OVERLAY_DIR, filepath)
  71. if os.path.exists(target):
  72. with open(target, "w", encoding="utf-8") as f:
  73. f.write(content)
  74. return RedirectResponse(url="/patch-manager/", status_code=303)