rest服务器的搭建 - CSDN博客 http://blog.csdn.net/zhanghaotian2011/article/details/8760794

REST的架构设计

  REST(Representational State Transfer)是一种轻量级的Web Service架构风格,其实现和操作明显比SOAP和XML-RPC更为简洁,可以完全通过HTTP协议实现,还可以利用缓存Cache来提高响应速度,性能、效率和易用性上都优于SOAP协议。

  REST架构遵循了CRUD原则,CRUD原则对于资源只需要四种行为:Create(创建)、Read(读取)、Update(更新)和Delete(删除)就可以完成对其操作和处理。这四个操作是一种原子操作,即一种无法再分的操作,通过它们可以构造复杂的操作过程,正如数学上四则运算是数字的最基本的运算一样。

  REST架构让人们真正理解我们的网络协议HTTP本来面貌,对资源的操作包括获取、创建、修改和删除资源的操作正好对应HTTP协议提供的GET、POST、PUT和DELETE方法,因此REST把HTTP对一个URL资源的操作限制在GET、POST、PUT和DELETE这四个之内。这种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。

  REST的设计准则

  REST架构是针对Web应用而设计的,其目的是为了降低开发的复杂性,提高系统的可伸缩性。REST提出了如下设计准则:

  网络上的所有事物都被抽象为资源(resource);

  每个资源对应一个唯一的资源标识符(resource identifier);

  通过通用的连接器接口(generic connector interface)对资源进行操作;

  对资源的各种操作不会改变资源标识符;

  所有的操作都是无状态的(stateless)。

  使用REST架构

  对于开发人员来说,关心的是如何使用REST架构,这里我们来简单谈谈这个问题。REST不仅仅是一种崭新的架构,它带来的更是一种全新的Web开发过程中的思维方式:通过URL来设计系统结构。REST是一套简单的设计原则、一种架构风格(或模式),不是一种具体的标准或架构。REST有很多成功的使用案例,著名的Delicious和Flickr都提供基于REST风格的API使用,客户端调用也极其方便。

Designing a RESTful API with Python and Flask - miguelgrinberg.com https://blog.miguelgrinberg.com/post/designing-a-restful-api-with-python-and-flask

使用python的Flask实现一个RESTful API服务器端[翻译] - Vovolie - 博客园 https://www.cnblogs.com/vovlie/p/4178077.html

# !flask/bin/python
from flask import Flask myapp = Flask(__name__) @myapp.route('/')
def index():
return "Hello, World!" if __name__ == '__main__':
myapp.run(host='120.78.187.72', debug=True) #指明调用的解释器

[root@bigdata-server-02 myrestserver]# cat app.py
from flask import Flask

myapp = Flask(__name__)

@myapp.route('/')
def index():
return "Hello, World!"

if __name__ == '__main__':
myapp.run(host='0.0.0.0', debug=True)

[root@bigdata-server-02 myrestserver]# python app.py
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 229-432-432
220.152.100.225 - - [04/Dec/2017 03:42:42] "GET / HTTP/1.1" 200 -
220.152.100.225 - - [04/Dec/2017 03:43:03] "GET / HTTP/1.1" 200 -

浏览器输入云服务器的外网IP

ip:5000

ok

[root@bigdata-server-02 myrestserver]# vim mytask.py
[root@bigdata-server-02 myrestserver]# cat mytask.py
from flask import Flask, jsonify

mytask = Flask(__name__)

tasks = [
{
'id': 1,
'title': 'Buy groceries',
'description': 'Milk, Cheese, Pizza, Fruit, Tylenol',
'done': False
},
{
'id': 2,
'title': 'Learn Python',
'description': 'Need to find a good Python tutorial on the web',
'done': False
}
]
tasks_try = [
{
'id': 111,
'title': 'Buy groceries',
'description': 'Milk, Cheese, Pizza, Fruit, Tylenol',
'done': False
},
{
'id': 222,
'title': 'Learn Python',
'description': 'Need to find a good Python tutorial on the web',
'done': False
}
]

