多年来那些年,API服务器端

  作为三个新手程序员,刚上班不久就被BOSS,拖去开发restful api
与APP交互。拿到手一脸蒙圈,然后看了某度的别人所设计的,感觉便是重复很多,设计很多。然后FQ出去看了旷日持久,终于把这一个K完了。然后写下这一个博文,让自身总计一下和著录。

  作为多少个新手程序员,刚上班不久就被BOSS,拖去开发restful api
与APP交互。得到手一脸蒙圈,然后看了某度的人家所陈设的,感觉便是再次很多,设计很多。然后FQ出去看了遥遥无期,终于把这么些K完了。然后写下那些博文,让祥和总括一下和记录。

近日这么些年,REST已经济体制改善为web
services和APIs的正规化架构,很多APP的架构基本上是行使RESTful的花样了。

使用python的Flask完结3个RESTful API服务器端[翻译]

方今这个年,REST已经变成web
services和APIs的正式架构,很多APP的框架结构基本上是运用RESTful的款式了。

 

正文将会利用python的Flask框架轻松实现八个RESTful的劳务。

 

REST的两个特征:

 

Client-Server:服务器端与客户端分离。

Stateless(无状态):每一遍客户端请求必需包罗完整的新闻,换句话说,每趟呼吁都是单独的。

Cacheable(可缓存):服务器端必需内定哪些请求是足以缓存的。

Layered
System(分层结构):服务器端与客户端通讯必需标准化,服务器的改观并不会潜移默化客户端。

Uniform Interface(统一接口):客户端与劳动器端的报纸发表格局必需是联合的。

Code on
demand(按需实施代码?):服务器端能够在前后文中执行代码只怕脚本?

Servers can provide executable code or scripts for clients to execute in
their context. This constraint is the only one that is
optional.(没看明白)

 

RESTful web service的样子

 

REST架构就是为着HTTP协议布置的。RESTful web
services的骨干概念是管理财富。财富是由URAV4Is来表示,客户端应用HTTP个中的’POST,
OPTIONS, GET, PUT, DELETE’等办法发送请求到服务器,改变相应的能源境况。

 

HTTP请求方法一般也非常适当去描述操作财富的动作:

 

HTTP方法
动作
例子

GET
获取财富新闻

 

(检索订单清单)

 

GET
获取财富消息

 

(检索订单 #123)

 

POST
创设一个次的能源

 

(使用带多少的请求,创设一个新的订单)

 

PUT
更新多少个财富

 

(使用带多少的请求,更新#123订单)

 

DELETE
删除二个能源

 

除去订单#123

 

REST请求并不必要特定的数码格式,经常使用JSON作为请求体,可能U路虎极光L的询问参数的一部份。

 

统一筹划一个概括的web service

 

下边包车型地铁天职将会演习设计以REST准则为教导,通过不一致的请求方法操作财富,标识能源的事例。

 

我们将写1个To Do List 应用,并且安排三个web
service。第叁步,规划2个根U卡宴L,例如:

 

 

 

下边的U宝马X5L包罗了应用程序的名目、API版本,那是特别可行的,既提供了命名空间的细分,同时又与此外系统区分开来。版本号在升级新特征时那多少个有用,当一个新功用特色增添在新本子上边时,并不影响旧版本。

 

第2步,规划能源的UCR-VL,这一个例子13分简短,唯有职务清单。

 

统一筹划如下:

 

HTTP方法
URI
动作

GET
检索职分清单

GET
] 检索一个任务

POST
成立三个新任务

PUT
]
更新三个已存在的天职

DELETE
] 删除三个职分

小编们定义职责清单有以下字段:

 

id:唯一标识。整型。

title:简短的天职描述。字符串型。

description:完整的职分描述。文本型。

done:职责实现意况。布尔值型。

上述基本形成了设计部份,接下去大家将会促成它!

 

 简单明白Flask框架

 

