python|web application framework|add dynamic routing

Yesterday we have modified the web route registration, changing it from function registration to class decorator registration. If you haven’t read the previous article, I suggest you read it first so that you can do it. To connect the previous and the following:

python|web application framework|use class decorator to register routes: juejin.cn/post/722879…

Today we will continue adding regular expressions to the routing of the framework.

The python environment this article relies on is:

What is the use of adding regular expressions to routes?

Before introducing, we first need to introduce the following parameter passing methods when Get obtains resources:

  • Use the form of key...value and put the parameters after the url question mark ?, such as: http://127.0. 0.1/userInfo?name=pdudo
  • Pass it as a path parameter in url, for example: http://127.0.0.1/userInfo/pdudo/info.
  • Pass parameters in the request header. The request header is stored in the form of key...value. Of course, you can also customize the request parameters.

The second method of passing parameters in the form of path parameters is the point described in our article here.

Why is this necessary?

Suppose we are writing a function now, which needs to return the uploaded user information. The interface is: /userInfo/userid/infos, where userid is dynamic, so the interface can It is /userInfo/c12345/infos, or it can be /userInfo/d33456/infos and so on.

If this is the case, how should we define routing? Do you define routing information for everyone in the project?

Obviously not. If at this time, the registered route happens to be regular, you can get the parameters passed by the client, for example: /userInfo/pdudo/info, the function will get pdudo, isn’t this great?

This requires the use of regular expressions.

How to define dynamic routing

Since we have already written the relevant methods for defining static routes before, when we define dynamic routes, it is best to add an identification parameter to tell the framework whether this route is static or dynamic.

Since it is a dynamic route, some values in the route url must be dynamic. How to distinguish between static values and dynamic values? In this framework, we enclose dynamic values in curly brackets, such as: /userInfo/{userID}/infos, where userID is dynamic and can be any value composition, but /userInfo and /infos must be static, and the order is fixed.

So, we can restrict it. When defining dynamic routing, we need to tell the framework that this is dynamic routing and dynamic url.

So we are going to plan the dynamic routing definition as follows:

@myWeb.routes(path="/jobs/{jobID}/startd",methods="post",regular=True)
def startJobs(r,cData):
    print("cData: " ,cData)

The above code is a code example after we are about to improve the function. regular is True, which means that the route is dynamic, and the value of path is /jobs/{jobID}/startd, where jobID is also dynamic and can be replaced by any value.

Finally, the function will receive 2 parameters. The value of r represents the environ information in wsgi. And cData represents the value reported from the client, that is: the replacement value of jobID.

Register dynamic routing

As above, we have constrained the addition rules of a dynamic route, so how do we register the dynamic route?

First of all, it is certain that dynamic routing cannot be placed together with static routing, so we have defined a new dictionary to store dynamic routing information, such as:

mapGetRegularRouting = {}
mapPostRegularRouting = {}

Then we need to convert the registered routing information into a regular expression. Here is an example:

The route we registered is like this: /jobs/{jobID}/startd, we need to convert it into a regular expression, the value of the regular expression is like this: ^/jobs/ (.*?)/startd$.

Regarding this regular expression, its meaning is to match the string starting with /jobs/ and ending with /startd, and the matched information (. *‘s value) is stored in a tuple.

Note that the question mark ? after .* here means that greedy matching is not enabled, that is, minimized matching.

The question now is, how to convert {jobsID} to (.*?)? In python, you can use re.sub to perform replacement operations. We can use the following statement to replace {jobsID} with (.*?), the code is as follows:

import re
print(re.sub("{.*?}","(.*?)","/jobs/{jobID}/startd"))

The result of executing the above code is:

Finally, the routing information is stored in the dictionary defined above. The code snippet is as follows:

reFindall = re.compile(r"{(.*?)}")
reSubAll = re.compile(r"{.*?}")

parameter = re.findall(reFindall,self.path)
reText = re.sub(reSubAll,"(.*?)",self.path)
reText = f"{reText}$"
regular = {
    "original": self.path,
    "reText": reText,
    "parameter": parameter,
    "func": func
}
#...
if self.re:
    mapPostRegularRouting[regular["reText"]] = regular

At this point, our dynamic routing has been registered.

Match dynamic routing