@mytask.route('/restapi/todo/v1.0/tasks', methods=['GET'])
def get_tasks():
return jsonify({'tasks': tasks})

@mytask.route('/restapi/todo/v1.0/tasks_try', methods=['GET'])
def get_tasks_try():
return jsonify({'tasks_try': tasks_try})

if __name__ == '__main__':
mytask.run(host='0.0.0.0',debug=True)
[root@bigdata-server-02 myrestserver]# python mytask.py
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 229-432-432
220.152.200.225 - - [04/Dec/2017 04:19:46] "GET /restapi/todo/v1.0/tasks HTTP/1.1" 200 -
220.152.200.225 - - [04/Dec/2017 04:19:52] "GET /restapi/todo/v1.0/tasks HTTP/1.1" 200 -
220.152.200.225 - - [04/Dec/2017 04:19:53] "GET /restapi/todo/v1.0/tasks HTTP/1.1" 200 -
220.152.200.225 - - [04/Dec/2017 04:20:00] "GET /restapi/todo/v1.0/tasks_try HTTP/1.1" 200 -
220.152.200.225 - - [04/Dec/2017 04:20:07] "GET /restapi/todo/v1.0/tasks HTTP/1.1" 200 -

from flask import Flask, jsonify, abort, make_response, request

"""
考虑到后续的迁移以及后续的稳定性
此处密码临时至于此
"""
"""
tmp
""" UidChkUrl = Flask(__name__)
UidChkUrl.config['JSON_AS_ASCII'] = False @UidChkUrl.route('/RestApi/v1.0/UidChkUrl', methods=['POST'])
def uid_chk_url():
if not request.json or not 'uid' in request.json:
abort(400)
task = {
'uid': request.json['uid'],
'no_open': 12,
'no_ad': 34,
'description': '该uid在ad_direct_order中共计123条当前未失效,其中12条打不开相应页面,34条页面中没有我司广告位',
'cost_time': 123,
'request_time': time.strftime('%Y%m%d_%H%M%S', time.localtime(time.time() - 123)),
'current_time': time.strftime('%Y%m%d_%H%M%S', time.localtime(time.time()))
}
return jsonify({'status': '1', 'info': task}), 201 if __name__ == '__main__':
UidChkUrl.run(host='0.0.0.0', debug=True)
request.json['uid']
class JSONMixin(object):
"""Common mixin for both request and response objects to provide JSON
parsing capabilities. .. versionadded:: 1.0
""" _cached_json = (Ellipsis, Ellipsis) @property
def is_json(self):
"""Check if the mimetype indicates JSON data, either
:mimetype:`application/json` or :mimetype:`application/*+json`. .. versionadded:: 0.11
"""
mt = self.mimetype
return (
mt == 'application/json'
or (mt.startswith('application/')) and mt.endswith('+json')
) @property
def json(self):
"""This will contain the parsed JSON data if the mimetype indicates
JSON (:mimetype:`application/json`, see :meth:`is_json`), otherwise it
will be ``None``.
"""
return self.get_json()

  

request.get_data()

    def get_data(self, cache=True, as_text=False, parse_form_data=False):
"""This reads the buffered incoming data from the client into one
bytestring. By default this is cached but that behavior can be
changed by setting `cache` to `False`. Usually it's a bad idea to call this method without checking the
content length first as a client could send dozens of megabytes or more
to cause memory problems on the server. Note that if the form data was already parsed this method will not
return anything as form data parsing does not cache the data like
this method does. To implicitly invoke form data parsing function
set `parse_form_data` to `True`. When this is done the return value
of this method will be an empty string if the form parser handles
the data. This generally is not necessary as if the whole data is
cached (which is the default) the form parser will used the cached
data to parse the form data. Please be generally aware of checking
the content length first in any case before calling this method
to avoid exhausting server memory. If `as_text` is set to `True` the return value will be a decoded
unicode string. .. versionadded:: 0.9
"""
rv = getattr(self, '_cached_data', None)
if rv is None:
if parse_form_data:
self._load_form_data()
rv = self.stream.read()
if cache:
self._cached_data = rv
if as_text:
rv = rv.decode(self.charset, self.encoding_errors)
return rv

  

