Compare commits
	
		
			5 Commits
		
	
	
		
			acdd776b92
			...
			ba36eaec1b
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | ba36eaec1b | ||
|   | a435a30c88 | ||
|   | 742b05ed66 | ||
|   | a26dc42d88 | ||
|   | 9002afbc7e | 
| @@ -6,7 +6,7 @@ from sanic import Blueprint | |||||||
|  |  | ||||||
| from cista import watching | from cista import watching | ||||||
| from cista.fileio import FileServer | from cista.fileio import FileServer | ||||||
| from cista.protocol import ControlBase, FileRange, StatusMsg | from cista.protocol import ControlTypes, FileRange, StatusMsg | ||||||
| from cista.util.apphelpers import asend, websocket_wrapper | from cista.util.apphelpers import asend, websocket_wrapper | ||||||
|  |  | ||||||
| bp = Blueprint("api", url_prefix="/api") | bp = Blueprint("api", url_prefix="/api") | ||||||
| @@ -76,9 +76,10 @@ async def download(req, ws): | |||||||
| @bp.websocket("control") | @bp.websocket("control") | ||||||
| @websocket_wrapper | @websocket_wrapper | ||||||
| async def control(req, ws): | async def control(req, ws): | ||||||
|     cmd = msgspec.json.decode(await ws.recv(), type=ControlBase) |     while True: | ||||||
|     await asyncio.to_thread(cmd) |         cmd = msgspec.json.decode(await ws.recv(), type=ControlTypes) | ||||||
|     await asend(ws, StatusMsg(status="ack", req=cmd)) |         await asyncio.to_thread(cmd) | ||||||
|  |         await asend(ws, StatusMsg(status="ack", req=cmd)) | ||||||
|  |  | ||||||
|  |  | ||||||
| @bp.websocket("watch") | @bp.websocket("watch") | ||||||
|   | |||||||
							
								
								
									
										60
									
								
								cista/app.py
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								cista/app.py
									
									
									
									
									
								
							| @@ -2,12 +2,13 @@ import mimetypes | |||||||
| from importlib.resources import files | from importlib.resources import files | ||||||
| from urllib.parse import unquote | from urllib.parse import unquote | ||||||
|  |  | ||||||
|  | import asyncio | ||||||
|  | import brotli | ||||||
| from sanic import Blueprint, Sanic, raw | from sanic import Blueprint, Sanic, raw | ||||||
| from sanic.exceptions import Forbidden, NotFound | from sanic.exceptions import Forbidden, NotFound | ||||||
|  |  | ||||||
| from cista import auth, config, session, watching | from cista import auth, config, session, watching | ||||||
| from cista.api import bp | from cista.api import bp | ||||||
| from cista.util import filename |  | ||||||
| from cista.util.apphelpers import handle_sanic_exception | from cista.util.apphelpers import handle_sanic_exception | ||||||
|  |  | ||||||
| app = Sanic("cista", strict_slashes=True) | app = Sanic("cista", strict_slashes=True) | ||||||
| @@ -58,15 +59,54 @@ def http_fileserver(app, _): | |||||||
|     app.blueprint(bp) |     app.blueprint(bp) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | www = {} | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @app.before_server_start | ||||||
|  | def load_wwwroot(app): | ||||||
|  |     global www | ||||||
|  |     wwwnew = {} | ||||||
|  |     base = files("cista") / "wwwroot" | ||||||
|  |     paths = ["."] | ||||||
|  |     while paths: | ||||||
|  |         path = paths.pop(0) | ||||||
|  |         current = base / path | ||||||
|  |         for p in current.iterdir(): | ||||||
|  |             if p.is_dir(): | ||||||
|  |                 paths.append(current / p.parts[-1]) | ||||||
|  |                 continue | ||||||
|  |             name = p.relative_to(base).as_posix() | ||||||
|  |             mime = mimetypes.guess_type(name)[0] or "application/octet-stream" | ||||||
|  |             data = p.read_bytes() | ||||||
|  |             # Use old data if not changed | ||||||
|  |             if name in www and www[name][0] == data: | ||||||
|  |                 wwwnew[name] = www[name] | ||||||
|  |                 continue | ||||||
|  |             # Precompress with Brotli | ||||||
|  |             br = brotli.compress(data) | ||||||
|  |             if len(br) >= len(data): | ||||||
|  |                 br = False | ||||||
|  |             wwwnew[name] = data, br, mime | ||||||
|  |     www = wwwnew | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @app.add_task | ||||||
|  | async def refresh_wwwroot(): | ||||||
|  |     while app.debug: | ||||||
|  |         await asyncio.sleep(0.5) | ||||||
|  |         load_wwwroot(app) | ||||||
|  |  | ||||||
|  |  | ||||||
| @app.get("/<path:path>", static=True) | @app.get("/<path:path>", static=True) | ||||||
| async def wwwroot(req, path=""): | async def wwwroot(req, path=""): | ||||||
|     """Frontend files only""" |     """Frontend files only""" | ||||||
|     name = filename.sanitize(unquote(path)) if path else "index.html" |     name = unquote(path) or "index.html" | ||||||
|     try: |     if name not in www: | ||||||
|         index = files("cista").joinpath("wwwroot", name).read_bytes() |         raise NotFound(f"File not found: /{path}", extra={"name": name}) | ||||||
|     except OSError as e: |     data, br, mime = www[name] | ||||||
|         raise NotFound( |     headers = {} | ||||||
|             f"File not found: /{path}", extra={"name": name, "exception": repr(e)} |     # Brotli compressed? | ||||||
|         ) |     if br and "br" in req.headers.accept_encoding.split(", "): | ||||||
|     mime = mimetypes.guess_type(name)[0] or "application/octet-stream" |         headers["content-encoding"] = "br" | ||||||
|     return raw(index, content_type=mime) |         data = br | ||||||
|  |     return raw(data, content_type=mime, headers=headers) | ||||||
|   | |||||||
| @@ -78,6 +78,9 @@ class Cp(ControlBase): | |||||||
|             ) |             ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ControlTypes = MkDir | Rename | Rm | Mv | Cp | ||||||
|  |  | ||||||
|  |  | ||||||
| ## File uploads and downloads | ## File uploads and downloads | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -15,6 +15,7 @@ classifiers = [ | |||||||
| ] | ] | ||||||
| dependencies = [ | dependencies = [ | ||||||
|     "argon2-cffi", |     "argon2-cffi", | ||||||
|  |     "brotli", | ||||||
|     "docopt", |     "docopt", | ||||||
|     "inotify", |     "inotify", | ||||||
|     "msgspec", |     "msgspec", | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user