I am currently creating an HTTP server that supports RESTful. In order to support url like /user/:user/:id, I have created a mechanism to find the endpoint from the url.
My current code:
self.index_array= [
"POST-/foo/__",
"GET-/user/__/__"
]
self.index = {
"/foo/__": ["POST"],
"/user/__/__": ["GET"]
}
self.endpoints = [EndPointClass(...), EndPointClass(...)]
def get(self, method, path):
# Static
if path in self.index and method in self.index[path]:
return self.endpoints[self.index_array.index(method + "-" + path)]
# Dynamic
parts = path.split("/")
for a in parts:
test = path.replace(a, "__", 1)
if method + "-" + test in self.index_array:
return self.endpoints[self.index_array.index(method + "-" + test)]
This above code can route paths like /foo/bar, but cannot route paths with more than one path argument like /user/username/1234. I am thinking of splitting this for method and processing it recursively, but this idea will slow down the execution speed as the path nesting gets deeper.
Also, the reason why I don't use regular expressions is because I believe that using regular expressions will cause terrible backtracking and slow down the process.
Can anyone tell me how I can route an endpoint that contains more than one path argument?
I am using a translator, so if you have any questions, please comment and I will do my best to answer them. If you have any questions or comments, please comment to me.
Thank you.
There is a million ways to do it just keep it simple for yourself. You can turn your index_array into index_tree using dictionaries, for example:
index_tree = {
"POST":{"foo":{"endpoint":1}}
"GET": {
"user":{
"username": {"endpoint":2},
"email":{"endpoint":5}
},
"bar":{
"DirtyGoose": {"endpoint":3},
"3HornUnicorn": {"endpoint":4}
}
}
}
And then navigate them simply after split:
nodes = path.split()
cur = index_tree
for i, node in enumerate(nodes):
if "endpoint" in cur:
if i == len(nodes) - 1:
return cur["endpoint"], None
return cur["endpoint"], nodes[i+1:] # arguments for your path
if node not in cur:
return None, None
cur = cur[node] # this will go as deep as you want until "endpoint" or incorrect node
But you could also do it without splitting: save then as sorted list of all possible paths and do bisect to find one that looks like yours. All that in not in a path - throw away or use as parameters.