Closed WolfgangFahl closed 2 years ago
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
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
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
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
as an amendment to #481 the routing as intended by #478 is broken. examples/tutorial/routes/route3.py has been modified slightly for this:
http://localhost:8000/hello/budy
will lead to KeyError: 'name'