Python Falcon 简明教程

Python Falcon - Hooks

钩子是在响应客户端请求时在资源类中的特定响应程序方法被调用时自动执行的用户定义函数。Falcon 支持 beforeafter 钩子。

作为钩子使用的函数被定义为具有请求、响应和资源类的参数,除了可能需要的任何可选参数。

def hookfunction(req, resp, resource):
   . . . . .
   . . . . .

此类函数通过应用以下装饰器之一附加到单个响应程序或整个资源类 -

  1. @falcon.before(hookfunction)

  2. @falcon.after(hookfunction)

将 before 钩子应用于 on_post() 响应程序 -

@falcon.before(hookfunction)
def on_post(self, req, resp):
   . . .
   . . .

应用一个 after 钩子 -

@falcon.after(hookfunction)
def on_get(self, req, resp):
   . . .
   . . .

要装饰整个资源类,请在类声明上方使用装饰器 -

@falcon.after(hookfunction)
class SomeResource:
 def on_get(self, req, resp):
   . . .
   . . .
   def on_post(self, req, resp):
   . . .
   . . .

在以下示例中,我们有 StudentResource 类,其中已定义 on_get()on_post() 响应程序。当 POST 请求发送一些数据并且使用它创建的新 dict 对象被添加到 Students 列表中时,会调用 on_post() 响应程序。

接收到的数据需要在处理之前进行验证。为此,已定义以下函数。它检查 percent 参数的值是否在 0 和 100 之间。仅当数据通过此条件时,才将其传递给响应程序。

def checkinput(req, resp, resource,params):
   student = json.load(req.bounded_stream)
   if "name" not in student:
      raise falcon.HTTPBadRequest(
         title="Bad request", description="Bad input, name must be provided."
      )

   per=int(student['percent'])
   if per<0 or per>100:
      raise falcon.HTTPBadRequest(
         title="Bad request", description="Bad input, invalid percentage"
      )
      req.context.data = student

此函数作为 StudentResource 类的 on_post() 响应程序上的钩子应用。

import falcon
import json
from waitress import serve
students = [
   {"id": 1, "name": "Ravi", "percent": 75.50},
   {"id": 2, "name": "Mona", "percent": 80.00},
   {"id": 3, "name": "Mathews", "percent": 65.25},
]
class StudentResource:
   def on_get(self, req, resp):
      resp.text = json.dumps(students)
      resp.status = falcon.HTTP_OK
      resp.content_type = falcon.MEDIA_JSON
   @falcon.before(checkinput)
   def on_post(self, req, resp):
      student = json.load(req.context.data)
      students.append(student)
      resp.text = "Student added successfully."
      resp.status = falcon.HTTP_OK
      resp.content_type = falcon.MEDIA_TEXT

   def on_get_student(self, req, resp, id):
      resp.text = json.dumps(students[id-1])
      resp.status = falcon.HTTP_OK
      resp.content_type = falcon.MEDIA_JSON
app = falcon.App()
app.add_route("/students", StudentResource())
if __name__ == '__main__':
   serve(app, host='0.0.0.0', port=8000)

让我们运行 Waitress 服务器并发起 POST 请求。

http POST localhost:8000/students id=4 percent=50
HTTP/1.1 400 Bad Request
Content-Length: 76
Content-Type: application/json
Date: Tue, 26 Apr 2022 14:49:07 GMT
Server: waitress
Vary: Accept {
   "description": "Bad input, name must be provided.",
   "title": "Bad request"
}

由于数据不包含 name 参数的值,因此引发异常。

在下面显示的另一个 POST 请求中,percent 参数的值未满足所需条件,因此会引发异常。

http POST localhost:8000/students id=4 name="aaa" percent=500
HTTP/1.1 400 Bad Request
Content-Length: 72
Content-Type: application/json
Date: Tue, 26 Apr 2022 15:01:20 GMT
Server: waitress
Vary: Accept {
   "description": "Bad input, invalid percentage",
   "title": "Bad request"
}