def push ( self) - > None :
top = _request_ctx_stack. top
if top is not None and top. preserved:
top. pop( top. _preserved_exc)
app_ctx = _app_ctx_stack. top
if app_ctx is None or app_ctx. app != self. app:
app_ctx = self. app. app_context( )
app_ctx. push( )
self. _implicit_app_ctx_stack. append( app_ctx)
else :
self. _implicit_app_ctx_stack. append( None )
_request_ctx_stack. push( self)
if self. session is None :
session_interface = self. app. session_interface
self. session = session_interface. open_session( self. app, self. request)
if self. session is None :
self. session = session_interface. make_null_session( self. app)
if self. url_adapter is not None :
self. match_request( )
def match_request ( self) - > None :
try :
result = self. url_adapter. match ( return_rule= True )
self. request. url_rule, self. request. view_args = result
except HTTPException as e:
self. request. routing_exception = e
def match (
self,
path_info: t. Optional[ str ] = None ,
method: t. Optional[ str ] = None ,
return_rule: bool = False ,
query_args: t. Optional[ t. Union[ t. Mapping[ str , t. Any] , str ] ] = None ,
websocket: t. Optional[ bool ] = None ,
) - > t. Tuple[ t. Union[ str , Rule] , t. Mapping[ str , t. Any] ] :
self. map . update( )
if path_info is None :
path_info = self. path_info
else :
path_info = _to_str( path_info, self. map . charset)
if query_args is None :
query_args = self. query_args or { }
method = ( method or self. default_method) . upper( )
if websocket is None :
websocket = self. websocket
require_redirect = False
domain_part = self. server_name if self. map . host_matching else self. subdomain
path_part = f"/ { path_info. lstrip( '/' ) } " if path_info else ""
path = f" { domain_part} | { path_part} "
have_match_for = set ( )
websocket_mismatch = False
for rule in self. map . _rules:
try :
rv = rule. match ( path, method)
except RequestPath as e:
raise RequestRedirect(
self. make_redirect_url(
url_quote( e. path_info, self. map . charset, safe= "/:|+" ) ,
query_args,
)
) from None
except RequestAliasRedirect as e:
raise RequestRedirect(
self. make_alias_redirect_url(
path, rule. endpoint, e. matched_values, method, query_args
)
) from None
if rv is None :
continue
if rule. methods is not None and method not in rule. methods:
have_match_for. update( rule. methods)
continue
if rule. websocket != websocket:
websocket_mismatch = True
continue
if self. map . redirect_defaults:
redirect_url = self. get_default_redirect( rule, method, rv, query_args)
if redirect_url is not None :
raise RequestRedirect( redirect_url)
if rule. redirect_to is not None :
if isinstance ( rule. redirect_to, str ) :
def _handle_match ( match : t. Match[ str ] ) - > str :
value = rv[ match . group( 1 ) ]
return rule. _converters[ match . group( 1 ) ] . to_url( value)
redirect_url = _simple_rule_re. sub( _handle_match, rule. redirect_to)
else :
redirect_url = rule. redirect_to( self, ** rv)
if self. subdomain:
netloc = f" { self. subdomain} . { self. server_name} "
else :
netloc = self. server_name
raise RequestRedirect(
url_join(
f" { self. url_scheme or 'http' } :// { netloc} { self. script_name} " ,
redirect_url,
)
)
if require_redirect:
raise RequestRedirect(
self. make_redirect_url(
url_quote( path_info, self. map . charset, safe= "/:|+" ) , query_args
)
)
if return_rule:
return rule, rv
else :
return rule. endpoint, rv
if have_match_for:
raise MethodNotAllowed( valid_methods= list ( have_match_for) )
if websocket_mismatch:
raise WebsocketMismatch( )
raise NotFound( )
def match (
self, path: str , method: t. Optional[ str ] = None
) - > t. Optional[ t. MutableMapping[ str , t. Any] ] :
if not self. build_only:
require_redirect = False
m = self. _regex. search( path)
if m is not None :
groups = m. groupdict( )
if (
self. strict_slashes
and not self. is_leaf
and not groups. pop( "__suffix__" )
and (
method is None or self. methods is None or method in self. methods
)
) :
path += "/"
require_redirect = True
elif not self. strict_slashes:
del groups[ "__suffix__" ]
result = { }
for name, value in groups. items( ) :
try :
value = self. _converters[ name] . to_python( value)
except ValidationError:
return None
result[ str ( name) ] = value
if self. defaults:
result. update( self. defaults)
if self. merge_slashes:
new_path = "|" . join( self. build( result, False ) )
if path. endswith( "/" ) and not new_path. endswith( "/" ) :
new_path += "/"
if new_path. count( "/" ) < path. count( "/" ) :
path = url_unquote( new_path)
require_redirect = True
if require_redirect:
path = path. split( "|" , 1 ) [ 1 ]
raise RequestPath( path)
if self. alias and self. map . redirect_defaults:
raise RequestAliasRedirect( result)
return result
return None