优化 web service 接口

目前 API 的设计的问题就是迫使客户端在任务标识返回后去构造 URIs。这对于服务器是十分简单的,但是间接地迫使客户端知道这些 URIs 是如何构造的,这将会阻碍我们以后变更这些 URIs。

不直接返回任务的 ids,我们直接返回控制这些任务的完整的 URI,以便客户端可以随时使用这些 URIs。为此,我们可以写一个小的辅助函数生成一个 “公共” 版本任务发送到客户端:

  1. from flask import url_for
  2.  
  3. def make_public_task(task):
  4. new_task = {}
  5. for field in task:
  6. if field == 'id':
  7. new_task['uri'] = url_for('get_task', task_id=task['id'], _external=True)
  8. else:
  9. new_task[field] = task[field]
  10. return new_task

这里所有做的事情就是从我们数据库中取出任务并且创建一个新的任务,这个任务的 id 字段被替换成通过 Flask 的 url_for 生成的 uri 字段。

当我们返回所有的任务列表的时候,在发送到客户端之前通过这个函数进行处理:

  1. @app.route('/todo/api/v1.0/tasks', methods=['GET'])
    def get_tasks():
    return jsonify({'tasks': map(make_public_task, tasks)})

这里就是客户端获取任务列表的时候得到的数据:

  1. $ curl -i http://localhost:5000/todo/api/v1.0/tasks
  2. HTTP/1.0 200 OK
  3. Content-Type: application/json
  4. Content-Length: 406
  5. Server: Werkzeug/0.8.3 Python/2.7.3
  6. Date: Mon, 20 May 2013 18:16:28 GMT
  7.  
  8. {
  9. "tasks": [
  10. {
  11. "title": "Buy groceries",
  12. "done": false,
  13. "description": "Milk, Cheese, Pizza, Fruit, Tylenol",
  14. "uri": "http://localhost:5000/todo/api/v1.0/tasks/1"
  15. },
  16. {
  17. "title": "Learn Python",
  18. "done": false,
  19. "description": "Need to find a good Python tutorial on the web",
  20. "uri": "http://localhost:5000/todo/api/v1.0/tasks/2"
  21. }
  22. ]
  23. }

我们将会把上述的方式应用到其它所有的函数上以确保客户端一直看到 URIs 而不是 ids。