Static files not loaded in a Bottle application when the trailing slash is omitted

前端 未结 3 1545
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-02-06 19:13

I am serving a test file through apache using Bottle.

Following are my apache config:

WSGIDaemonProcess temp user=www-data group=www-data processes=1 thr         


        
相关标签:
3条回答
  • 2021-02-06 19:39

    The Problem

    The problematic line is this one:

    <link rel="stylesheet" type="text/css" href="static/prettify.css" />
    

    The address of the CSS file is a relative one, thus the full absolute address is computed from the loaded page location.

    For http://192.168.1.3/temp/, it will be http://192.168.1.3/temp/static/prettify.css (correct).

    For http://192.168.1.3/temp, it will be http://192.168.1.3/static/prettify.css. temp is considered to be a file in the root directory, not a subdirectory of its own right.

    The Solution

    There is no viable way to use a single relative address for referring to the static resources. Your application will likely to have “nested” paths like /article/some-name, or /view/content/566, or something like this, as well as paths as simple as /.

    You can try to specify a root-based path, like /temp/static/prettify.css, in your template, but this means you will have to change the template if you relocate the app itself (say, to myapp.example.com/ from example.com/myapp/).

    Instead, you need to tell the framework to make the correct path to the resource you need to use. Bottle has a function named get_url to facilitate this. Unfortunately, it's not mentioned in the Bottle tutorials.

    The Code

    Here's what you should do.

    In template.tpl, call get_url referring to the static handler:

    <link rel="stylesheet" type="text/css" 
          href="{{ get_url('static', filename='prettify.css') }}" />
    

    In routes.py, import get_url:

    from bottle import Bottle, run, route, static_file, view, template, 
                       post, request, get_url
    

    Then, name your handler so you can pass its name to get_url:

    @app.route('/static/<filename>', name='static')
    def server_static(filename):
        return static_file(filename, root='static')
    

    Finally, supply the actual get_url as the template argument when rendering the template:

    @app.route('/') 
    def index(): 
        return template('template', text='This is index page!', get_url=get_url)
    

    Alternatively, instead of supplying get_url in every handler, set up a template default in index.py:

    from Bottle import SimpleTemplate
    SimpleTemplate.defaults["get_url"] = app.get_url
    

    Caveat: The last method seems to be undocumented, but was explained by the Bottle's author on the mailing list.

    Final Thought

    As every page on a website should have a canonical address, you might want to choose one form (either with a trailing slash or without one) as canonical, and add some kind of redirect from the other one.

    0 讨论(0)
  • 2021-02-06 19:47

    One workaround is to add:

    <base href="/temp/">
    

    to the head in the template.

    0 讨论(0)
  • 2021-02-06 19:49

    Another workaround is to add this redirection in your Apache configuration file :

    RedirectMatch 301 ^/(temp)$ /$1/
    

    This will add a / at the end of your index page, so you don't have to modify your code.

    0 讨论(0)
提交回复
热议问题