REST已经化为web,API服务器端

  作为2个新手程序员,刚上班不久就被BOSS,拖去开发restful api
与APP交互。拿到手一脸蒙圈,然后看了某度的别人所陈设的,感觉就是再度很多,设计很多。然后FQ出去看了漫长,终于把那几个K完了。然后写下这么些博文,让投机总计一下和笔录。

  作为3个新手程序员,刚上班不久就被BOSS,拖去开发restful api
与APP交互。拿到手一脸蒙圈,然后看了某度的人家所设计的,感觉就是再次很多,设计很多。然后FQ出去看了长时间,终于把这一个K完了。然后写下这一个博文,让本身总括一下和著录。

近来这一个年,REST已经改成web
services和APIs的规范架构,很多APP的架构基本上是拔取RESTful的款式了。

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

近期那个年,REST已经变为web
services和APIs的正统架构,很多APP的架构基本上是采用RESTful的款式了。

 

正文将会利用python的Flask框架轻松完结3个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的主导概念是治本财富。能源是由UHavalIs来代表,客户端应用HTTP当中的’POST,
OPTIONS, GET, PUT, DELETE’等措施发送请求到服务器,改变相应的能源处境。

 

HTTP请求方法一般也不行适合去描述操作能源的动作:

 

HTTP方法
动作
例子

GET
获取能源消息

 

(检索订单清单)

 

GET
获取财富音信

 

(检索订单 #123)

 

POST
创立3个次的能源

 

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

 

PUT
更新二个资源

 

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

 

DELETE
删除3个能源

 

剔除订单#123

 

REST请求并不必要特定的数额格式,经常采用JSON作为请求体,或者URubiconL的询问参数的一部份。

 

规划3个简便的web service

 

上边的义务将会操练设计以REST准则为指导,通过区其余伸手方法操作能源,标识财富的事例。

 

咱俩将写二个To Do List 应用,并且安排1个web
service。第2步,规划一个根U奥迪Q5L,例如:

 

 

 

下边的UOdysseyL包罗了应用程序的称谓、API版本,那是尤其卓有成效的,既提供了命名空间的划分,同时又与任何系统区分开来。版本号在进步新特征时丰硕有用,当一个新功能特色增添在新本子下边时,并不影响旧版本。

 

第叁步,规划财富的U本田CR-VL,这么些例子拾壹分简便,唯有义务清单。

 

设计如下:

 

HTTP方法
URI
动作

GET
检索职责清单

GET
] 检索三个任务

POST
创立3个新职务

PUT
]
更新1个已存在的任务

DELETE
] 删除二个职务

咱俩定义职责清单有以下字段:

 

id:唯一标识。整型。

title:简短的任务描述。字符串型。

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

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

上述基本到位了规划部份,接下去大家将会促成它!

 

 容易了然Flask框架

 

Flask好不难,但是又很强劲的Python web 框架。那里有一名目繁多教程Flask
梅格a-Tutorial series。(注:Django\Tornado\web.py感觉好多框:()

 

在大家深入落到实处web service从前,让我们来总结地看多个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=[‘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。

 

开辟1个巅峰运维以下命令:

 

 

$ 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”

    }

  ]

}

 

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

 

明日,我们写第3个本子的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格式写入数据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

REST已经化为web,API服务器端。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接口

 

当下我们还有1个难点,客户端有或者须要从重回的JSON中再一次布局U卡宴I,要是今日进入新的特点时,或然须要修改客户端。(例如新增版本。)

 

大家能够回来整个U中华VI的路径给客户端,而不是天职的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的安全声明

 

咱俩早就到位了百分之百功效,不过我们还有1个难点。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
的用户接入。下边就安装了多少个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回调函数会发送错误的代码给客户端。这里我们自定义2个错误代码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。可以把常量就是布局数据库的写在头顶,或是写在别的1个页面,导入这些cofin。

  首先大家要做的是PHP
