klein
klein copied to clipboard
Unable to serve index.html at the route "/"
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
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
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
.
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)
So, did PR #59 fix this?
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?
It's an issue with twisted.web.static.File
.
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.
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
)
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.
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
@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)
In my case I have the same issue. I solved it by using '' as root path
resource.putChild('', File(....))