klein icon indicating copy to clipboard operation
klein copied to clipboard

Unable to serve index.html at the route "/"

Open michaelnt opened this issue 10 years ago • 12 comments

The following doesn't work, returning a file not found error.

@app.route("/")
def root(request):
   return File("index.html")

The following works

@app.route("/index.html")
def root(request):
   return File("index.html")

And this also works

@app.route("/")
def root(request):
   return "Hello"

This is a failing test that I think illustrates the problem

    def test_staticRoot_noBranch(self):
        """
        The following should return the contents of the file index.html

        @app.route("/")
        def root(request):
            return File("index.html")

        """
        app = self.app
        request = requestMock("/")

        @app.route("/")
        def root(request):
            return File(__file__)

        d = _render(self.kr, request)

        def _cb(result):
            self.assertEqual(request.getWrittenData(), 
                open(__file__).read())
            self.assertEqual(request.finishCount, 1)

        d.addCallback(_cb)
        return d

michaelnt avatar Jan 12 '14 15:01 michaelnt

I have a similar experience. I thought that returning an absolute path to a file served on / would work, but didn't. Solved it by:

@app.route('/')
def bootstrap(self, request):
    f = static.File(get_assets_path('html'))
    f.indexNames = ['bootstrap.html']
    return f

magnusp avatar Mar 05 '14 22:03 magnusp

This is not a problem unique to klein.

Consider the following invocation of twistd's web plugin:

$ echo "Hello, world!" > hello.txt
$ twistd -n web --path hello.txt
2014-03-14 13:00:24-0700 [-] Log opened.
2014-03-14 13:00:24-0700 [-] twistd 12.2.0 (/System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python 2.7.5) starting up.
2014-03-14 13:00:24-0700 [-] reactor class: twisted.internet.selectreactor.SelectReactor.
2014-03-14 13:00:24-0700 [-] Site starting on 8080
2014-03-14 13:00:24-0700 [-] Starting factory <twisted.web.server.Site instance at 0x10d675488>
2014-03-14 13:00:26-0700 [HTTPChannel,0,127.0.0.1] 127.0.0.1 - - [14/Mar/2014:20:00:26 +0000] "GET / HTTP/1.1" 404 145 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.149 Safari/537.36"

You'll notice that GET / always fails with a 404.

dreid avatar Mar 14 '14 20:03 dreid

Is this addressed by using the same technique as in #59? I.E., something like this:

...

UPDATE: The technique from #59 seems to work for me:

from klein import Klein
from twisted.web.static import File

app = Klein()

@app.route('/', branch=True)
def root(request):
    f = File(__file__)
    f.isLeaf = True
    f.type, f.encoding = 'text/plain', None # force MIME type for browser rendering
    return f

if __name__ == '__main__':
   app.run('localhost', 8080)

posita avatar May 04 '15 23:05 posita

So, did PR #59 fix this?

brighid avatar Sep 09 '15 05:09 brighid

Used the original reporter's code to reproduce this with Klein version 15.1.

@dreid: Would you say this is a bug in Klein's code, a quirk that the docs should explain, or neither?

brighid avatar Sep 11 '15 21:09 brighid

It's an issue with twisted.web.static.File.

dreid avatar Sep 11 '15 23:09 dreid

So I'm hearing "the thing to do about it on the Klein side is note it in the docs, then remove the note when it's fixed in Twisted"?

I'm inclined to hear that because I'm working on another PR that is about updating and expanding Klein's docs.

brighid avatar Sep 12 '15 00:09 brighid

I think that is a worthwhile approach even if @hawkowl or @glyph (or anyone else really) decides to address it in Klein. (Note: I know longer work on Klein due to lack of time and no longer using it in my job.)

If someone wanted to make it "just work" the approach would probably be to ask the static.File if it is a file or a directory. And set isLeaf if it is a file. (static.File provides IFilePath)

dreid avatar Sep 12 '15 02:09 dreid

Ah, thanks for clarifying your role—mostly @-mentioned you because you were the last contributor in the thread. Okay, I'll make a note about this behavior in the docs update branch and nudge the @hawkowl about this issue after that PR's sorted.

brighid avatar Sep 12 '15 04:09 brighid

Don't ask me why, but that works:

    @app.route("/")
    def index(self, _request):
        return File(path_to_index_html)

    @app.route("/index.html")
    def index(self, _request):
        return File(path_to_index_html)

if the two functions does not have the same name, it does not work

gsemet avatar Oct 21 '17 22:10 gsemet

@Stibbons I'm not exactly sure why it works, but that is taking advantage of a bug in the way that we look up routes in werkzeug's url_map; it probably won't work forever :).

The workaround from @posita up-thread will work fine.

Or, perhaps to illustrate the issue more succinctly:

from klein import Klein
from twisted.web.resource import Resource
from twisted.web.static import File

app = Klein()

@app.route('/')
def root(request):
    f = File(__file__)
    f.type, f.encoding = 'text/plain', None
    r = Resource()
    r.putChild(b"", f)
    return r

if __name__ == '__main__':
   app.run('localhost', 8080)

glyph avatar Nov 12 '17 09:11 glyph

In my case I have the same issue. I solved it by using '' as root path

resource.putChild('', File(....))

llazzaro avatar Nov 24 '17 15:11 llazzaro