pallets / flask

The Python micro framework for building web applications.
https://flask.palletsprojects.com
BSD 3-Clause "New" or "Revised" License
67.56k stars 16.15k forks source link

url_for('static', _external=True) gives bogus url with app.url_map.host_matching = True #1559

Closed jab closed 7 years ago

jab commented 9 years ago
app = Flask(__name__)
app.url_map.host_matching = True
app.url_map._rules_by_endpoint['static'][0].host = 'mydomain.com'  # XXX better way to do this?
with app.test_request_context():
    print url_for('static', filename='foo', _external=True)

=> 'http:///static/foo'

Expected 'http://mydomain.com/static/foo'.

Am I missing something, or is this a bug?

Thanks for looking and for the great work on Flask.

jab commented 9 years ago

Just made a PR that fixes this: #1560 Hope this helps. Thanks in advance for reviewing, and let me know if you would prefer another approach.

jab commented 9 years ago

For anyone needing to work around this in the latest stable release (0.10.1), you can remove the static route and re-add it after enabling host_matching:

app = Flask(__name__)
# clear the automatically added route for static
app.url_map._rules.clear()
app.url_map._rules_by_endpoint.clear()
# enable host matching and re-add the static route with the desired host
app.url_map.host_matching = True
app.add_url_rule(app.static_url_path + '/<path:filename>',
                 endpoint='static',
                 view_func=app.send_static_file,
                 host=static_host)
philippe2803 commented 8 years ago

@jab This worked for me. That really helped. Thank you. You may encounter a problem with your fonts however. I had the following message:

Font from origin 'http://statichost.com' has been blocked from loading by Cross-Origin Resource Sharing policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://domainA.com is therefore not allowed access.

For NGINX, the trick is to add add_header Access-Control-Allow-Origin into the static location. It should look as follow:

location /static {
 autoindex on;
 alias /path/to/static/folder;
 add_header "Access-Control-Allow-Origin" "*"; 
}
jab commented 8 years ago

@philippe2803 Glad this helped you. Your fonts issue sounds unrelated fwiw.

blark commented 7 years ago

Ugh. This bug just wasted a couple hours of my time. Finally found this issue, thanks for the info.

Do you know of any way to fix this for Blueprints, so I could have a static folder for each domain that I'm serving? It seems that host= support is very half baked at the moment.

jab commented 7 years ago

Had totally forgotten about this issue! Looks like I submitted a PR that fixes it 15 months ago. It looks like it hasn't been reviewed yet, still merges cleanly, and wouldn't take long to review. Can any maintainers please take a peek, or at least take a minute to chime in? Thanks again for maintaining Flask.

jab commented 7 years ago

Btw happy to help maintain Flask if it would help. I've gotten several commits landed in werkzeug (as well as urllib3, lxml, et al. and am also the author of bidict), fwiw.

blark commented 7 years ago

Any idea how I can improve my hack for getting Blueprint static files to work? Right now I've got:

app.add_url_rule('/static' + '/<path:filename>', endpoint='foo.static',
                 view_func=app.send_static_file, host='test.foo.com')

But I really want to serve the static files from a different directory (not the root /static dir). Do you know if there is any way I can use send_from_directory? Thanks!

EDIT I hacked this together, it works but I can't figure out how to properly tell view_func to pass parameters. I'd rather do something like view_func=app.send_file(path, filename) so I can reuse this function for other Blueprints but it doesn't seem to pass the parameters when I do that.

def send_file(filename, **kwargs):
    return send_from_directory(static_path, filename)

app.add_url_rule('/static' + '/<path:filename>', endpoint='foo.static',
                 view_func=send_file, host=HOST)
jab commented 7 years ago

Just looked through my open pull requests and found #1560, opened August 2015 and not yet acknowledged, which fixes this. Can any maintainers either take a look or delegate sometime soonish? As I said a couple comments above, "happy to help maintain Flask if it would help. I've gotten several commits landed in werkzeug (as well as urllib3, lxml, et al..."