Package: restfy
restfyA small rest framework.InstalationpipinstallrestfyUsageMinimal usageA basic Restfy application is showed below.fromrestfyimportApplication,Server,Request,Responseapp=Application()@app.post('/')asyncdefhandler(request:Request)->Response:ret=request.datareturnResponse(ret)server=Server(app)server.run()This code fragment sets up a basic web application using your asynchronous web application framework.
It defines a route for a POST request at the root URL and returns a response with the request data.
The server is then started to handle incoming requests.In this code, therestfymodule is imported, and the necessary classesApplication,Server,Request, andResponseare imported from it.An instance of the Application class is created and assigned to the variable app. This class represents the restfy application framework itself.The@app.post('/')decorator is used to define a route for the HTTP POST method at the root URL ("/") of the application. When a POST request is made to this URL, the handler function will be called.The handler function is an asynchronous function that takes a request parameter of type Request. It creates a Response object with a data and returns it.An instance of the Server class is created, passing the app object as a parameter to associate the server with the application.Finally, the run() method is called on the server object, which starts the server and makes it listen for incoming requests.The routes also can be added by using.add_route(path, handler, method)application method.fromrestfyimportApplication,Server,Response,Requestasyncdefhandler(request:Request)->Response:data=f'{request.method}:{request.url}'returnResponse(data)app=Application()app.add_route('/',handler,method='GET')...Adding route by router decoratorFor applications with a great number of routes is necessary a better modules organization.
To help in this process, Restfy has a class to manager the routes,Routerclass.The Router class is similar to Application class to register routes.
Then, a cluster of routes can be created as necessary.# servers.pyfromrestfyimportRouterrouter=Router()@router.get('')asyncdefget_servers_list():ret=[]returnret@router.post('')asyncdefcreate_new_server():...return{}...# application.pyfromrestfyimportApplicationfrom.serversimportrouterasserversapp=Application()app.register_router('/servers',servers)...As we can see, the routes are defined on other file by aRouteinstance.
The app object registry this through.register_router(path, router).With this approach, several routes can be registered with different routes.Receiving data and args from request objectThe information can be passed by path variables, query_string parameters, request body and request headers.Below, is showed a condensed example how to that information are distributed insideRequestobject....@router.put('/servers/{key}')asyncdefhandler(request:Request,key:int)->Response:headers:dict=request.headers# request headers...# Body HTTP requestbody:bytes=request.body# The raw binary request body.dada:dict|list|None=request.data# A deserialized body....# The path variablesargs:dict=request.path_args# Complete variablesvars:dict=request.vars# Variables not explicit used by function...# The query_string parametersquery:dict=request.query_args# Completeparams:dict=request.params# Incomplete...returnResponse([])...If you need a more explict variable declaration, you can declare it as a function parameter.
Restfy will identify this value on Request path_args or query_args and set it.
The query_args and path_args will not be affected by the Request params and vars will be.
That attributes hold the values are not used as function parameter.
Then, in the fragment above, the path_args will have the key value and the vars will be empty because key value is setted as a funcion parameter.The Request try parse the body bytes to data based on its content type.
For example, if the request content type is aapplication/json, the data will set by json format.Returning dataIf we are creating a server, it a fact we want return some data.
It can be done by a Response instance object passing data attribute and optionality, the status and headers.
In addition, we can just return a value that Restfy will try to create a Response object instance based on value type.The return also can be a tuple with value and the status code.That shortcuts are very useful for most common situations by when the data are a file body, we need create a Response instance with the correct content type.In the future Restfy release, probably will bring exclusive Response objects but will not cover all cases.fromrestfy.httpimportResponse,Request...asyncdefhandler(request:Request,pk:int)->Response:data=f'<b>restfy: pk{pk}</b>'headers={'Content-Type':'text/html'}returnResponse(data,status=400,headers=headers)...asyncdefhandler_other(request:Request,pk:int)->Response:data=f'<b>restfy: pk{pk}</b>'returnResponse(data,status=400,content_type='text/html')...MiddlewaresRestfy uses middleware creating a class with .exec() method.
The parameter request must be passed into exec method.The Application has the method .register_middleware() to register middlewares.
The register order is the same order of execution.fromrestfyimportApplication,MiddlewareclassDefaultMiddleware(Middleware):asyncdefexec(self,request):# Do something with request object...response=awaitself.forward(request)...# Do something with response objectreturnresponseapp=Application()app.register_middleware(DefaultMiddleware)HTTP client requestsWith http module, you can do asynchronous requests to other services.
The most simple request can be seen below.fromrestfyimporthttp...res=awaithttp.get('https://someserver.api/endpoint')print(res.status)# 200In addition to the get function, others functions are available like
post(), put(), delete() and patch().
If other request method are necessary, we can use request() function passing method param.
The next example shows a more complex example.fromrestfyimporthttpdata={'name':'Nick','surname':'Lauda'}headers={'Content-Type':'application/json'}url='https://someserver.api/endpoint'res=awaithttp.post(url=url,data=data,headers=headers)print(res.status)# 200