WebPie URI-to-web method mapping, detailed¶
Here is what actually happens when a WebPie application receives a request for a URI like this: /a/b/c/…/d?x=y&z=q:
Create a WebOb Request object and let it parse the WSGI environment.
Extract the URI path (/a/b/c/…/d) and the query arguments (x=y&z=q) from the WebOb object.
Creates arguments dictionary
{"x":"y", "z":"q"}
.Break the URI path into pieces
["a","b","c",..."d"]
.Set
unseen_path
to["a","b","c",..."d"]
.Create the top Handler object and make the top Handler
current handler
.Loop:
If the
current handler
is callable, setcallable
to thecurrent handler
break out of the loop.If the
unseen path
is empty, exit with error – invalid pathRemove first element from the
unseen_path
and remember it asmethod
If the
current handler
is a WPHandler object and it has an attribute named asmethod
:- Set
current handler
to the method of thecurrent handler
- continue the Loop
- Set
Otherwise, exit with error
join
unused path
into relpath and call thecallable
:response = callable(request, # original WebOb Request object "/".join(unused_path), # joined unused path **arguments # query arguments )
In plain English: URI is mapped to actual web method by going down the tree of WPHandler obcjets starting from the top Handler, looking for first callable and calling it as a web method, passing it the WebOb Request, unused portion of the path and query arguments.
Examples¶
class H1(WPHandler):
def say(self, request, relpath, what="hello", **therest):
# only "what" query argument will be used.
# The rest will be accepted, but ignored
return relpath or what
class Hander(WPHandler):
def __init__(self, *params):
WPHandler.__init__(self, *params)
self.down = H1(*params)
def hello(self, request, relpath, **args):
return relpath
def no_args(self, request, relapth):
return "OK"
def few_args(self, request, relapth, x=None, b="yes"):
return "OK"
app = WPApp(Hander)
This handler will respond to URIs:
/hello # relpath="", args={}
/hello/there # relpath="there", args={}
/hello?a=b # relpath="", args={"a":"b"}
/hi # error - web method not found
/no_args # relpath=""
/no_args?x=y # error - the web method does not expect
# any query arguments
/few_args/abc?x=y # relpath = "abc", x="y", b="yes"
/few_args?b=no # relpath = "", x=None, b="no"
/down/say?what=hi # relpath = "", what="hi", reply: "hi"
/down/say?x=unused # relpath = "", what="hi", reply: "hi"
/down/say/hi # relpath = "hi", what="hello", reply: "hi"
/down/say # relpath = "", what="hello", reply: "hello"
A Handler, which will accept any URI:
class AcceptAll(WPHandler):
def __call__(self, request, relpath, **args):
return f"""
relpath: {relpath}\n
query args: {args}\n
"""
app = WPApp(AcceptAll)
In simple cases, there is no need to create WPHandler explicitly:
def hello_world(request, relpath, **args):
from = f" from {relpath}" if relpath else ""
return f"Hello World!{form}"
WPApp(hello_world).run_server(8080)
Or even shorter, but less readable, unless you are into functional programming:
from webpie import WPApp
WPApp(lambda q,p,x: f"{(((int(x)+19)**3)%101)}").run_server(8888)