db封装,这些要含有最中央的CRUD。可以把常量就是布署数据库的写在头顶,或是写在此外2个页面,导入这么些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对应不一样的主意,那样有利于而且便于区分。

  每1个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有个天性,他只会修改2回,不管你怎么刷新页面)

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前面的_去掉,然后在用谷歌(谷歌(Google))就可以动用了]

  [此处要采纳2个工具
chorm的postman,那几个工具得以一成不变从APP发送不一样的method方法,发送的格式因为都是JSON,也可以在上边修改,那几个是其余软件,不会操作自身百度时而,对了,下载下来如若发现装不上来,可以把内部特别文件的后缀名,改成.rar.然后在解压到当前的公文夹,把_metadata前面的_去掉,然后在用谷歌就足以运用了]

 

 

 

RESTful web service的样子

  而本人不采取put和delect
,不是嫌麻烦,是那四个没怎么用过,有点抗拒。小编是如此写的

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

 

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

  都用POST或是分开get和Post,只要传入的json中有”首个“[way]=add或select,把措施传进来,用swtich这么些主意判断。

REST架构就是为着HTTP协议布署的。RESTful web
services的中坚概念是治本能源。财富是由UOdysseyIs来代表,客户端应用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方法
动作
例子

  当大家执行了一回那几个DB流程回来,大家要发送json数据回去和HTTP
code回去。

  当大家实施了2遍这么些DB流程回来,大家要发送json数据回去和HTTP
code回去。

GET
获取财富音信

  查询是要回来的,其余的回来二个标示就大约了 。

  查询是要回来的,其余的归来3个标记就基本上了 。

  发送回去的json:

  发送回去的json:

 

  {code:200,data:”}本身把要回去的数码拼进去,不回来数据的{code:200,msg:…};这几个都得以自定义再次来到的,当然要写成二个文档

  {code:200,data:”}本人把要回来的多寡拼进去,不回去数据的{code:200,msg:…};那么些都足以自定义重返的,当然要写成1个文档

(检索订单清单)

  

  

 

  发送回去的httpd code:

  发送回去的httpd code:

GET
获取能源音讯

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

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

  http_response_code(200);

  http_response_code(200);

 

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

  不懂有没有同桌也会跟自家同一,说那个函数没概念,那么些时候你要本身定义二个函数了

(检索订单 #123)

  澳门葡京备用网址 1

  澳门葡京备用网址 2

 

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

  不发个图感觉都不算是博客。

POST
成立八个次的能源

  

  

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

  添加方法里面,小编不是怎么都听外人丢什么,大家就要什么样的。

 

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

  我们要把温馨的字段表封装,就是把那几个想要的 $data[‘oid’] =
给对方的字段,json解封下来所对应的字段,大家把团结想要的取下来,然后才放进去。这些是有必不可少的,当然大家也要问对面想要什么,小编也发特定的回给他。

(使用带多少的乞请,成立贰个新的订单)

  到此处restful
api设计已毕了。没有何样规划方面的学问。有哪些的大神我们一起互换,终归‘新手上路’;

  到此处restful
api设计落成了。没有怎么规划方面的学问。有怎么着的大神大家一起交换,终究‘新手上路’;

 

                                                                                      —-j.m

                                                                                      —-j.m

PUT
更新1个能源

 

 

 

(使用带多少的呼吁,更新#123订单)

 

DELETE
删除3个能源

 

剔除订单#123

 

REST请求并不需求特定的多少格式,日常拔取JSON作为请求体,恐怕U中华VL的询问参数的一部份。

 

安排五个简便的web service

 

上边的义务将会操练设计以REST准则为指引,通过差其他伸手方法操作财富,标识能源的例证。

 

我们将写二个To Do List 应用,并且布署四个web
service。第③步,规划三个根U卡宴L,例如:

 

 

 

地点的UQashqaiL包含了应用程序的名称、API版本,那是十分一蹴而就的,既提供了命名空间的分割,同时又与此外系统分别开来。版本号在升级新特色时尤其有用,当2个新功效特色增添在新本子上边时,并不影响旧版本。

 

其次步,规划财富的UHighlanderL,那些事例十一分简便,唯有任务清单。

 

规划如下:

 

HTTP方法
URI
动作

GET
检索任务清单

GET
] 检索二个职责

POST
成立3个新职分

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

DELETE
] 删除三个任务

