Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

followup issue routing parameter #502

Closed
WolfgangFahl opened this issue Sep 7, 2022 · 6 comments
Closed

followup issue routing parameter #502

WolfgangFahl opened this issue Sep 7, 2022 · 6 comments
Assignees
Labels
bug Something isn't working core
Milestone

Comments

@WolfgangFahl
Copy link
Collaborator

WolfgangFahl commented Sep 7, 2022

as an amendment to #481 the routing as intended by #478 is broken.
examples/tutorial/routes/route3.py has been modified slightly for this:

# Justpy Tutorial demo  from docs/tutorial/routes.md
import justpy as jp
def greeting_function(request):
    wp = jp.WebPage()
    name=f"""{request.path_params["name"]}"""
    wp.add(jp.P(text=f'Hello there, {name}!', classes='text-5xl m-2'))
    return wp
jp.Route('/hello/{name}', greeting_function)

# initialize the demo
from  examples.basedemo import Demo
Demo ("route3",None)
scripts/start examples/tutorial/routes/route3.py

http://localhost:8000/hello/budy

will lead to
KeyError: 'name'

name=f"""{request.path_params["name"]}"""
@WolfgangFahl WolfgangFahl added bug Something isn't working core labels Sep 7, 2022
@WolfgangFahl WolfgangFahl added this to the 0.6 milestone Sep 7, 2022
@WolfgangFahl WolfgangFahl self-assigned this Sep 7, 2022
WolfgangFahl added a commit that referenced this issue Sep 7, 2022
@WolfgangFahl WolfgangFahl changed the title followup issues followup issue routing parameter Sep 7, 2022
@WolfgangFahl WolfgangFahl modified the milestones: 0.6, 0.7, 0.8 Sep 7, 2022
@WolfgangFahl
Copy link
Collaborator Author

see encode/starlette#1196

@WolfgangFahl
Copy link
Collaborator Author

This would be a way to move the homepage to the end - but it would only work for justpy special routing

def getRoutesByPriority(self):
        """
        get the routes by priority
        """
        routes=self.router.routes
        routes_by_priority=[]
        homepage=None
        for route in routes:
            if isinstance(route,Route):
                if route.name and route.name =="Homepage":
                    homepage=route
                else:
                    routes_by_priority.append(route)
        if homepage:
            routes_by_priority.append(homepage)
        return routes_by_priority

@WolfgangFahl
Copy link
Collaborator Author

see also tiangolo/fastapi#317

WolfgangFahl added a commit that referenced this issue Sep 10, 2022
WolfgangFahl added a commit that referenced this issue Sep 10, 2022
@WolfgangFahl
Copy link
Collaborator Author

Original HomePage code:

