Waleed S Khan
Waleed S Khan

Reputation: 150

FastAPI serving static files through symlinks

I have mounted the static directory in my FastAPI app using the following code:

from fastapi.staticfiles import StaticFiles

app = FastAPI(
    title="Title of the Application",
    description="Over all description of the application")
app.mount("/public", StaticFiles(directory='public'), name='public')

If I have a symlink pointing to a path outside the app folder, e.g.

/home/xyz/app/main.py
/home/xyz/app/index.html
/home/xyz/app/public/data -> /home/xyz/static/whatever.tgz

The FastAPI application can recognize the URL xyz.com/public/index.html, but it can't recognize xyz.com/public/data.

Is this doable? Unfortunately, I cannot use FileResponse due to the blob size being too large. I want to return the file with a simple link somehow.

Upvotes: 1

Views: 2390

Answers (2)

Chris
Chris

Reputation: 34345

Update

Starlette has recently added the follow_symlink parameter in StaticFiles class, which is a boolean indicating if symbolic links for files and directories should be followed—by default, this value is set to False. One could set this to True, and hence, every symbolic link in the directory path should be followed. Example:

app.mount("/static", StaticFiles(directory="static", follow_symlink=True), name="static")

Given that there is a symlink called data in your static directory, you could then access, for instance, http://localhost:8000/static/data/image.png directly from your browser, or in your Jinja2 template, you could request files as follows:

<img src="{{ url_for('static', path='data/image.png')}}" width="50%">

Original Answer

It is doable, as long as you mount a StaticFiles instance on that specific path as well. For example:

app.mount("/static", StaticFiles(directory="static"), name="static")
app.mount("/symlink", StaticFiles(directory="static/data"), name="publicsym")

Then, in your Jinja2 template you could request files as follows:

<link href="{{ url_for('static', path='/styles.css') }}" rel="stylesheet">
<img src="{{ url_for('symlink', path='/image.png')}}" width="50%">

or, if there is an images sub-directory inside data:

<img src="{{ url_for('symlink', path='images/image.png')}}" width="50%">

Upvotes: 1

Ben Lin
Ben Lin

Reputation: 19

It was updated in Starlette 0.24.0 (Feb 2023) that StaticFiles() has a new parameter follow_symlink=True to support symlink.

Upvotes: 1

Related Questions