11
11
12
12
from __future__ import annotations
13
13
14
+ import asyncio
14
15
import os
15
16
from typing import Awaitable , Callable
16
17
17
- from emmett_core .http .response import HTTPResponse
18
- from emmett_core .protocols .rsgi .handlers import HTTPHandler as _HTTPHandler , WSHandler as _WSHandler
18
+ from emmett_core .http .response import HTTPResponse , HTTPStringResponse
19
+ from emmett_core .protocols .rsgi .handlers import HTTPHandler as _HTTPHandler , WSHandler as _WSHandler , WSTransport
19
20
from emmett_core .utils import cachedprop
20
- from granian .rsgi import (
21
- HTTPProtocol ,
22
- Scope ,
23
- )
24
21
25
- from ..ctx import current
22
+ from ..ctx import RequestContext , WSContext , current
26
23
from ..debug import debug_handler , smart_traceback
27
24
from ..wrappers .response import Response
28
25
from .wrappers import Request , Websocket
@@ -37,7 +34,7 @@ class HTTPHandler(_HTTPHandler):
37
34
def error_handler (self ) -> Callable [[], Awaitable [str ]]:
38
35
return self ._debug_handler if self .app .debug else self .exception_handler
39
36
40
- def _static_handler (self , scope : Scope , protocol : HTTPProtocol , path : str ) -> Awaitable [HTTPResponse ]:
37
+ def _static_handler (self , scope , protocol , path : str ) -> Awaitable [HTTPResponse ]:
41
38
#: handle internal assets
42
39
if path .startswith ("/__emmett__" ):
43
40
file_name = path [12 :]
@@ -57,6 +54,51 @@ async def _debug_handler(self) -> str:
57
54
current .response .headers ._data ["content-type" ] = "text/html; charset=utf-8"
58
55
return debug_handler (smart_traceback (self .app ))
59
56
57
+ async def dynamic_handler (self , scope , protocol , path : str ) -> HTTPResponse :
58
+ request = Request (
59
+ scope ,
60
+ path ,
61
+ protocol ,
62
+ max_content_length = self .app .config .request_max_content_length ,
63
+ max_multipart_size = self .app .config .request_multipart_max_size ,
64
+ body_timeout = self .app .config .request_body_timeout ,
65
+ )
66
+ response = Response ()
67
+ ctx = RequestContext (self .app , request , response )
68
+ ctx_token = current ._init_ (ctx )
69
+ try :
70
+ http = await self .router .dispatch (request , response )
71
+ except HTTPResponse as http_exception :
72
+ http = http_exception
73
+ #: render error with handlers if in app
74
+ error_handler = self .app .error_handlers .get (http .status_code )
75
+ if error_handler :
76
+ http = HTTPStringResponse (
77
+ http .status_code , await error_handler (), headers = response .headers , cookies = response .cookies
78
+ )
79
+ except Exception :
80
+ self .app .log .exception ("Application exception:" )
81
+ http = HTTPStringResponse (500 , await self .error_handler (), headers = response .headers )
82
+ finally :
83
+ current ._close_ (ctx_token )
84
+ return http
85
+
60
86
61
87
class WSHandler (_WSHandler ):
62
88
wrapper_cls = Websocket
89
+
90
+ async def dynamic_handler (self , scope , transport : WSTransport , path : str ):
91
+ ctx = WSContext (self .app , Websocket (scope , path , transport ))
92
+ ctx_token = current ._init_ (ctx )
93
+ try :
94
+ await self .router .dispatch (ctx .websocket )
95
+ except HTTPResponse as http :
96
+ transport .status = http .status_code
97
+ except asyncio .CancelledError :
98
+ if not transport .interrupted :
99
+ self .app .log .exception ("Application exception:" )
100
+ except Exception :
101
+ transport .status = 500
102
+ self .app .log .exception ("Application exception:" )
103
+ finally :
104
+ current ._close_ (ctx_token )
0 commit comments