Compared with registering dynamic routes, when a client request comes, matching dynamic routes will be very troublesome, because there is no request message to tell you whether it is a dynamic route or a static route, so matching dynamic routes is very troublesome.

When we match dynamic routes, we think of a stupid way, that is: match static routes first. If the static routes cannot be matched, then match the dynamic routes. If the dynamic routes cannot be matched, then the default route is selected.

Matching static routing and dynamic routing has been introduced in the previous chapter, so I will not go into details here. Here we will introduce how to match dynamic routing.

The so-called dynamic routing rule matching actually means taking the url uploaded by the client and doing rotation training on our existing regular expressions one by one. If the match is successful, we will exit the loop. If the match fails, we will finally Just return a default route, and the matching regular expression code is as follows:

for key in RegularRouting.keys():
    if re.match(key, path):
        isRegular = True
        collText = re.findall(key, path)
        func = RegularRouting[key]["func"]
        break
else:
    func = Route["/*"]

Framework operation effect display

Regarding myWeb.py, it is very long, with more than 100 lines. It is not easy to take screenshots or just copy the code, so I put it on gitee: gitee.com/pdudo /golea…

Let’s simply write a few demo to test the web framework. The code is as follows:

import myWeb
import wsgiref.simple_server

@myWeb.routes(path="/ip",methods="all")
def indx(r):
    print(r["REMOTE_ADDR"])
    return (200,r["REMOTE_ADDR"])

@myWeb.routes(path="/hello/{name}",methods="get",regular=True)
def helloWold(r,cData):
    name = cData[0]
    return (200,"hello %s" % (name))

def main():
    s = wsgiref.simple_server.make_server('', 8888, myWeb.application)
    s.serve_forever()

if __name__ == '__main__':
    main()

In the above code, we first introduced the myWeb and wsgiref modules. The front part is written by ourselves, and the latter is a server framework that meets the requirements of wsgi. In the code, we define two routing information, one is static routing and the other is dynamic routing. The function of static routing is indx, and the routing information is /ip. The matching client request method is get or post, which mainly returns the ip address.

The function of dynamic routing is helloWold, which will match the routing information headed by /hello/, and the matching client request method is get. The return function mainly obtains the dynamic value sent by the user and returns it to the client in the form of hello etc.

In the main function, we start a simple wsgi server, and the entrance is the application method of myWeb.

The code runs as follows:

We use the get and post methods respectively to request the local /ip route. It can be seen that they all responded back, and then we accessed /hello/ pdudo and /hello/juejin, they also replied to hello pdudo and hello juejin respectively.

Summary

This document introduces the modification of the previous web framework and routing into regular expression form. The specific adding method is: when registering the route, convert its routing information into a regular expression, and when When performing route matching, first match the static server. If there is no static server, then perform regular matching. If regular matching still fails, return to the final default page.


———————————END——————- ——–

Digression

In the current era of big data, how can one keep up with the times without mastering a programming language? Python, the hottest programming language at the moment, has a bright future! If you also want to keep up with the times and improve yourself, please take a look.

Interested friends will receive a complete set of Python learning materials, including interview questions, resume information, etc. See below for details.


CSDN gift package:The most complete “Python learning materials” on the Internet are given away for free! (Safe link, click with confidence)

1. Python learning routes in all directions

The technical points in all directions of Python have been compiled to form a summary of knowledge points in various fields. Its usefulness is that you can find corresponding learning resources according to the following knowledge points to ensure that you learn more comprehensively.

img
img

2. Essential development tools for Python

The tools have been organized for you, and you can get started directly after installation! img

3. Latest Python study notes

When I learn a certain basic and have my own understanding ability, I will read some books or handwritten notes compiled by my seniors. These notes record their understanding of some technical points in detail. These understandings are relatively unique and can be learned. to a different way of thinking.

img

4. Python video collection

Watch a comprehensive zero-based learning video. Watching videos is the fastest and most effective way to learn. It is easy to get started by following the teacher’s ideas in the video, from basic to in-depth.

img

5. Practical cases

What you learn on paper is ultimately shallow. You must learn to type along with the video and practice it in order to apply what you have learned into practice. At this time, you can learn from some practical cases.

img

6. Interview Guide

Resume template

CSDN gift package:The most complete “Python learning materials” on the Internet are given away for free! (Safe link, click with confidence)

If there is any infringement, please contact us for deletion.