Search code examples
pythonwindowssymlinkcherrypy

How to get CherryPy to follow symbolic links?


I am trying to run a local server that (for now) serves mostly static content from a Windows 7 machine. The problem is that a lot of the content is organized using symbolic links, and when I try and serve these files using CherryPy, they always return:

The requested resource returned more bytes than the declared Content-Length.

Presumably this is because CherryPy checks the size of the symbolic link on disk, uses that for the Content-Length, then when it tries to access the file, Windows gives it the full size of the file, and so the two don't match. I'm guessing that this problem has been solved at some point, and that there's a config option that I just don't know about, but I can't seem to find a full listing of all CherryPy configuration options. Anyone have a good solution for this?


Solution

  • As far as I see this issue has nothing to do with CherryPy. If you have looked at cherrypy.lib.static.serve_file you would see the following.

    try:
        st = os.stat(path)
    except OSError:
        if debug:
            cherrypy.log('os.stat(%r) failed' % path, 'TOOLS.STATIC')
        raise cherrypy.NotFound()
    
    # ...
    
    # Set Content-Length and use an iterable (file object)
    #   this way CP won't load the whole file in memory
    content_length = st.st_size
    fileobj = open(path, 'rb')
    return _serve_fileobj(fileobj, content_type, content_length, debug=debug)
    

    Python documentation states about os.stat:

    Perform the equivalent of a stat() system call on the given path. (This function follows symlinks; to stat a symlink use lstat().)

    Wikipedia points to restrictions in creating symbolic links as only elevated administrators can create them. So it doesn't look like a common feature. There are also few types of these links, ways to enable them, so they may behave differently.

    Anyway it's easy to check whether os.stat really follows the symbolic links you have on your platform:

    import os
    print os.stat('/path/to/filename').st_size
    

    If you don't think the result is correct I'd suggest you to file a report to Python bug tracker.