0

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?

Michael Dautermann
  • 88,797
  • 17
  • 166
  • 215
Rose Perrone
  • 61,572
  • 58
  • 208
  • 243
  • Have you tried `localhost:5000/s/../static/images/volume.png`? it sounds like to me that you're passing a relative path to your route rather then starting from your project root and traversing from there. – AlexLordThorsen Aug 15 '13 at 22:02
  • Nope, it redirects immediately to `localhost:5000/s/static/images/volume.png` and gives a `404`. – Rose Perrone Aug 15 '13 at 22:07
  • Do you have to stay on this path? would it be possible to redirect to / ? – AlexLordThorsen Aug 15 '13 at 22:11
  • Yes, I could do that. Why isn't it simple to use different routes and access static resources? – Rose Perrone Aug 15 '13 at 22:13
  • Well, there are one ways you can make this simple but it requires a little bit of hard coding. One solution is to have a `/` variable to the end of everyone one of your URL routes (or at least, to every route you car about). So the s route would turn into `'/s/'` and you'd follow the resource path to your static resource. – AlexLordThorsen Aug 15 '13 at 22:21

1 Answers1

2

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.

Florian
  • 182
  • 1
  • 10
Sean Vieira
  • 155,703
  • 32
  • 311
  • 293