我们定义义务清单有以下字段:

 

id:唯一标识。整型。

title:简短的任务描述。字符串型。

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

done:职分成功景况。布尔值型。

如上基本做到了安插部份,接下去大家将会兑现它!

 

 简单了然Flask框架

 

Flask好不难,但是又很有力的Python
web 框架。那里有一种类教程Flask Mega-Tutorial
series。(注:Django\Tornado\web.py感觉好多框:()

 

在我们深入贯彻web service此前,让咱们来归纳地看七个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的费用条件,初叶创办3个简便的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=[‘GET’])

def get_tasks():

    return jsonify({‘tasks’: tasks})

 

if __name__ == ‘__main__’:

    app.run(debug=True)

 

正如你所见,并没有改变太多代码。大家将职责清单存储在list内(内存),list存放五个卓殊简单的数组字典。各种实体就是大家地点定义的字段。

 

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

 

其一响应并非一般文本,是JSON格式的多少,是由此Flask框架的
jsonify模块格式化过的多寡。

 

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

 

像刚刚同样运维app.py。

 

开拓2个终端运维以下命令:

 

 

$ 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”

    }

  ]

}

 

诸如此类就调用了3个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]})

 

 第2个函数稍稍复杂了部分。职务的id蕴含在UEvoqueL内,Flask将task_id参数传入了函数内。

 

因此参数,检索tasks数组。如若参数传过来的id不存在于数组内,大家需要回到错误代码404,依照HTTP的规定,404象征是”Resource
Not Found”,财富未找到。

 

比方找到职务在内存数组内,我们经过jsonify模块将字典打包成JSON格式,并发送响应到客户端上。似乎处理1个实体字典一样。

 

试跳使用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 方法,插入2个新的天职到数组中:

 

 

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格式写入数据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接口

 

此时此刻大家还有贰个难点,客户端有只怕必要从重临的JSON中另行社团U福睿斯I,假设明日参预新的特点时,或者须求修改客户端。(例如新增版本。)

 

作者们得以回到整个U冠道I的不二法门给客户端,而不是义务的id。为了这些职能,创制贰个小函数生成三个“public”版本的职务U福特ExplorerI重返:

 

 

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而不是3个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函数是一个回调函数,获取2个已知用户的密码。在千丝万缕的连串中,函数是索要到数据库中检查的,然而此间只是五个小示例。

 

当暴发认证错误之后,error_handler回调函数会发送错误的代码给客户端。那里大家自定义2个错误代码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”: “”

    }

  ]

}

 

其一认证extension十二分心灵手巧,能够随钦赐需求验证的APIs。

 

为了保险登录音讯的安全,最好的措施如故选拔https加密的通信方式,客户端与劳务器端传输认证音信都是加密过的,幸免第叁方的人去探望。

 

当使用浏览器去访问那么些接口,会弹出2个丑丑的报到对话框,倘若密码错误就回重回401的错误代码。为了防止万一浏览器弹出讲明对话框,客户端应该处理好这一个登录请求。

 

有三个小技巧可以防止那个题材,就是修改再次回到的错误代码401。例如修改成403(”Forbidden“)就不会弹出评释对话框了。

 

@auth.error_handler

def unauthorized():

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

理所当然,同时也要求客户端知道这些403不当的意思。

 

最后

 

再有很多艺术去改善这么些web service。

 

实际,三个实在的web
service应该使用真正的数据库。使用内存数据结构有丰盛多的范围,不要用在骨子里运用方面。

 

其余三头,处理多用户。假如系统资助多用户认证,则职分清单也是对应多用户的。同时大家需求有第2种能源,用户能源。当用户注册时接纳POST请求。使用GET重返用户新闻到客户端。使用PUT请求更新用户资料,或然邮件地址。使用DELETE删除用户账号等。

 

通过GET请求检索职分清单时,有众多格局能够进增添。第二,可以加上分页参数,使客户端只请求一部份数据。第贰,可以拉长筛选重点字等。全体那几个因素得以加上到UCR-VL下边的参数。

相关文章

发表评论

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

*
*
Website