morepath / morepath_cerebral_todomvc

Cerebral TodoMVC with a Morepath REST backend.
BSD 3-Clause "New" or "Revised" License
2 stars 1 forks source link

Allow client router to handle URLs by absorbing the path #1

Closed henri-hulski closed 8 years ago

henri-hulski commented 8 years ago

When calling the root directory ('/') the TodoMVC client redirects to '/all'. You can also filter Todos to show only active or completed ones. The Cerebral router is routing this to '/active' and '/completed'. In the client everything works fine, but when I try to fetch '/all', '/active' or '/completed' from the server I get '404 Not Found'. Only '/' works.and redirect. So refreshing don't work anymore.

The backend is based on morepath_reactredux.

The JSON calls to the REST API works all fine, but actually I don't really understand how serving the website works. It doesn't show up neither in path.py nor in view.py, where we have only the JSON calls to the REST API. It seems to be handled in run.py:

def run():   # pragma: no cover
    morepath.autoscan()

    index = FileApp('static/index.html')
    static = DirectoryApp('static')
    app = App()

    @webob.dec.wsgify
    def morepath_with_static(request):
        if request.path_info_peek() == '':
            return request.get_response(index)

        popped = request.path_info_pop()
        if popped == 'api':
            return request.get_response(app)
        elif popped == 'static':
            return request.get_response(static)

        raise HTTPNotFound()

    morepath.run(morepath_with_static)

So to solve this, we need some absorb mechanism. But I think we have it only for the path directive.

@faassen Do you have any idea, how to solve this?

henri-hulski commented 8 years ago

There is a client-side hack for this. I can use the onlyHash option of cerebral-module-http. It creates URLs like '/#/all', /#/active' and '/#/completed'. This is used by the original cerebral-todomvc and just works. But it doesn't look very nice and I would really prefer to have correct URLs.

Maybe a solution would be to create a sub-app which serves the client. But not sure, how this could look like.

henri-hulski commented 8 years ago

Fixed it by changing morepath_with_static in run.py to:

    @webob.dec.wsgify
    def morepath_with_static_absorb(request):
        popped = request.path_info_pop()
        if popped == 'api':
            return request.get_response(app)
        elif popped == 'static':
            return request.get_response(static)
        else:
            return request.get_response(index)