flaskflask-assets

Flask import static resources


The problem: I get a 404 when I access static resources from any route other than '/'.

I have an image called volume.png in my static folder in my Flask application. When I route my main page to '/' using @app.route('/') it finds the image fine, and I can display the image when I hit localhost:5000/static/images/volume.png. But when I use any other link, for example, '/s', it says it can't find the image in s/static/images/volume.png. Even when I create an s directory and copy the static directory to it, I get a 404 when I type localhost:5000/s/static/images/volume.png. I've considered using Flask-Assets, but there doesn't appear to be much documentation or examples. What's a good way to make sure my routes have access to the static resources?


Solution

  • You need to qualify the path to your image in your HTML (or CSS):

    <!-- This will break in the way you describe -->
    <img src="static/images/volume.png" />
    
    <!-- This will not -->
    <img src="/static/images/volume.png" />
    
    <!-- Nor will this (assuming you are using a Jinja template) -->
    <img src="{{ url_for('static', filename='images/volume.png') }}" />
    

    The reason for this is because of the way that user-agents are required to resolve relative paths for URIs (see section 5.1 of RFC 3968 for the details).

    Using static/images/volume.png results in the following path at /:

    scheme://host.name/static/images/volume.png
    

    and the following at /s:

    scheme://host.name/s/static/images/volume.png
    

    as you have discovered. By ensuring that you provide an absolute path component (at the very least) for your resources, you ensure that the browser will merge your provided path with only scheme and host.name, rather than with scheme, host.name and path.