Following symlinks & static files #2285
-
Just found out that symlinks in static directories are not followed if they point outside the project directory. I (now) know that this is more of a starlette/FastAPI issue, but it may be useful to add to the Nicegui docs. For future reference I am sharing the problem & a working solution. If there's a better way I would love to hear it. Problem. See example below, the first ui.image is shown, the second is not. # main.py
from nicegui import ui, app
@ui.page("/")
def page():
app.add_static_files("/static", "static")
# this image IS shown:
ui.image("/static/thumbs/1_sq_IMG_1967.jpg") # static/thumbs is a local path
# but this image gives a 404:
ui.image("/static/org/20/photos/IMG_2440.jpg") # static/org is an "outside" symlink
ui.run(show=False) The symlink for 'org' points outside...
# symlink.py
from fastapi import FastAPI
from starlette.staticfiles import StaticFiles
import os
from nicegui import ui
# static files subclass that allows following symlinks outside project directory
# note: allowing access to any directory by symlink may be a security risk, use with care
#
class CustomStaticFiles(StaticFiles):
def lookup_path(self, path):
full_path = os.path.join(str(self.directory), path)
if os.path.exists(full_path) or os.path.islink(full_path):
real_path = os.path.realpath(full_path)
try:
statstaticult = os.stat(real_path, follow_symlinks=False)
return real_path, statstaticult
except FileNotFoundError:
return None, None
return None, None
app = FastAPI()
app.mount("/static", CustomStaticFiles(directory="static"), name="static")
@ui.page("/")
def page():
# app.add_static_files("/static", "static") # no longer required
# now both images are shown:
ui.image("/static/thumbs/1_sq_IMG_1967.jpg") # local path
ui.image("/static/org/20/photos/IMG_2440.jpg") # symlink outside the current project
ui.run_with(app) and to run it under uvicorn:
|
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
Interesting observation, @kleynjan! As a simple workaround, you can borrow the line from app.mount('/static/', StaticFiles(directory='static', follow_symlink=True)) Maybe we should add such a parameter to |
Beta Was this translation helpful? Give feedback.
-
That is a whole lot simpler, thanks @falkoschindler! I had found the Starlette static docs but I couldn't figure out how to link that to Nicegui. (Also, the Starlette docs simply mention "following symlinks", which isn't too helpful, since I'd already established that symlinks work without this parameter -- they just don't work "outside".) For future reference: from fastapi import FastAPI
from starlette.staticfiles import StaticFiles
from nicegui import ui
app = FastAPI()
app.mount("/static/", StaticFiles(directory="static", follow_symlink=True))
@ui.page("/")
def page():
# app.add_static_files("/static", "static") # no longer required
# now both images are shown:
ui.image("/static/thumbs/1_sq_IMG_1967.jpg") # local path
ui.image("/static/org/20/photos/IMG_2440.jpg") # symlink outside the current project
ui.run_with(app) |
Beta Was this translation helpful? Give feedback.
Interesting observation, @kleynjan!
As a simple workaround, you can borrow the line from
add_static_files
and setfollow_symlink=True
:Maybe we should add such a parameter to
add_static_files
. 🤔