Flask好简单,可是又很强大的Python web 框架。那里有一多级教程Flask
Mega-Tutorial series。(注:Django\Tornado\web.py感觉好多框:()

 

在大家深刻落实web service从前,让大家来不难地看3个Flask web
应用的布局示例。

 

此地都是在Unix-like(Linux,Mac OS
X)操作系统上边包车型地铁以身作则,不过任何系统也足以跑,例如windows下的Cygwin。大概命令有个别分裂吧。(注:忽略Windows吧。)

 

先使用virtualenv安装八个Flask的虚拟环境。如若没有设置virtualenv,开发python必备,最好去下载安装。

 

 

$ mkdir todo-api

$ cd todo-api

$ virtualenv flask

New python executable in flask/bin/python

Installing setuptools……………………….done.

Installing pip……………….done.

$ flask/bin/pip install flask

 

 那样做好了七个Flask的支出环境,开首创办二个总结的web应用,在当前目录里面创设三个app.py文件:

 

 

#!flask/bin/python

from flask import Flask

 

app = Flask(__name__)

 

@app.route(‘/’)

def index():

    return “Hello, World!”

 

if __name__ == ‘__main__’:

    app.run(debug=True)

 

去执行app.py:

 

$ chmod a+x app.py

$ ./app.py

 * Running on

 * Restarting with reloader

今日得以打开浏览器,输入

 

可以吗,十三分简短吗。我们起始更换来RESTful service!

 

使用Python 和 Flask实现RESTful services

 

采纳Flask建立web services一流简单。

 

本来,也有成百上千Flask extensions能够扶持建立RESTful
services,可是这么些例实在太简单了,不须求选择别的扩展。

 

以此web
service提供增添,删除、修改职务清单,所以大家须要将职分清单存款和储蓄起来。最简便的做法便是采纳微型的数据库,可是数据库并不是本文涉及太多的。能够参见原作小编的欧洲经济共同体教程。Flask
Mega-Tutorial series

 

在这边例子大家将任务清单存储在内部存款和储蓄器中,这样只可以运维在单进度和单线程中,那样是不合乎当作生产服务器的,若非就少不了使用数据库了。

多年来那些年,API服务器端。 

当今大家准备实现率先个web service的入口点:

 

 

#!flask/bin/python

from flask import Flask, jsonify

 

app = Flask(__name__)

 

tasks = [

    {

        ‘id’: 1,

        ‘title’: u’Buy groceries’,

        ‘description’: u’Milk, Cheese, Pizza, Fruit, Tylenol’, 

        ‘done’: False

    },

    {

        ‘id’: 2,

        ‘title’: u’Learn Python’,

        ‘description’: u’Need to find a good Python tutorial on the
web’, 

        ‘done’: False

    }

]

 

@app.route(‘/todo/api/v1.0/tasks’, methods=[‘GET’])

def get_tasks():

    return jsonify({‘tasks’: tasks})

 

if __name__ == ‘__main__’:

    app.run(debug=True)

 

正如您所见,并不曾改动太多代码。大家将任务清单存款和储蓄在list内(内部存款和储蓄器),list存放四个卓殊简单的数组字典。每一种实体便是大家地点定义的字段。

 

而 index 入口点有二个get_tasks函数与/todo/api/v1.0/tasks
URI关联,只接受http的GET方法。

 

这么些响应并非一般文本,是JSON格式的数额,是经过Flask框架的
jsonify模块格式化过的多少。

 

应用浏览器去测试web
service并不是1个好的格局,因为要成立不一致类弄的HTTP请求,事实上,大家将选择curl命令行。要是没有设置curl,快点去安装叁个。

 

像刚刚同样运营app.py。

 

开辟三个极端运营以下命令:

 

 

$ curl -i

HTTP/1.0 200 OK

Content-Type: application/json

Content-Length: 294

Server: Werkzeug/0.8.3 Python/2.7.3

Date: Mon, 20 May 2013 04:53:53 GMT

 

{

  “tasks”: [

    {

      “description”: “Milk, Cheese, Pizza, Fruit, Tylenol”,

      “done”: false,

      “id”: 1,

      “title”: “Buy groceries”

    },

    {

      “description”: “Need to find a good Python tutorial on the web”,

      “done”: false,

      “id”: 2,

      “title”: “Learn Python”

    }

  ]

}

 

如此那般就调用了三个RESTful service方法!

 

今昔,大家写第二个版本的GET方法取得一定的天职。获取单个职分:

 

 

from flask import abort

 

@app.route(‘/todo/api/v1.0/tasks/<int:task_id>’,
methods=[‘GET’])

def get_task(task_id):

    task = filter(lambda t: t[‘id’] == task_id, tasks)

    if len(task) == 0:

        abort(404)

    return jsonify({‘task’: task[0]})

 

 第二个函数稍稍复杂了部分。任务的id包括在U奥迪Q5L内,Flask将task_id参数字传送入了函数内。

 

因此参数,检索tasks数组。如若参数字传送过来的id不存在于数组内,我们要求回到错误代码404,依据HTTP的规定,404意味是”Resource
Not Found”,能源未找到。

 

假设找到职务在内存数组内,大家因此jsonify模块将字典打包成JSON格式,并发送响应到客户端上。就像是处理三个实体字典一样。

 

试试使用curl调用:

 

 

$ curl -i

HTTP/1.0 200 OK

Content-Type: application/json

Content-Length: 151

Server: Werkzeug/0.8.3 Python/2.7.3

Date: Mon, 20 May 2013 05:21:50 GMT

 

{

  “task”: {

    “description”: “Need to find a good Python tutorial on the web”,

    “done”: false,

    “id”: 2,

    “title”: “Learn Python”

  }

}

$ curl -i

HTTP/1.0 404 NOT FOUND

Content-Type: text/html

Content-Length: 238

Server: Werkzeug/0.8.3 Python/2.7.3

Date: Mon, 20 May 2013 05:21:52 GMT

 

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 3.2 Final//EN”>

<title>404 Not Found</title>

<h1>Not Found</h1>

<p>The requested URL was not found on the
server.</p><p>If you     entered the URL manually please
check your spelling and try again.</p>

 

当我们恳请#2
id的能源时,能够博得,不过当我们恳请#3的能源时重回了404荒唐。并且重返了一段奇怪的HTML错误,而不是大家期待的JSON,这是因为Flask发生了暗中同意的404响应。客户端须求吸收的都是JSON的响应,由此我们供给改正404错误处理:

 

from flask import make_response

 

@app.errorhandler(404)

def not_found(error):

    return make_response(jsonify({‘error’: ‘Not found’}), 404)

诸如此类大家就拿走了自个儿的API错误响应:

 

 

$ curl -i

HTTP/1.0 404 NOT FOUND

Content-Type: application/json

Content-Length: 26

Server: Werkzeug/0.8.3 Python/2.7.3

Date: Mon, 20 May 2013 05:36:54 GMT

 

{

  “error”: “Not found”

}

 

接下去我们落到实处 POST 方法,插入1个新的任务到数组中:

 

 

from flask import request

 

@app.route(‘/todo/api/v1.0/tasks’, methods=[‘POST’])

def create_task():

    if not request.json or not ‘title’ in request.json:

        abort(400)

    task = {

        ‘id’: tasks[-1][‘id’] + 1,

        ‘title’: request.json[‘title’],

        ‘description’: request.json.get(‘description’, “”),

        ‘done’: False

    }

    tasks.append(task)

    return jsonify({‘task’: task}), 201

 

 request.json里面富含呼吁数据,倘诺不是JSON或许个中没有包蕴title字段,将会回来400的错误代码。

 

当成立一个新的任务字典,使用最终三个职责id数值加1作为新的职责id(最简便的章程产生一个唯一字段)。那里允许不带description字段,暗许将done字段值为False。

 

将新职责叠加到tasks数组里面,并且重返客户端201状态码和正好添加的天职内容。HTTP定义了201状态码为“Created”。

 

测试上边的新效用:

 

 

$ curl -i -H “Content-Type: application/json” -X POST -d ‘{“title”:”Read
a book”}’

HTTP/1.0 201 Created

Content-Type: application/json

Content-Length: 104

Server: Werkzeug/0.8.3 Python/2.7.3

Date: Mon, 20 May 2013 05:56:21 GMT

 

{

  “task”: {

    “description”: “”,

    “done”: false,

    “id”: 3,

    “title”: “Read a book”

  }

}

 

只顾:假设利用原生版本的curl命令行提醒符,上边的命令会正确履行。假使是在Windows下行使Cygwin
bash版本的curl,必要将body部份添加双引号:

 

curl -i -H “Content-Type: application/json” -X POST -d
“{“””title”””:”””Read a book”””}”

基本上在Windows中要求选择双引号包罗body部份在内,而且亟需多个双引号转义类别。

 

完了地点的作业,就足以见到更新之后的list数组内容:

 

$ curl -i

HTTP/1.0 200 OK

Content-Type: application/json

Content-Length: 423

Server: Werkzeug/0.8.3 Python/2.7.3

Date: Mon, 20 May 2013 05:57:44 GMT

 

{

  “tasks”: [

    {

      “description”: “Milk, Cheese, Pizza, Fruit, Tylenol”,

      “done”: false,

      “id”: 1,

      “title”: “Buy groceries”

    },

    {

      “description”: “Need to find a good Python tutorial on the web”,

      “done”: false,

      “id”: 2,

      “title”: “Learn Python”

    },

    {

      “description”: “”,

      “done”: false,

      “id”: 3,

      “title”: “Read a book”

    }

  ]

}

 

剩余的几个函数如下:

 

 

@app.route(‘/todo/api/v1.0/tasks/<int:task_id>’,
methods=[‘PUT’])

def update_task(task_id):

    task = filter(lambda t: t[‘id’] == task_id, tasks)

    if len(task) == 0:

        abort(404)

    if not request.json:

        abort(400)

    if ‘title’ in request.json and type(request.json[‘title’]) !=
unicode:

        abort(400)

    if ‘description’ in request.json and
type(request.json[‘description’]) is not unicode:

        abort(400)

    if ‘done’ in request.json and type(request.json[‘done’]) is not
bool:

        abort(400)

    task[0][‘title’] = request.json.get(‘title’,
task[0][‘title’])

    task[0][‘description’] = request.json.get(‘description’,
task[0][‘description’])

    task[0][‘done’] = request.json.get(‘done’, task[0][‘done’])

    return jsonify({‘task’: task[0]})

 

@app.route(‘/todo/api/v1.0/tasks/<int:task_id>’,
methods=[‘DELETE’])

def delete_task(task_id):

    task = filter(lambda t: t[‘id’] == task_id, tasks)

    if len(task) == 0:

        abort(404)

    tasks.remove(task[0])

    return jsonify({‘result’: True})

 

delete_task函数没什么太尤其的。update_task函数必要检讨所输入的参数,幸免发生错误的bug。确定保障是预料的JSON格式写入数据库里面。

 

测试将任务#2的done字段变更为done状态:

 

 

$ curl -i -H “Content-Type: application/json” -X PUT -d ‘{“done”:true}’

HTTP/1.0 200 OK

Content-Type: application/json

Content-Length: 170

Server: Werkzeug/0.8.3 Python/2.7.3

Date: Mon, 20 May 2013 07:10:16 GMT

 

{

  “task”: [

    {

      “description”: “Need to find a good Python tutorial on the web”,

      “done”: true,

      “id”: 2,

      “title”: “Learn Python”

    }

  ]

}

 

改进Web Service接口

 

当下大家还有三个难题,客户端有恐怕供给从再次来到的JSON中重复组织UCR-VI,如果以往投入新的天性时,大概必要修改客户端。(例如新增版本。)

 

咱俩得以回到整个U陆风X8I的途径给客户端,而不是任务的id。为了那些功能,创制二个小函数生成2个“public”版本的职责U本田CR-VI再次回到:

 

 

from flask import url_for

 

def make_public_task(task):

    new_task = {}

    for field in task:

        if field == ‘id’:

            new_task[‘uri’] = url_for(‘get_task’,
task_id=task[‘id’], _external=True)

        else:

            new_task[field] = task[field]

    return new_task

 

通过Flask的url_for模块,获取职责时,将职务中的id字段替换来uri字段,并且把值改为uri值。

 

当大家回到包蕴职责的list时,通过这一个函数处理后,重临完整的uri给客户端:

 

@app.route(‘/todo/api/v1.0/tasks’, methods=[‘GET’])

def get_tasks():

    return jsonify({‘tasks’: map(make_public_task, tasks)})

于今看到的追寻结果:

 

 

$ curl -i

HTTP/1.0 200 OK

Content-Type: application/json

Content-Length: 406

Server: Werkzeug/0.8.3 Python/2.7.3

Date: Mon, 20 May 2013 18:16:28 GMT

 

{

  “tasks”: [

    {

      “title”: “Buy groceries”,

      “done”: false,

      “description”: “Milk, Cheese, Pizza, Fruit, Tylenol”,

      “uri”: “”

    },

    {

      “title”: “Learn Python”,

      “done”: false,

      “description”: “Need to find a good Python tutorial on the web”,

      “uri”: “”

    }

  ]

}

 

那种格局制止了与别的效用的合营,获得的是完全uri而不是几个id。

 

RESTful web service的平安评释

 

大家曾经成功了一切作用,不过大家还有三个题材。web
service任何人都得以访问的,那不是三个好主意。

 

日前service是怀有客户端都能够两次三番的,假使有旁人理解了那么些API就足以写个客户端随意改动数据了。
大多数学科没有与安全相关的剧情,那是个要命严重的标题。

 

最简易的章程是在web
service中,只同意用户名和密码验证通过的客户端连接。在一个平常的web应用中,应该有记名表单提交去申明,同时服务器会创立多个对话进程去开始展览报纸发表。这几个会话进程id会被积存在客户端的cookie里面。不过那样就违返了大家REST中无状态的平整,由此,大家供给客户端每一回都将她们的辨证音讯发送到服务器。

 

 为此大家有二种情势表单认证格局去做,分别是 Basic 和 Digest。

 

此间有有个小Flask extension能够轻松做到。首先要求安装 Flask-HTTPAuth :

 

$ flask/bin/pip install flask-httpauth

假使web service只有用户 ok 和密码为 python
的用户接入。下边就安装了3个Basic HTTP认证:

 

 

from flask.ext.httpauth import HTTPBasicAuth

auth = HTTPBasicAuth()

 

@auth.get_password

def get_password(username):

    if username == ‘ok’:

        return ‘python’

    return None

 

@auth.error_handler

def unauthorized():

    return make_response(jsonify({‘error’: ‘Unauthorized access’}),
401)

 

get_password函数是三个回调函数,获取多个已知用户的密码。在纷纭的连串中,函数是供给到数据库中反省的,然而那里只是二个小示例。

 

当产生认证错误之后,error_handler回调函数会发送错误的代码给客户端。那里我们自定义二个错误代码401,再次回到JSON数据,而不是HTML。

 

将@auth.login_required装饰器添加到必要验证的函数方面:

 

@app.route(‘/todo/api/v1.0/tasks’, methods=[‘GET’])

@auth.login_required

def get_tasks():

    return jsonify({‘tasks’: tasks})

明日,试试使用curl调用那么些函数:

 

 

$ curl -i

HTTP/1.0 401 UNAUTHORIZED

div>Content-Type: application/json

  首先大家要做的是PHP
db封装,这么些要包蕴最基本的CRUD。能够把常量便是布局数据库的写在头顶,或是写在其它二个页面,导入那么些cofin。

  首先大家要做的是PHP
db封装,那些要包涵最基本的CRUD。能够把常量正是计划数据库的写在头顶,或是写在其它二个页面,导入这一个cofin。

 

  然后本身要介绍restful api 的规划有成都百货上千种,

  然后自身要介绍restful api 的宏图有好种种,

正文将会利用python的Flask框架轻松实现三个RESTful的劳动。

  大家利用那种情势:

  大家运用那种办法:

 

  get:select  POST:inseit into  put:update  delete:delete

  get:select  POST:inseit into  put:update  delete:delete

REST的多少个特色:

  每三个method对应不一样的方法,那样方便而且便于区分。

  每一个method对应分歧的主意,那样方便而且便于区分。

 

  例如1个用户表:

  例如贰个用户表:

Client-Server:服务器端与客户端分离。

  GET:/app/    列出装有用户

  GET:/app/    列出具有用户

Stateless(无状态):每一回客户端请求必需包罗完整的新闻,换句话说,每壹回呼吁都以独立的。

  GET: /app/1   列出ID为1的用户

  GET: /app/1   列出ID为1的用户

Cacheable(可缓存):服务器端必需钦定哪些请求是能够缓存的。

  POST:/app/    扩展用户

  POST:/app/    增添用户

Layered
System(分层结构):服务器端与客户端通信必需标准化,服务器的更改并不会潜移默化客户端。

  PUT:/app/id
   修改钦赐ID为1的用户(put有本个性,他只会修改一次,不管你怎么刷新页面)

  PUT:/app/id
   修改钦定ID为1的用户(put有个特色,他只会修改壹遍,不管您怎么刷新页面)

Uniform Interface(统一接口):客户端与服务器端的通信格局必需是联合的。

  delete:/app/id   删除内定ID

  delete:/app/id   删除钦点ID

Code on
demand(按需实践代码?):服务器端可以在内外文中执行代码可能脚本?

 

 

Servers can provide executable code or scripts for clients to execute in
their context. This constraint is the only one that is
optional.(没看精晓)

  [这边要选择二个工具
chorm的postman,这几个工具得以效仿从APP发送不一致的method方法,发送的格式因为都以JSON,也能够在上头修改,这些是别的软件,不会操作本人百度时而,对了,下载下来假使发现装不上来,能够把内部特别文件的后缀名,改成.rar.然后在解压到当前的文本夹,把_metadata前面的_去掉,然后在用谷歌就能够动用了]

  [那里要运用三个工具
chorm的postman,这么些工具得以效仿从APP发送不相同的method方法,发送的格式因为都以JSON,也能够在上边修改,那几个是其余软件,不会操作本人百度时而,对了,下载下来若是发现装不上来,能够把个中尤其文件的后缀名,改成.rar.然后在解压到当前的文本夹,把_metadata前面的_去掉,然后在用谷歌(Google)就能够使用了]

 

 

 

RESTful web service的样子

  而自小编不利用put和delect
,不是嫌麻烦,是那八个没怎么用过,有点抗拒。笔者是如此写的

  而自小编不应用put和delect
,不是嫌麻烦,是那三个没怎么用过,有点抗拒。作者是那般写的

 

  都用POST或是分开get和Post,只要传入的json中有”第3个“[way]=add或select,把措施传进来,用swtich那一个点子判断。

  都用POST或是分开get和Post,只要传入的json中有”第二个“[way]=add或select,把办法传进来,用swtich这一个艺术判断。

REST架构正是为着HTTP协议安插的。RESTful web
services的主导概念是管制财富。财富是由U索罗德Is来表示,客户端采纳HTTP个中的’POST,
OPTIONS, GET, PUT, DELETE’等办法发送请求到服务器,改变相应的能源气象。

    1.POST措施接收不到尾部不是header(”content-type:application/json“),为啥要设置这么些底部,别问我,作者也不清楚。那样自个儿不可能用$_post[‘’]本条点子接收了,$_get[”]能够行使,大家能够用这几个,json_decode(file_get_contents(“php://input”),true);本身查一出手册,就知道那是什么了。

    1.POST措施接收不到底部不是header(”content-type:application/json“),为何要安装这几个尾部,别问笔者,我也不亮堂。那样笔者不可能用$_post[‘’]那个主意接收了,$_get[”]能够动用,大家得以用那个,json_decode(file_get_contents(“php://input”),true);本人查一入手册,就知道那是何等了。

 

    2.我们怎么知道对方交付的是哪些的method,能够用这几个。$_SERVER[‘REQUEST_METHOD’]

    2.我们怎么知道对方付出的是如何的method,能够用这些。$_SERVER[‘REQUEST_METHOD’]

HTTP请求方法一般也要命适中去描述操作能源的动作:

    3.为啥要刨除way。呵呵你传进来的这些分析后的数组,你不要里面包车型大巴参数了呢?难道
你的数据Curry也有[way]=’add’;那些方法,那就当自家没说,我们能够用这些函数unset();把这一个[way]这个K掉

    3.为啥要去除way。呵呵你传进来的那么些分析后的数组,你不要里面包车型大巴参数了吗?难道
你的数据Curry也有[way]=’add’;这么些主意,这就当自家没说,大家得以用这些函数unset();把那几个[way]这个K掉

 

  

  

HTTP方法
动作
例子

  当大家实践了1遍那一个DB流程回来,大家要发送json数据回去和HTTP
code回去。

  当大家实施了1次那一个DB流程回来,大家要发送json数据回去和HTTP
code回去。

GET
获取能源新闻

  查询是要回到的,别的的回来贰个标记就基本上了 。

  查询是要赶回的,别的的回来三个标示就差不离了 。

  发送回去的json:

  发送回去的json:

 

  {code:200,data:”}本人把要回去的数量拼进去,不回去数据的{code:200,msg:…};那一个都可以自定义再次回到的,当然要写成2个文书档案

  {code:200,data:”}本身把要再次回到的数目拼进去,不回来数据的{code:200,msg:…};那个都足以自定义重返的,当然要写成一个文书档案

(检索订单清单)

  

  

 

  发送回去的httpd code:

  发送回去的httpd code:

GET
获取能源消息

  网上要十一分多介绍code的状态码,小编想说城里的人真会玩,笔者不懂那么些是状态码吗?作者只是想怎么发回去罢了,看到最终都没察觉。作者也是服了。

  网上要卓殊多介绍code的状态码,笔者想说城里的人真会玩,笔者不懂那个是状态码吗?笔者只是想怎么发回去罢了,看到最后都没觉察。小编也是服了。

  http_response_code(200);

  http_response_code(200);

 

  不懂有没有同桌也会跟本人同一,说这几个函数没概念,这些时候你要本人定义贰个函数了

  不懂有没有同桌也会跟自个儿同一,说那个函数没概念,这一个时候你要和谐定义一个函数了

(检索订单 #123)

  www.30064.com 1

  www.30064.com 2

 

  不发个图感觉都不到底博客。

  不发个图感觉都不到底博客。

POST
创造叁个次的财富

  

  

  添加方法里面,笔者不是何许都听人家丢什么,大家就要怎么的。

  添加方法里面,作者不是如何都听外人丢什么,大家就要哪些的。

 

  大家要把自个儿的字段表封装,正是把这几个想要的 $data[‘oid’] =
给对方的字段,json解封下来所对应的字段,大家把本人想要的取下来,然后才放进去。那些是有须求的,当然我们也要问对面想要什么,作者也发特定的回给他。

  我们要把自个儿的字段表封装,正是把那几个想要的 $data[‘oid’] =
给对方的字段,json解封下来所对应的字段,大家把自身想要的取下来,然后才放进去。那一个是有必不可少的,当然我们也要问对面想要什么,笔者也发特定的回给他。

(使用带多少的央浼,创造多个新的订单)

  到此处restful
api设计实现了。没有怎么安顿方面包车型地铁学问。有怎样的大神大家一起沟通,毕竟‘新手上路’;

  到那边restful
api设计达成了。没有怎么安排方面包车型地铁文化。有啥的大神咱们一起调换,毕竟‘新手上路’;

 

                                                                                      —-j.m

                                                                                      —-j.m

PUT
更新2个能源

 

 

 

(使用带多少的伸手,更新#123订单)

 

DELETE
删除多个财富

 

去除订单#123

 

REST请求并不供给特定的数目格式,常常使用JSON作为请求体,恐怕UQashqaiL的询问参数的一部份。

 

计划二个简便的web service

 

下边的天职将会演练设计以REST准则为引导,通过分裂的伸手方法操作财富,标识能源的事例。

 

大家将写三个To Do List 应用,并且布署1个web
service。第③步,规划贰个根UCR-VL,例如:

 

 

 

下面的UEvoqueL包蕴了应用程序的称号、API版本,那是可怜卓有功效的,既提供了命名空间的剪切,同时又与此外系统区分开来。版本号在提高新特点时13分有用,当多个新效率特色增添在新本子下边时,并不影响旧版本。

 

第1步,规划财富的U奥迪Q5L,那些例子十分简短,只有任务清单。

 

统一筹划如下:

 

HTTP方法
URI
动作

GET
检索任务清单

GET
] 检索二个职分

POST
创制四个新职分

PUT
]
更新一个已存在的职务

DELETE
] 删除八个职分

大家定义任务清单有以下字段:

 

id:唯一标识。整型。

title:简短的天职描述。字符串型。

description:完整的职务描述。文本型。

done:职分到位景况。布尔值型。

上述基本形成了设计部份,接下去我们将会落成它!

 

 简单通晓Flask框架

 

Flask好简单,然而又很有力的Python
web 框架。那里有一多重视教育程Flask Mega-Tutorial
series。(注:Django\Tornado\web.py感觉好多框:()

 

在大家深刻贯彻web service在此以前,让大家来大约地看1个Flask web
应用的协会示例。

 

此处都以在Unix-like(Linux,Mac OS
X)操作系统上面包车型大巴示范,可是别的系统也能够跑,例如windows下的Cygwin。或然命令有个别差别啊。(注:忽略Windows吧。)

 

先利用virtualenv安装多少个Flask的虚拟环境。假使没有设置virtualenv,开发python必备,最好去下载安装。

 

 

$ mkdir todo-api

$ cd todo-api

$ virtualenv flask

New python executable in flask/bin/python

Installing setuptools……………………….done.

Installing pip……………….done.

$ flask/bin/pip install flask

 

 那样做好了3个Flask的开销条件,开端创办一个简单的web应用,在当前目录里面创造叁个app.py文件:

 

 

#!flask/bin/python

from flask import Flask

 

app = Flask(__name__)

 

@app.route(‘/’)

def index():

    return “Hello, World!”

 

if __name__ == ‘__main__’:

    app.run(debug=True)

 

去执行app.py:

 

$ chmod a+x app.py

$ ./app.py

 * Running on

 * Restarting with reloader

后天得以打开浏览器,输入

 

好呢,拾贰分回顾吗。大家早先转换成RESTful service!

 

使用Python 和 Flask实现RESTful services

 

应用Flask建立web services一级简单。

 

当然,也有多如牛毛Flask extensions能够补助建立RESTful
services,不过这一个例实在太简单了,不须求采取其余扩张。

 

以此web
service提供扩充,删除、修改职务清单,所以大家须求将任务清单存款和储蓄起来。最简易的做法正是选用微型的数据库,可是数据库并不是本文涉及太多的。能够参见原版的书文小编的完整教程。Flask
Mega-Tutorial series

 

在此处例子我们将职分清单存款和储蓄在内部存款和储蓄器中,那样只好运维在单进度和单线程中,那样是不吻同盟为生产服务器的,若非就必需使用数据库了。

 

当今我们准备完结率先个web service的入口点:

 

 

#!flask/bin/python

from flask import Flask, jsonify

 

app = Flask(__name__)

 

tasks = [

    {

        ‘id’: 1,

        ‘title’: u’Buy groceries’,

        ‘description’: u’Milk, Cheese, Pizza, Fruit, Tylenol’, 

        ‘done’: False

    },

    {

        ‘id’: 2,

        ‘title’: u’Learn Python’,

        ‘description’: u’Need to find a good Python tutorial on the
web’, 

        ‘done’: False

    }

]

 

@app.route(‘/todo/api/v1.0/tasks’, methods=[www.30064.com ,’GET’])

def get_tasks():

    return jsonify({‘tasks’: tasks})

 

if __name__ == ‘__main__’:

    app.run(debug=True)

 

正如你所见,并不曾改变太多代码。大家将任务清单存储在list内(内部存款和储蓄器),list存放三个格外简单的数组字典。每一个实体正是大家地点定义的字段。

 

而 index 入口点有多少个get_tasks函数与/todo/api/v1.0/tasks
URI关联,只接受http的GET方法。

 

这些响应并非一般文本,是JSON格式的数额,是透过Flask框架的
jsonify模块格式化过的多少。

 

动用浏览器去测试web
service并不是二个好的措施,因为要创制差异类弄的HTTP请求,事实上,大家将采纳curl命令行。假若没有设置curl,快点去安装一个。

 

像刚刚一律运转app.py。

 

打开四个终极运维以下命令:

 

 

$ curl -i

HTTP/1.0 200 OK

Content-Type: application/json

Content-Length: 294

Server: Werkzeug/0.8.3 Python/2.7.3

Date: Mon, 20 May 2013 04:53:53 GMT

 

{

  “tasks”: [

    {

      “description”: “Milk, Cheese, Pizza, Fruit, Tylenol”,

      “done”: false,

      “id”: 1,

      “title”: “Buy groceries”

    },

    {

      “description”: “Need to find a good Python tutorial on the web”,

      “done”: false,

      “id”: 2,

      “title”: “Learn Python”

    }

  ]

}

 

那般就调用了2个RESTful service方法!

 

现行反革命,我们写第③个版本的GET方法取得一定的任务。获取单个职分:

 

 

from flask import abort

 

@app.route(‘/todo/api/v1.0/tasks/<int:task_id>’,
methods=[‘GET’])

def get_task(task_id):

    task = filter(lambda t: t[‘id’] == task_id, tasks)

    if len(task) == 0:

        abort(404)

    return jsonify({‘task’: task[0]})

 

 第二个函数稍稍复杂了有的。职分的id包括在U安德拉L内,Flask将task_id参数字传送入了函数内。

 

通过参数,检索tasks数组。假设参数字传送过来的id不设有于数组内,大家须要回到错误代码404,依据HTTP的规定,404象征是”Resource
Not Found”,能源未找到。

 

假如找到职责在内部存款和储蓄器数组内,我们通过jsonify模块将字典打包成JSON格式,并发送响应到客户端上。就像处理贰个实体字典一样。

 

试跳使用curl调用:

 

 

$ curl -i

HTTP/1.0 200 OK

Content-Type: application/json

Content-Length: 151

Server: Werkzeug/0.8.3 Python/2.7.3

Date: Mon, 20 May 2013 05:21:50 GMT

 

{

  “task”: {

    “description”: “Need to find a good Python tutorial on the web”,

    “done”: false,

    “id”: 2,

    “title”: “Learn Python”

  }

}

$ curl -i

HTTP/1.0 404 NOT FOUND

Content-Type: text/html

Content-Length: 238

Server: Werkzeug/0.8.3 Python/2.7.3

Date: Mon, 20 May 2013 05:21:52 GMT

 

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 3.2 Final//EN”>

<title>404 Not Found</title>

<h1>Not Found</h1>

<p>The requested URL was not found on the
server.</p><p>If you     entered the URL manually please
check your spelling and try again.</p>

 

当大家请求#2
id的财富时,可以获得,不过当大家请求#3的能源时回来了404不当。并且重临了一段奇怪的HTML错误,而不是我们期待的JSON,那是因为Flask发生了暗许的404响应。客户端要求接受的都以JSON的响应,由此我们必要创新404错误处理:

 

from flask import make_response

 

@app.errorhandler(404)

def not_found(error):

    return make_response(jsonify({‘error’: ‘Not found’}), 404)

如此那般我们就获得了和谐的API错误响应:

 

 

$ curl -i

HTTP/1.0 404 NOT FOUND

Content-Type: application/json

Content-Length: 26

Server: Werkzeug/0.8.3 Python/2.7.3

Date: Mon, 20 May 2013 05:36:54 GMT

 

{

  “error”: “Not found”

}

 

接下去大家落到实处 POST 方法,插入3个新的天职到数组中:

 

 

from flask import request

 

@app.route(‘/todo/api/v1.0/tasks’, methods=[‘POST’])

def create_task():

    if not request.json or not ‘title’ in request.json:

        abort(400)

    task = {

        ‘id’: tasks[-1][‘id’] + 1,

        ‘title’: request.json[‘title’],

        ‘description’: request.json.get(‘description’, “”),

        ‘done’: False

    }

    tasks.append(task)

    return jsonify({‘task’: task}), 201

 

 request.json里面含有呼吁数据,假设不是JSON可能个中没有包含title字段,将会回来400的错误代码。

 

当创造2个新的天职字典,使用最后3个任务id数值加1作为新的义务id(最不难易行的主意发生壹个唯一字段)。那里允许不带description字段,暗中认可将done字段值为False。

 

将新职务叠加到tasks数组里面,并且再次来到客户端201状态码和正好添加的天职内容。HTTP定义了201状态码为“Created”。

 

测试上边的新功用:

 

 

$ curl -i -H “Content-Type: application/json” -X POST -d ‘{“title”:”Read
a book”}’

HTTP/1.0 201 Created

Content-Type: application/json

Content-Length: 104

Server: Werkzeug/0.8.3 Python/2.7.3

Date: Mon, 20 May 2013 05:56:21 GMT

 

{

  “task”: {

    “description”: “”,

    “done”: false,

    “id”: 3,

    “title”: “Read a book”

  }

}

 

留意:假诺采纳原生版本的curl命令行提醒符,上边的命令会正确履行。借使是在Windows下选用Cygwin
bash版本的curl,须求将body部份添加双引号:

 

curl -i -H “Content-Type: application/json” -X POST -d
“{“””title”””:”””Read a book”””}”

基本上在Windows中供给选用双引号包罗body部份在内,而且要求多少个双引号转义体系。

 

姣好地方的工作,就可以阅览更新之后的list数组内容:

 

$ curl -i

HTTP/1.0 200 OK

Content-Type: application/json

Content-Length: 423

Server: Werkzeug/0.8.3 Python/2.7.3

Date: Mon, 20 May 2013 05:57:44 GMT

 

{

  “tasks”: [

    {

      “description”: “Milk, Cheese, Pizza, Fruit, Tylenol”,

      “done”: false,

      “id”: 1,

      “title”: “Buy groceries”

    },

    {

      “description”: “Need to find a good Python tutorial on the web”,

      “done”: false,

      “id”: 2,

      “title”: “Learn Python”

    },

    {

      “description”: “”,

      “done”: false,

      “id”: 3,

      “title”: “Read a book”

    }

  ]

}

 

剩余的多个函数如下:

 

 

@app.route(‘/todo/api/v1.0/tasks/<int:task_id>’,
methods=[‘PUT’])

def update_task(task_id):

    task = filter(lambda t: t[‘id’] == task_id, tasks)

    if len(task) == 0:

        abort(404)

    if not request.json:

        abort(400)

    if ‘title’ in request.json and type(request.json[‘title’]) !=
unicode:

        abort(400)

    if ‘description’ in request.json and
type(request.json[‘description’]) is not unicode:

        abort(400)

    if ‘done’ in request.json and type(request.json[‘done’]) is not
bool:

        abort(400)

    task[0][‘title’] = request.json.get(‘title’,
task[0][‘title’])

    task[0][‘description’] = request.json.get(‘description’,
task[0][‘description’])

    task[0][‘done’] = request.json.get(‘done’, task[0][‘done’])

    return jsonify({‘task’: task[0]})

 

@app.route(‘/todo/api/v1.0/tasks/<int:task_id>’,
methods=[‘DELETE’])

def delete_task(task_id):

    task = filter(lambda t: t[‘id’] == task_id, tasks)

    if len(task) == 0:

        abort(404)

    tasks.remove(task[0])

    return jsonify({‘result’: True})

 

delete_task函数没什么太特其余。update_task函数要求检讨所输入的参数,幸免产生错误的bug。确定保障是意料的JSON格式写入数据Curry面。

 

测试将任务#2的done字段变更为done状态:

 

 

$ curl -i -H “Content-Type: application/json” -X PUT -d ‘{“done”:true}’

HTTP/1.0 200 OK

Content-Type: application/json

Content-Length: 170

Server: Werkzeug/0.8.3 Python/2.7.3

Date: Mon, 20 May 2013 07:10:16 GMT

 

{

  “task”: [

    {

      “description”: “Need to find a good Python tutorial on the web”,

      “done”: true,

      “id”: 2,

      “title”: “Learn Python”

    }

  ]

}

 

改进Web Service接口

 

时下大家还有3个题材,客户端有恐怕须求从重返的JSON中再次布局U哈弗I,要是后天参加新的性状时,大概供给修改客户端。(例如新增版本。)

 

大家得以回来整个UXC90I的路子给客户端,而不是职分的id。为了这些意义,创设一个小函数生成三个“public”版本的职责U途观I重返:

 

 

from flask import url_for

 

def make_public_task(task):

    new_task = {}

    for field in task:

        if field == ‘id’:

            new_task[‘uri’] = url_for(‘get_task’,
task_id=task[‘id’], _external=True)

        else:

            new_task[field] = task[field]

    return new_task

 

通过Flask的url_for模块,获取职分时,将职责中的id字段替换来uri字段,并且把值改为uri值。

 

当我们再次来到包括任务的list时,通过那些函数处理后,再次回到完整的uri给客户端:

 

@app.route(‘/todo/api/v1.0/tasks’, methods=[‘GET’])

def get_tasks():

    return jsonify({‘tasks’: map(make_public_task, tasks)})

当今看来的搜索结果:

 

 

$ curl -i

HTTP/1.0 200 OK

Content-Type: application/json

Content-Length: 406

Server: Werkzeug/0.8.3 Python/2.7.3

Date: Mon, 20 May 2013 18:16:28 GMT

 

{

  “tasks”: [

    {

      “title”: “Buy groceries”,

      “done”: false,

      “description”: “Milk, Cheese, Pizza, Fruit, Tylenol”,

      “uri”: “”

    },

    {

      “title”: “Learn Python”,

      “done”: false,

      “description”: “Need to find a good Python tutorial on the web”,

      “uri”: “”

    }

  ]

}

 

那种情势防止了与别的作用的分外,得到的是完好uri而不是一个id。

 

RESTful web service的吕梁表明

 

大家曾经做到了任何作用,不过我们还有三个标题。web
service任哪个人都得以访问的,这不是多少个好主意。

 

方今service是富有客户端都能够接连的,要是有外人知道了这一个API就能够写个客户端随意改动数据了。
大多数学科没有与中卫有关的剧情,那是个13分严重的难点。

 

最简单易行的不二法门是在web
service中,只允许用户名和密码验证通过的客户端连接。在三个常常的web应用中,应该有记名表单提交去注脚,同时服务器会创立一个对话进度去进行广播发表。那个会话进程id会被积存在客户端的cookie里面。也就那样就违返了我们REST中无状态的平整,由此,大家要求客户端每一回都将他们的注脚消息发送到服务器。

 

 为此大家有三种格局表单认证方式去做,分别是 Basic 和 Digest。

 

此间有有个小Flask extension能够轻松做到。首先要求设置 Flask-HTTPAuth :

 

$ flask/bin/pip install flask-httpauth

一经web service唯有用户 ok 和密码为 python
的用户接入。上面就安装了二个Basic HTTP认证:

 

 

from flask.ext.httpauth import HTTPBasicAuth

auth = HTTPBasicAuth()

 

@auth.get_password

def get_password(username):

    if username == ‘ok’:

        return ‘python’

    return None

 

@auth.error_handler

def unauthorized():

    return make_response(jsonify({‘error’: ‘Unauthorized access’}),
401)

 

get_password函数是1个回调函数,获取1个已知用户的密码。在复杂的系统中,函数是索要到数据库中反省的,不过此间只是五个小示例。

 

当发生认证错误之后,error_handler回调函数会发送错误的代码给客户端。那里大家自定义三个错误代码401,再次回到JSON数据,而不是HTML。

 

将@auth.login_required装饰器添加到供给证实的函数方面:

 

@app.route(‘/todo/api/v1.0/tasks’, methods=[‘GET’])

@auth.login_required

def get_tasks():

    return jsonify({‘tasks’: tasks})

现行反革命,试试使用curl调用这一个函数:

 

 

$ curl -i

HTTP/1.0 401 UNAUTHORIZED

Content-Type: application/json

Content-Length: 36

WWW-Authenticate: Basic realm=”Authentication Required”

Server: Werkzeug/0.8.3 Python/2.7.3

Date: Mon, 20 May 2013 06:41:14 GMT

 

{

  “error”: “Unauthorized access”

}

 

此间表示了没通过认证,上边是带用户名与密码的印证:

 

$ curl -u ok:python -i

HTTP/1.0 200 OK

Content-Type: application/json

Content-Length: 316

Server: Werkzeug/0.8.3 Python/2.7.3

Date: Mon, 20 May 2013 06:46:45 GMT

 

{

  “tasks”: [

    {

      “title”: “Buy groceries”,

      “done”: false,

      “description”: “Milk, Cheese, Pizza, Fruit, Tylenol”,

      “uri”: “”

    },

    {

      “title”: “Learn Python”,

      “done”: false,

      “description”: “Need to find a good Python tutorial on the web”,

      “uri”: “”

    }

  ]

}

 

其一认证extension10分灵活,能够随钦定必要验证的APIs。

 

为了确认保证登录音信的安全,最好的办法还是选择https加密的通讯方式,客户端与服务器端传输认证新闻都是加密过的,防止第壹方的人去见见。

 

当使用浏览器去做客这些接口,会弹出七个丑丑的记名对话框,假使密码错误就回再次回到401的错误代码。为了幸免浏览器弹出注明对话框,客户端应该处理好这些登录请求。

 

有一个小技巧可避防止那么些题材,正是修改重返的错误代码401。例如修改成403(”Forbidden“)就不会弹出注明对话框了。

 

@auth.error_handler

def unauthorized():

    return make_response(jsonify({‘error’: ‘Unauthorized access’}),
403)

自然,同时也急需客户端知道那么些403错误的意义。

 

最后

 

还有很多措施去革新这几个web service。

 

其实,四个当真的web
service应该利用真正的数据库。使用内存数据结构有尤其多的范围,不要用在实际上选择方面。

 

除此以外1只,处理多用户。要是系统帮助多用户认证,则职务清单也是对应多用户的。同时大家须求有第三种财富,用户资源。当用户注册时选拔POST请求。使用GET再次来到用户音信到客户端。使用PUT请求更新用户资料,大概邮件地址。使用DELETE删除用户账号等。

 

因而GET请求检索职责清单时,有广大主意能够进扩充。第②,能够拉长分页参数,使客户端只请求一部份数据。第壹,能够加上筛选重点字等。全体那个成分得以添加到UXC60L下边的参数。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图