@app.route("/{path:path}")
class Homepage(HTTPEndpoint):

    async def get(self, request):
        # Handle web requests
        session_cookie = request.cookies.get(SESSION_COOKIE_NAME)
        if SESSIONS:
            new_cookie = False
            if session_cookie:
                try:
                    session_id = cookie_signer.unsign(session_cookie).decode("utf-8")
                except:
                    return PlainTextResponse('Bad Session')
                request.state.session_id = session_id
                request.session_id = session_id
            else:
                # Create new session_id
                request.state.session_id = str(uuid.uuid4().hex)
                request.session_id = request.state.session_id
                new_cookie = True
                logging.debug(f'New session_id created: {request.session_id}')
        for route in Route.instances:
            func = route.matches(request['path'], request)
            if func:
                func_to_run = func
                break
        func_parameters = len(inspect.signature(func_to_run).parameters)
        assert func_parameters < 2, f"Function {func_to_run.__name__} cannot have more than one parameter"
        if inspect.iscoroutinefunction(func_to_run):
            if func_parameters == 1:
                load_page = await func_to_run(request)
            else:
                load_page = await func_to_run()
        else:
            if func_parameters == 1:
                load_page = func_to_run(request)
            else:
                load_page = func_to_run()
        if isinstance(load_page, Response):
            logging.debug('Returning raw starlette.responses.Response.')
            return load_page
        assert issubclass(type(load_page), WebPage), 'Function did not return a web page'
        assert len(load_page) > 0 or load_page.html, '\u001b[47;1m\033[93mWeb page is empty, add components\033[0m'
        page_options = {'reload_interval': load_page.reload_interval, 'body_style': load_page.body_style,
                        'body_classes': load_page.body_classes, 'css': load_page.css, 'head_html': load_page.head_html, 'body_html': load_page.body_html,
                        'display_url': load_page.display_url, 'dark': load_page.dark, 'title': load_page.title, 'redirect': load_page.redirect,
                        'highcharts_theme': load_page.highcharts_theme, 'debug': load_page.debug, 'events': load_page.events,
                        'favicon': load_page.favicon if load_page.favicon else FAVICON}
        if load_page.use_cache:
            page_dict = load_page.cache
        else:
            page_dict = load_page.build_list()
        template_options['tailwind'] = load_page.tailwind
        context = {'request': request, 'page_id': load_page.page_id, 'justpy_dict': json.dumps(page_dict, default=str),
                   'use_websockets': json.dumps(WebPage.use_websockets), 'options': template_options, 'page_options': page_options,
                   'html': load_page.html}
        response = templates.TemplateResponse(load_page.template_file, context)
        if SESSIONS and new_cookie:
            cookie_value = cookie_signer.sign(request.state.session_id)
            cookie_value = cookie_value.decode("utf-8")
            response.set_cookie(SESSION_COOKIE_NAME, cookie_value, max_age=COOKIE_MAX_AGE, httponly=True)
            for k, v in load_page.cookies.items():
                response.set_cookie(k, v, max_age=COOKIE_MAX_AGE, httponly=True)
        if LATENCY:
            await asyncio.sleep(LATENCY/1000)
        return response

WolfgangFahl added a commit that referenced this issue Sep 11, 2022
WolfgangFahl added a commit that referenced this issue Sep 11, 2022
WolfgangFahl added a commit that referenced this issue Sep 11, 2022
WolfgangFahl added a commit that referenced this issue Sep 12, 2022
WolfgangFahl added a commit that referenced this issue Sep 12, 2022
WolfgangFahl added a commit that referenced this issue Sep 13, 2022
@WolfgangFahl
Copy link
Collaborator Author

a wrap decorator might solve the issue - we tested this with

"""
Created on 2022-09-13

@author: wf
"""
import justpy as jp
from starlette.requests import Request
from tests.base_client_test import BaseClienttest
import time
# https://fastapi.tiangolo.com/tutorial/middleware/
@jp.app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    start_time = time.time()
    func=request.app.get_func_for_request(request)
    response = await call_next(request)
    process_time = time.time() - start_time
    response.headers["X-Process-Time"] = str(process_time)
    return response

@jp.app.route("/webpage", name="webpage")
@jp.app.wrap
def hello_world(_request):
    wp = jp.WebPage()
    _d = jp.Div(text='I am justpy webpage',a=wp)
    return wp

class TestMiddleWare(BaseClienttest):
    """
    test FASTAPI middleware 
    """
    
    def setUp(self, debug=False, profile=True):
        BaseClienttest.setUp(self, debug=debug, profile=profile)
        self.app.prioritize_routes()
    
    def test_middleware(self):
        """
        test the middleware 
        """
        response=self.checkResponse("/webpage",debug=True)
        pass   

and had to move the def get_response_for_load_page(self,request,load_page) to JustpyApp for a start.

def wrap(self,fn):
        """
        decorator
        """
        def funcResponse(request,*args,**kwargs):
            wp=fn(request)
            response=self.get_response_for_load_page(request, wp)
            return response
        pass
    
        return funcResponse

@freemant2000
Copy link
Contributor

Perhaps I am missing something. I don't understand why the code below is needed. Why not just add the route for the homepage only when the justpy() function is called? As it is the catch all page with a most generic path, it makes sense to add it last, right?

super().add_route(path,route,methods,name,include_in_schema)
        if name: 
            if name=="justpy_homepage":
                routes= self.router.routes.copy()
                last=routes[len(routes)-1]
                routes.remove(last)
                routes.insert(0,last)
                self.router.routes=routes
                pass
            else:
                JpRoute(path=path,endpoint=route,name=name)
        pass

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working core
Projects
None yet
Development

No branches or pull requests

2 participants