pip包检索

/usr/local/bin/pip3 search aliyun
/usr/local/bin/pip3 install aliyun-python-sdk-core-v3
/usr/local/bin/pip3 install aliyun-python-sdk-sts

import json
from flask import Flask, jsonify, abort, make_response, request
import time
from aliyunsdkcore import client
from aliyunsdksts.request.v20150401 import AssumeRoleRequest def getSts(uid):
# 通过管理控制后台-访问控制 https://help.aliyun.com/product/28625.html
# RAM控制台 https://ram.console.aliyun.com/
# STS授权相关信息获取步骤:
# 1.RAM控制台用户管理创建子用户(User)同时点击该用户创建并获取AccessKeyID和AccessKeySecret https://help.aliyun.com/document_detail/28637.html
# 2.对该子用户(User) 授予AliyunSTSAssumeRoleAccess策略(必须),如需自定义策略请看 https://help.aliyun.com/document_detail/28640.html
# 3.RAM控制台角色管理创建角色role,进行自定义授权设置(控制操作的内容),获取Arn https://help.aliyun.com/document_detail/28649.html
# 注意点:
# 只有子用户(User)才能调用 AssumeRole 接口
# 阿里云主用户(Root User)的AccessKeys不能用于发起AssumeRole请求
# python sdk说明
# 构建一个 Aliyun Client, 用于发起请求
# 构建Aliyun Client时需要设置AccessKeyId和AccessKeySevcret
# STS是Global Service, API入口位于华东 1 (杭州) , 这里Region填写"cn-hangzhou"
# clt = client.AcsClient('<access-key-id>','<access-key-secret>','cn-hangzhou')
AccessKeyID = "************************"
AccessKeySecret = "************************"
roleArn = "************************" kid, ks = '5', '55'
AccessKeyID, AccessKeySecret = kid, ks
roleArn = 'acs:ram::30646318:role/aliyunosstokengeneratorrole'
clt = client.AcsClient(AccessKeyID, AccessKeySecret, 'cn-hangzhou')
# 构造"AssumeRole"请求
request___ = AssumeRoleRequest.AssumeRoleRequest()
# 指定角色 需要在 RAM 控制台上获取
request___.set_RoleArn(roleArn)
# RoleSessionName 是临时Token的会话名称,自己指定用于标识你的用户,主要用于审计,或者用于区分Token颁发给谁
# 但是注意RoleSessionName的长度和规则,不要有空格,只能有'-' '.' '@' 字母和数字等字符
# 具体规则请参考API文档中的格式要求 '''
#AssumeRole_操作接口_API 参考(STS)_访问控制-阿里云 https://help.aliyun.com/document_detail/28763.html RoleSessionName 类型:String
必须:是
描述:用户自定义参数。此参数用来区分不同的Token,可用于用户级别的访问审计。
格式:^[a-zA-Z0-9\.@\-_]+$ 2-32个字符
'''
request___.set_RoleSessionName(uid) # OSS Policy settings could not set by default
# can read https://help.aliyun.com/document_detail/56288.html
# case https://help.aliyun.com/knowledge_detail/39717.html?spm=5176.product28625.6.735.5etPTf
# case https://help.aliyun.com/knowledge_detail/39712.html?spm=5176.7739717.6.729.aZiRgD
# 发起请求,并得到response
try:
response = clt.do_action_with_exception(request___)
## { "ErrorDump": "the JSON object must be str, not 'bytes'", "StatusCode": "500" }
# text = json.loads(response) win ok linux + .decode('utf-8') 加后 win 依然ok
text = json.loads(response.decode('utf-8')) stsDict = dict().fromkeys(['RequestId', 'uid', 'Expiration', 'SecurityToken', 'StatusCode'])
stsDict["RequestId"] = text["RequestId"]
stsDict["uid"] = uid
stsDict['Expiration'] = text["Credentials"]['Expiration']
stsDict['SecurityToken'] = text["Credentials"]['SecurityToken']
stsDict["StatusCode"] = "200" # stsText = json.dumps(stsDict)
print('-----------》')
print(stsDict)
print('《-----------')
return stsDict
except Exception as e:
print(e)
# errorDict = dict().fromkeys(['StatusCode', 'ErrorCode', 'ErrorMessage'])
errorDict = dict().fromkeys(['StatusCode', 'ErrorDump'])
errorDict["StatusCode"] = "500"
# errorDict["ErrorMessage"] = e.message
# errorDict["ErrorCode"] = e.error_code
errorDict["ErrorDump"] = '{}'.format(e)
# stsText = json.dumps(errorDict)
return errorDict
# return stsText
pass aliBridge = Flask(__name__)
aliBridge.config['JSON_AS_ASCII'] = False @aliBridge.route('/v1.0/aliBridge/aliyunosstokengenerator', methods=['POST'])
def aliyunosstokengeneratorrole():
if not request.json:
abort(400)
chk_k = ['ipv4', 'imei', 'kid', 'ks']
ipv4, imei, kid, ks = request.json['ipv4'], request.json['imei'], request.json['kid'], request.json['ks']
# ipv4, imei, kid, ks = request.json[0:4]
uid = 'ipv4@{}@imei@{}'.format(ipv4, imei)
uid = '{}@{}'.format(ipv4, imei)
# uid ='ipv4__123__imei_123',
if (kid, ks) != ('ourServerKeyId', 'ourServerKeyValue'):
abort(400)
for c in chk_k:
if c not in request.json:
abort(400)
# task = {
# 'uid': request.json['uid'],
# # 'uid': request,
# 'no_open': 12,
# 'no_ad': 34,
# 'description': '该uid在ad_direct_order中共计123条当前未失效,其中12条打不开相应页面,34条页面中没有我司广告位',
# 'cost_time': 123,
# 'request_time': time.strftime('%Y%m%d_%H%M%S', time.localtime(time.time() - 123)),
# 'current_time': time.strftime('%Y%m%d_%H%M%S', time.localtime(time.time()))
# }
# return jsonify({'status': '1', 'info': task}), 201 task = getSts(uid) return jsonify(task), 201 '''
{
"ipv4":"197.164.165.154","imei":"123456789012347","kid":"ourServerKeyId","ks":"ourServerKeyValue"
}
'''
'''
{ "Expiration": "2018-06-15T07:04:29Z", "RequestId": "8F24601E-48E7-42F1-9128-2D631595DF9C", "SecurityToken": "CAISjQJ1q6Ft5B2yfSjIr4jhEer53pUV7bSaUWfFgk03QPxtubz91Dz2IHlNdHJpBeoZsfg2nWpQ7PgYlrYqGsADHBKYK5Ius9IOrF+JOtCa55HrsuxV0MT/QjTMU69uPTV6J7eXdsjUX9vwQXKm/3YB7NmXXDGmWEPfQv/toJV7b9MRcxClZD5dfrl/LRdjr8loXhm4d4zaUHjQj3HXEVBjtydllGp78t7f+MCH7QfEh1CIoY185aaRecD6M5c3ZcdFPo3rjLAsRM3oyzVN7hVGzqBygZFf9C3P1tPnWAAIs07fb7CLrYE2dVUhPPZgAd1NqPntiPt/offPkIf6zRlAO+xPWjjYXpqnxMbU3ksPUBqAATD+F5nQSnqFspyaLTywtxkTppmjCcCqTNDzRHG6X8umfz2IBECEIM8kWjmG9d/a6smkzgGiaZKGCy/AfzM06QWXyVmFZ8SdlBxJZxsW5qVKE0Hlbgx6rZao1Gm4uWF8r+1/4yTUd40cyjUjmoiaEj6iw6+oDWsS2RVG2hAjlaUN", "StatusCode": "200", "uid": "197.164.165.154@123456789012347" }
''' if __name__ == '__main__':
aliBridge.run(host='0.0.0.0', port=5001, debug=True)

  

《-----------
192.168.36.99 - - [/Jun/ ::] "POST /v1.0/aliBridge/aliyunosstokengenerator HTTP/1.1" -
-----------》
{'SecurityToken': 'CAISjQJ1q6Ft5B2yfSjIr4nYPtPQnLpE5LKCaUj0o3lhf9lEjfPMjTz2IHlNdHJpBeoZsfg2nWpQ7PgYlrYqGsADHBKYK5Ius9IOrF+JOtCa55HrsuxV0MT/QjTMU5tTczR6J7eXdsjUX9vwQXKm/3YB7NmXXDGmWEPfQv/toJV7b9MRcxClZD5dfrl/LRdjr8loXhm4d4zaUHjQj3HXEVBjtydllGp78t7f+MCH7QfEh1CIoY185aaRecD6M5c3ZcdFPo3rjLAsRM3oyzVN7hVGzqBygZFf9C3P1tPnWAAIs07fb7CLrYE2dVUhPPZgAd1NqPntiPt/offPkIf6zRlAO+xPWjjYXpqnxMbU3ksPUBqAAaQv4QxLwoq6uvykmhGQJJNsH6gTnXcrLjhYUZ9G9lBNUV7NGq4hNJnpSWOw/5wBV3N+yZyO4ftTtLQG28tYa/EUy0zOri5xxB9t2GEfv2xNgtm5c5XsgZwAQEoiBvLHWWeBMDHkQGf+2tYWwQWf4IOa1Ij6lacZP6+BaFE7MG9h', 'StatusCode': '', 'Expiration': '2018-06-15T07:56:14Z', 'RequestId': 'BBD5B0B1-49DA-4931-98F2-029409656A8C', 'uid': '197.164.165.154@123456789012347'}
《-----------
https://graph.qq.com/oauth2.0/show?which=Login&display=pc&scope=get_user_info%2Cadd_share%2Cadd_t%2Cadd_pic_t%2Cget_info%2Cget_other_info%2Cget_fanslist%2Cget_idollist%2Cadd_idol%2Cget_repost_list&state=b4a42c9cisQBYRjEAXCpcXpvbmVfc25zxAFzxADEAXICxAFkAMQBdgLEAWkAxAFoxA5hcGkuc25zc2RrLmNvbcQBbQDEAW7ZZmh0dHBzOi8vc3NvLnRvdXRpYW8uY29tL2F1dGgvbG9naW5fc3VjY2Vzcy8_c2VydmljZT1odHRwczovL21wLnRvdXRpYW8uY29tL3Nzb19jb25maXJtLz9yZWRpcmVjdF91cmw9Lw%3D%3D&redirect_uri=http%3A%2F%2Fapi.snssdk.com%2Fauth%2Flogin_success%2F&response_type=code&client_id=100290348

在header中指明按照json解释,在body中按照json格式形成字符串

import requests
import json
url = 'http://192.168.3.212:5001/v1.0/aliBridge/aliyunosstokengenerator'
headers = {'Content-Type': 'application/json'}
d = {
"ipv4": "197.164.165.154", "imei": "123456789012347", "kid": "ourServerKeyId", "ks": "ourServerKeyValue"
}
r=requests.post(url,data=json.dumps(d),headers=headers) print(r)
dd=9

  

def dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True,
allow_nan=True, cls=None, indent=None, separators=None,
default=None, sort_keys=False, **kw):
"""Serialize ``obj`` to a JSON formatted ``str``. If ``skipkeys`` is true then ``dict`` keys that are not basic types
(``str``, ``int``, ``float``, ``bool``, ``None``) will be skipped
instead of raising a ``TypeError``. If ``ensure_ascii`` is false, then the return value can contain non-ASCII
characters if they appear in strings contained in ``obj``. Otherwise, all
such characters are escaped in JSON strings. If ``check_circular`` is false, then the circular reference check
for container types will be skipped and a circular reference will
result in an ``OverflowError`` (or worse). If ``allow_nan`` is false, then it will be a ``ValueError`` to
serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in
strict compliance of the JSON specification, instead of using the
JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``). If ``indent`` is a non-negative integer, then JSON array elements and
object members will be pretty-printed with that indent level. An indent
level of 0 will only insert newlines. ``None`` is the most compact
representation. If specified, ``separators`` should be an ``(item_separator, key_separator)``
tuple. The default is ``(', ', ': ')`` if *indent* is ``None`` and
``(',', ': ')`` otherwise. To get the most compact JSON representation,
you should specify ``(',', ':')`` to eliminate whitespace. ``default(obj)`` is a function that should return a serializable version
of obj or raise TypeError. The default simply raises TypeError. If *sort_keys* is true (default: ``False``), then the output of
dictionaries will be sorted by key. To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
``.default()`` method to serialize additional types), specify it with
the ``cls`` kwarg; otherwise ``JSONEncoder`` is used. """
# cached encoder
if (not skipkeys and ensure_ascii and
check_circular and allow_nan and
cls is None and indent is None and separators is None and
default is None and not sort_keys and not kw):
return _default_encoder.encode(obj)
if cls is None:
cls = JSONEncoder
return cls(
skipkeys=skipkeys, ensure_ascii=ensure_ascii,
check_circular=check_circular, allow_nan=allow_nan, indent=indent,
separators=separators, default=default, sort_keys=sort_keys,
**kw).encode(obj)

  

201 Created - HTTP | MDN https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status/201

在HTTP协议中,201 Created 是一个代表成功的应答状态码,表示请求已经被成功处理,并且创建了新的资源。新的资源在应答返回之前已经被创建。同时新增的资源会在应答消息体中返回,其地址或者是原始请求的路径,或者是 Location 首部的值。

这个状态码的常规使用场景是作为 PUT 请求的返回值。

最新文章

  1. 【学习笔记】load-on-startup Servlet
  2. 原生js实现查询天气的小应用
  3. android 伸缩控件ExpandableListView 展开失败的可能原因。
  4. target=&quot;_blank&quot;
  5. 影响google PageRank的因素
  6. Pairing heap
  7. Java多线程 - 线程状态
  8. 学习PHP C扩展之面向对象开发方式 (转)
  9. ubuntu的vi
  10. 九度OJ 1385 重建二叉树
  11. y combinator 做的一个调查_可以学习一下
  12. 教你怎么用Mono Cecil - 动态注入 (注意代码的注释)
  13. Django: 之数据库导入、迁移和联用
  14. JAVAFX-3 开发应用
  15. 2018上C语言程序设计(高级)作业- 第1次作业
  16. DCGAN 代码简单解读
  17. DedeCMS清空删除所有文档后新建文档信息ID从1开始
  18. 错误: after element list
  19. (后端)Mybatis中#{}和${}传参的区别及#和$的区别小结(转)
  20. RMAN_RAC归档日志备份包恢复到单机

热门文章

  1. JS事件兼容性
  2. BZOJ3611 [Heoi2014]大工程 【虚树】
  3. uva 10090 二元一次不定方程
  4. java多线程编程核心技术学习-1
  5. POJ 2185 Milking Grid [二维KMP next数组]
  6. ctrl+c,ctrl+d,ctrl+z在linux程序中意义和区别
  7. I.Tower Defense
  8. Java下接口interface前面要不要加I
  9. java cocurrent并发包
  10. FIREDAC字段类型映射