素马网站建设费用差距,手机网站建设优势,陕西建设厅网站,58黄页目录 一 领域驱动二 UDDI三 SOA四 SAOP五 RPC六 gRPC七 MVC八 MVVM九 RestFul架构风格的特点1 什么是REST2 资源与URI3 统一资源接口4 资源的表述5 资源的链接6 状态的转移7 应用状态与资源状态8 应用状态的转移 十 ROA、SOA、REST与RPC1 概述2 本真REST与hybrid风格十 RestFul… 目录 一 领域驱动二 UDDI三 SOA四 SAOP五 RPC六 gRPC七 MVC八 MVVM九 RestFul架构风格的特点1 什么是REST2 资源与URI3 统一资源接口4 资源的表述5 资源的链接6 状态的转移7 应用状态与资源状态8 应用状态的转移 十 ROA、SOA、REST与RPC1 概述2 本真REST与hybrid风格十 RestFul认证机制1 Basic Auth2 Token Auth3 OAuth 十一 RESTful API 编写指南1 Request 和 Response2. Serialization 和 Deserialization3. Validation4. Authentication 和 Permission5. CORS6. URL Rules 一 领域驱动
二 UDDI
三 SOA 四 SAOP
五 RPC RPC 框架----- 远程过程调用协议RPCRemote Procedure Call Protocol)-----允许像调用本地服务一样调用远程服务。 v提到RPC就躲不开提到分布式这个促使RPC诞生的领域。 RPCRemote Produce Call 是一种技术的概念名词HTTP是一种协议,RPC可以通过 HTTP 来实现,也可以通过Socket自己实现一套协议来实现.所以题目可以换一种理解,为何 RPC 还有除 HTTP 之外的实现法,有何必要毕竟除了HTTP实现外,私有协议不具备通用性.领域驱动
六 gRPC 本节内容来自这里。 gRPC其实就是RPC框架的一种前面带了一个g代表是RPC中的大哥龙头老大的意思另外g也有global的意思意思是全球化比较fashion是一个高性能、开源和通用的 RPC 框架基于ProtoBuf(Protocol Buffers) 序列化协议开发且支持众多开发语言。面向服务端和移动端基于 HTTP/2 设计带来诸如双向流、流控、头部压缩、单 TCP 连接上的多复用请求等特。这些特性使得其在移动设备上表现更好更省电和节省空间占用。 在 gRPC 里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法使得您能够更容易地创建分布式应用和服务。与许多 RPC 系统类似gRPC 也是基于以下理念定义一个服务指定其能够被远程调用的方法包含参数和返回类型。在服务端实现这个接口并运行一个 gRPC 服务器来处理客户端调用。在客户端拥有一个存根能够像服务端一样的方法。
七 MVC MVC是一种设计模式 Model-View-Controller(模型-视图-控制器)单向数据绑定Model通过控制器将html渲染到视图 M(Model)模型层。是应用程序中用于处理应用程序数据逻辑的部分模型对象负责在数据库中存取数据 V(View)视图层。是应用程序中处理数据显示的部分视图是依据模型数据创建的 C(Controller)控制层。是应用程序中处理用户交互的部分控制器接受用户的输入并调用模型和视图去完成用户的需求控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求然后再确定用哪个视图来显示返回的数据。
八 MVVM MVVMModel-View-ViewModel(模型-视图-视图模型)双向数据绑定即数据驱动视图当数据改变时视图更新当视图的数据改变时model 也会改变只要关注业务逻辑不用手动操作DOM vue框架中MVVM的M就是后端的数据V就是节点树VM就是new出来的那个Vue({})对象 Vue2.0双向数据绑定实现原理Object.defineProperty Vue3.0双向数据绑定实现原理new Proxy M(Model)模型层。就是业务逻辑相关的数据对象通常从数据库映射而来我们可以说是与数据库对应的 model。 V(View)视图层。就是展现出来的用户界面。 VM(ViewModel)视图模型层。连接 view 和 model 的桥梁。因为Model层中的数据往往是不能直接跟 View 中的控件一一对应上的所以需要再定义一个数据对象专门对应 view 上的控件。而 ViewModel 的职责就是把 model 对象封装成可以显示和接受输入的界面数据对象。 View 与 ViewModel 之间通过双向绑定建立联系这样当 View(视图层) 变化时会自动更新到 ViewModel(视图模型)反之亦然。 MVVM的优势 1、mvc 和 mvvm 都是一种设计思想。 主要就是 mvc 中 Controller 演变成 mvvm 中的 viewModel 。mvvm 主要解决了 mvc 中大量DOM操作使页面渲染性能降低加载速度变慢的问题 。 2、MVVM 与 MVC 最大的区别就是它实现了 View 和 Model 的自动同步当 Model 的属性改变时我们不用再自己手动操作Dom元素来改变View的显示它会自动变化。 3、整体看来MVVM 比 MVC 精简很多我们不用再用选择器频繁地操作DOM。 MVVM 并不是用 VM 完全取代了 CViewModel 存在目的在于抽离 Controller 中展示的业务逻辑而不是替代 Controller其它视图操作业务等还是应该放在 Controller 中实现。
九 RestFul架构风格的特点
1 什么是REST REST全称是 Representational State Transfer中文意思是表述编者注通常译为表征性状态转移。 它首次出现在2000年Roy Fielding的博士论文中Roy Fielding是HTTP规范的主要编写者之一。 他在论文中提到“我这篇文章的写作目的就是想在符合架构原理的前提下理解和评估以网络为基础的应用软件的架构设计得到一个功能强、性能好、适宜通信的架构。REST指的是一组架构约束条件和原则。” 如果一个架构符合REST的约束条件和原则称它为RESTful架构。 REST本身并没有创造新的技术、组件或服务而隐藏在 RESTful 背后的理念就是使用 Web 的现有特征和能力 更好地使用现有Web标准中的一些准则和约束。虽然REST本身受Web技术的影响很深 但是理论上 REST 架构风格并不是绑定在HTTP上只不过目前 HTTP 是唯一与 REST 相关的实例。 所以我们这里描述的 REST 也是通过HTTP实现的REST。 从其诞生之日开始它就因其可扩展性和简单性受到越来越多的架构师和开发者们的青睐。一方面随着云计算和移动计算的兴起许多企业愿意在互联网上共享自己的数据、功能另一方面在企业中RESTful API也称RESTful Web服务也逐渐超越SOAP成为实现SOA的重要手段之一。时至今日RESTful架构风格已成为企业级服务的标配。 REST即Representational State Transfer的缩写可译为表现层状态转化”。REST最大的几个特点为资源、统一接口、URI和无状态。
2 资源与URI 要让一个资源可以被识别需要有个唯一标识在Web中这个唯一标识就是URI(Uniform Resource Identifier)。 URI既可以看成是资源的地址也可以看成是资源的名称。 使用_或-来让URI可读性更好。 使用/来表示资源的层级关系。 使用?用来过滤资源。 ,或;可以用来表示同级资源的关系。
3 统一资源接口 RESTful架构风格规定数据的元操作即CRUD(create, read, update和delete,即数据的增删查改)操作分别对应于HTTP方法GET用来获取资源POST用来新建资源也可以用于更新资源PUT用来更新资源DELETE用来删除资源这样就统一了数据操作的接口仅通过HTTP方法就可以完成对数据的所有增删查改工作。 RESTful架构应该遵循统一接口原则统一接口包含了一组受限的预定义的操作不论什么样的资源都是通过使用相同的接口进行资源的访问。接口应该使用标准的HTTP方法如GETPUT和POST并遵循这些方法的语义。 如果按照HTTP方法的语义来暴露资源那么接口将会拥有安全性和幂等性的特性例如GET和HEAD请求都是安全的 无论请求多少次都不会改变服务器状态。而GET、HEAD、PUT和DELETE请求都是幂等的无论对资源操作多少次 结果总是一样的后面的请求并不会产生比第一次更多的影响。 下面列出了GETDELETEPUT和POST的典型用法: 1、GET
安全且幂等获取表示变更时获取表示缓存200OK - 表示已在响应中发出204无内容 - 资源有空表示301Moved Permanently - 资源的URI已被更新303See Other - 其他如负载均衡304not modified- 资源未更改缓存400 bad request- 指代坏请求如参数错误404 not found- 资源不存在406 not acceptable- 服务端不支持所需表示500 internal server error- 通用错误响应503 Service Unavailable- 服务端当前无法处理请求 2、POST
不安全且不幂等使用服务端管理的自动产生的实例号创建资源创建子资源部分更新资源如果没有被修改则不过更新资源乐观锁200OK- 如果现有资源已被更改201created- 如果新资源被创建202accepted- 已接受处理请求但尚未完成异步处理301Moved Permanently- 资源的URI被更新303See Other- 其他如负载均衡400bad request- 指代坏请求404 not found- 资源不存在406 not acceptable- 服务端不支持所需表示409 conflict- 通用冲突412 Precondition Failed- 前置条件失败如执行条件更新时的冲突415 unsupported media type- 接受到的表示不受支持500 internal server error- 通用错误响应503 Service Unavailable- 服务当前无法处理请求 3、PUT
不安全但幂等用客户端管理的实例号创建一个资源通过替换的方式更新资源如果未被修改则更新资源乐观锁200 OK- 如果已存在资源被更改201 created- 如果新资源被创建301Moved Permanently- 资源的URI已更改303 See Other- 其他如负载均衡400 bad request- 指代坏请求404 not found- 资源不存在406 not acceptable- 服务端不支持所需表示409 conflict- 通用冲突412 Precondition Failed- 前置条件失败如执行条件更新时的冲突415 unsupported media type- 接受到的表示不受支持500 internal server error- 通用错误响应503 Service Unavailable- 服务当前无法处理请求 4、DELETE
不安全但幂等删除资源200 OK- 资源已被删除301 Moved Permanently- 资源的URI已更改303 See Other- 其他如负载均衡400 bad request- 指代坏请求404 not found- 资源不存在409 conflict- 通用冲突500 internal server error- 通用错误响应503 Service Unavailable- 服务端当前无法处理请求 下面我们来看一些实践中常见的问题: POST和PUT用于创建资源时有什么区别 POST和PUT在创建资源的区别在于所创建的资源的名称(URI)是否由客户端决定。 例如为我的博文增加一个java的分类生成的路径就是分类名/categories/java那么就可以采用PUT方法。不过很多人直接把POST、GET、PUT、DELETE直接对应上CRUD例如在一个典型的rails实现的RESTful应用中就是这么做的。 我认为这是因为rails默认使用服务端生成的ID作为URI的缘故而不少人就是通过rails实践REST的所以很容易造成这种误解。 客户端不一定都支持这些HTTP方法吧 的确有这种情况特别是一些比较古老的基于浏览器的客户端只能支持GET和POST两种方法。 在实践上客户端和服务端都可能需要做一些妥协。例如rails框架就支持通过隐藏参数_methodDELETE来传递真实的请求方法 而像Backbone这样的客户端MVC框架则允许传递_method传输和设置X-HTTP-Method-Override头来规避这个问题。 统一接口是否意味着不能扩展带特殊语义的方法 统一接口并不阻止你扩展方法只要方法对资源的操作有着具体的、可识别的语义即可并能够保持整个接口的统一性。 像WebDAV就对HTTP方法进行了扩展增加了LOCK、UPLOCK等方法。而github的API则支持使用PATCH方法来进行issue的更新例如:PATCH /repos/:owner/:repo/issues/:number 不过需要注意的是像PATCH这种不是HTTP标准方法的服务端需要考虑客户端是否能够支持的问题。 统一资源接口对URI有什么指导意义 统一资源接口要求使用标准的HTTP方法对资源进行操作所以URI只应该来表示资源的名称而不应该包括资源的操作。 通俗来说URI不应该使用动作来描述。例如下面是一些不符合统一接口要求的URI:
GET /getUser/1
POST /createUser
PUT /updateUser/1
DELETE /deleteUser/1如果GET请求增加计数器这是否违反安全性 安全性不代表请求不产生副作用例如像很多API开发平台都对请求流量做限制。像github就会限制没有认证的请求每小时只能请求60次。 但客户端不是为了追求副作用而发出这些GET或HEAD请求的产生副作用是服务端“自作主张”的。 另外服务端在设计时也不应该让副作用太大因为客户端认为这些请求是不会产生副作用的。 直接忽视缓存可取吗 即使你按各个动词的原本意图来使用它们你仍可以轻易禁止缓存机制。 最简单的做法就是在你的HTTP响应里增加这样一个报头 Cache-control: no-cache。 但是同时你也对失去了高效的缓存与再验证的支持(使用Etag等机制)。 对于客户端来说在为一个REST式服务实现程序客户端时也应该充分利用现有的缓存机制以免每次都重新获取表示。 响应代码的处理有必要吗 HTTP的响应代码可用于应付不同场合正确使用这些状态代码意味着客户端与服务器可以在一个具备较丰富语义的层次上进行沟通。 例如201“Created”响应代码表明已经创建了一个新的资源其URI在Location响应报头里。 假如你不利用HTTP状态代码丰富的应用语义那么你将错失提高重用性、增强互操作性和提升松耦合性的机会。 如果这些所谓的RESTful应用必须通过响应实体才能给出错误信息那么SOAP就是这样的了它就能够满足了。
4 资源的表述 上面提到客户端通过HTTP方法可以获取资源是吧? 不确切的说客户端获取的只是资源的表述而已。 资源在外界的具体呈现可以有多种表述(或成为表现、表示)形式在客户端和服务端之间传送的也是资源的表述而不是资源本身。 例如文本资源可以采用html、xml、json等格式图片可以使用PNG或JPG展现出来。 资源的表述包括数据和描述数据的元数据例如HTTP头“Content-Type” 就是这样一个元数据属性。 那么客户端如何知道服务端提供哪种表述形式呢 答案是可以通过HTTP内容协商客户端可以通过Accept头请求一种特定格式的表述服务端则通过Content-Type告诉客户端资源的表述形式。 以github为例请求某组织资源的json格式的表述形式: 假如github也能够支持xml格式的表述格式那么结果就是这样的: 下面我们来看一些实践上常见的设计: 在URI里边带上版本号 有些API在URI里边带上版本号例如:
http://api.example.com/1.0/foo
http://api.example.com/1.2/foo
http://api.example.com/2.0/foo如果我们把版本号理解成资源的不同表述形式的话就应该只是用一个URL并通过Accept头部来区分还是以github为例它的Accept的完整格式是:application/vnd.github[.version].param[json] 对于v3版本的话就是Accept: application/vnd.github.v3。对于上面的例子同理可以使用使用下面的头部:
Accept: vnd.example-com.foojson; version1.0
Accept: vnd.example-com.foojson; version1.2
Accept: vnd.example-com.foojson; version2.0使用URI后缀来区分表述格式 像rails框架就支持使用/users.xml或/users.json来区分不同的格式。 这样的方式对于客户端来说无疑是更为直观但混淆了资源的名称和资源的表述形式。 我个人认为还是应该优先使用内容协商来区分表述格式。 如何处理不支持的表述格式 当服务器不支持所请求的表述格式那么应该怎么办若服务器不支持它应该返回一个HTTP 406响应表示拒绝处理该请求。下面以github为例展示了一个请求XML表述资源的结果
5 资源的链接 我们知道REST是使用标准的HTTP方法来操作资源的但仅仅因此就理解成带CURD的Web数据库架构就太过于简单了。 这种反模式忽略了一个核心概念“超媒体即应用状态引擎hypermedia as the engine of application state”。 超媒体是什么? 当你浏览Web网页时从一个连接跳到一个页面再从另一个连接跳到另外一个页面就是利用了超媒体的概念把一个个把资源链接起来. 要达到这个目的就要求在表述格式里边加入链接来引导客户端。在《RESTful Web Services》一书中作者把这种具有链接的特性成为连通性。下面我们具体来看一些例子。 下面展示的是github获取某个组织下的项目列表的请求可以看到在响应头里边增加Link头告诉客户端怎么访问下一页和最后一页的记录。 而在响应体里边用url来链接项目所有者和项目地址。 又例如下面这个例子创建订单后通过链接引导客户端如何去付款。 上面的例子展示了如何使用超媒体来增强资源的连通性。很多人在设计RESTful架构时使用很多时间来寻找漂亮的URI而忽略了超媒体。所以应该多花一些时间来给资源的表述提供链接而不是专注于“资源的CRUD”。
6 状态的转移 有了上面的铺垫再讨论REST里边的状态转移就会很容易理解了。 不过我们先来讨论一下REST原则中的无状态通信原则。初看一下好像自相矛盾了既然无状态何来状态转移一说? 其实这里说的无状态通信原则并不是说客户端应用不能有状态而是指服务端不应该保存客户端状态。
7 应用状态与资源状态 实际上状态应该区分应用状态和资源状态客户端负责维护应用状态而服务端维护资源状态。 客户端与服务端的交互必须是无状态的并在每一次请求中包含处理该请求所需的一切信息。 服务端不需要在请求间保留应用状态只有在接受到实际请求的时候服务端才会关注应用状态。 这种无状态通信原则使得服务端和中介能够理解独立的请求和响应。 在多次请求中同一客户端也不再需要依赖于同一服务器方便实现高可扩展和高可用性的服务端。 但有时候我们会做出违反无状态通信原则的设计例如利用Cookie跟踪某个服务端会话状态常见的像J2EE里边的JSESSIONID。 这意味着浏览器随各次请求发出去的Cookie是被用于构建会话状态的。 当然如果Cookie保存的是一些服务器不依赖于会话状态即可验证的信息比如认证令牌这样的Cookie也是符合REST原则的。 所谓无状态的即所有的资源都可以通过URI定位而且这个定位与其他资源无关也不会因为其他资源的变化而改变。有状态和无状态的区别举个简单的例子说明一下。如查询员工的工资如果查询工资是需要登录系统进入查询工资的页面执行相关操作后获取工资的多少则这种情况是有状态的因为查询工资的每一步操作都依赖于前一步操作只要前置操作不成功后续操作就无法执行如果输入一个url即可得到指定员工的工资则这种情况是无状态的因为获取工资不依赖于其他资源或状态且这种情况下员工工资是一个资源由一个url与之对应可以通过HTTP中的GET方法得到资源这是典型的RESTful风格。
8 应用状态的转移 状态转移到这里已经很好理解了 “会话”状态不是作为资源状态保存在服务端的而是被客户端作为应用状态进行跟踪的。客户端应用状态在服务端提供的超媒体的指引下发生变迁。服务端通过超媒体告诉客户端当前状态有哪些后续状态可以进入。 这些类似“下一页”之类的链接起的就是这种推进状态的作用——指引你如何从当前状态进入下一个可能的状态。
十 ROA、SOA、REST与RPC
1 概述 ROA即Resource Oriented ArchitectureRESTful 架构风格的服务是围绕资源展开的是典型的ROA架构虽然“A”和“架构”存在重复但说无妨虽然ROA与SOA并不冲突甚至把ROA看做SOA的一种也未尝不可但由于RPC也是SOA比较久远一点点论文、博客或图书也常把SOA与RPC混在一起讨论因此RESTful 架构风格的服务通常被称之为ROA架构很少提及SOA架构以便更加显式的与RPC区分。 RPC风格曾是Web Service的主流最初是基于XML-RPC协议一个远程过程调用remote procedure callRPC)的分布式计算协议后来渐渐被SOAP协议简单对象访问协议Simple Object Access Protocol取代RPC风格的服务不仅可以用HTTP还可以用TCP或其他通信协议。但RPC风格的服务受开发服务采用语言的束缚比较大如.NET框架中开发web service的传统方式是使用WCF基于WCF开发的服务即RPC风格的服务使用该服务的客户端通常要用C#来实现如果使用python或其他语言很难实现可以直接与服务通信客户端进入移动互联网时代后RPC风格的服务很难在移动终端使用而RESTful风格的服务由于可以直接以json或xml为载体承载数据以HTTP方法为统一接口完成数据操作客户端的开发不依赖于服务实现的技术移动终端也可以轻松使用服务这也加剧了REST取代RPC成为web service的主导。 RPC与RESTful的区别如下面两个图所示
2 本真REST与hybrid风格 通常开发者做服务相关的客户端开发时使用的所谓RESTful服务基本可分为本真REST和hybrid风格两类。本真REST即我上文阐述的RESTful架构风格具有上述的4个特点是真正意义上的RESTful风格而hybrid风格只是借鉴了RESTful的一些优点具有一部分RESTful的特点但对外依然宣称是RESTful风格的服务。窃以为正是由于hybrid风格服务混淆了RESTful的概念才在RESTful架构风格提出了本真REST的概念以为了划分界限 hybrid风格的最主流的用法是使用GET方法获取资源用POST方法实现资源的创建、修改和删除。hybrid风格之所以存在据我了解有两种来源一种情况是因为某些开发者并没有真正理解何为RESTful架构风格导致开发的服务貌合神离而主流的原因是由于历史包袱 —— 服务本来是RPC风格的由于上文提到的RPC的劣势及RESTful的优势开发者在RPC风格的服务上又包装了一层RESTful的外壳通常这层外壳只为获取资源服务因此会按RESTful风格实现GET方法如果客户端提出一些简单的创建、修改或删除数据的需求则通过HTTP协议中最常用的POST方法实现相应功能。 因此开发RESTful 服务如果没有历史包袱不建议使用hybrid风格。
十 RestFul认证机制 认证机制解决的问题是确定访问资源的用户是谁权限机制解决的问题是确定用户是否被许可使用、修改、删除或创建资源。权限机制通常与服务的业务逻辑绑定因此权限机制需要在每个系统内部定制而认证机制基本上是通用的常用的认证机制包括session auth(即通过用户名密码登录)basic authtoken auth和OAuth服务开发中常用的认证机制为后三者。
1 Basic Auth HTTP Basic authentication (BA) implementation is the simplest technique for enforcing access controls to web resources because it doesn’t require cookies, session identifier and login pages. Rather, HTTP Basic authentication uses static, standard fields in the HTTP header which means that no handshakes have to be done in anticipation. Visit Wikipedia To Read More 简言之Basic Auth是配合RESTful API 使用的最简单的认证方式只需提供用户名密码即可但由于有把用户名密码暴露给第三方客户端的风险在生产环境下被使用的越来越少。因此在开发对外开放的RESTful API时尽量避免采用Basic Auth
2 Token Auth Token Auth并不常用它与Basic Auth的区别是不将用户名和密码发送给服务器做用户认证而是向服务器发送一个事先在服务器端生成的token来做认证。因此Token Auth要求服务器端要具备一套完整的Token创建和管理机制该机制的实现会增加大量且非必须的服务器端开发工作也不见得这套机制足够安全和通用因此Token Auth用的并不多。 本文不在展开介绍Token Auth我个人对这套机制也了解有限有兴趣了解这套机制的同学不妨从Stack Overflow上的这篇讨论入手。
3 OAuth OAuth is an open standard for authorization. OAuth provides client applications a ‘secure delegated access’ to server resources on behalf of a resource owner. It specifies a process for resource owners to authorize third-party access to their server resources without sharing their credentials. Designed specifically to work with Hypertext Transfer Protocol (HTTP), OAuth essentially allows access tokens to be issued to third-party clients by an authorization server, with the approval of the resource owner. The client then uses the access token to access the protected resources hosted by the resource server. OAuth is commonly used as a way for Internet users to log into third party websites using their Microsoft, Google, Facebook or Twitter accounts without exposing their password. OAuth is a service that is complementary to and distinct from OpenID. OAuth is also distinct from OATH, which is a reference architecture for authentication, not a standard for authorization. However, OAuth is directly related to OpenID Connect (OIDC) since OIDC is an authentication layer built on top of OAuth 2.0. Visit Wikipedia To Read More OAuth开放授权是一个开放的授权标准允许用户让第三方应用访问该用户在某一web服务上存储的私密的资源如照片视频联系人列表而无需将用户名和密码提供给第三方应用。 OAuth允许用户提供一个令牌而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的第三方系统例如视频编辑网站)在特定的时段例如接下来的2小时内内访问特定的资源例如仅仅是某一相册中的视频。这样OAuth让用户可以授权第三方网站访问他们存储在另外服务提供者的某些特定信息而非所有内容。 正是由于OAUTH的严谨性和安全性现在OAUTH已成为RESTful架构风格中最常用的认证机制和RESTful架构风格一起成为企业级服务的标配。 目前OAuth已经从OAuth1.0发展到OAuth2.0但这二者并非平滑过渡升级OAuth2.0在保证安全性的前提下大大减少了客户端开发的复杂性因此Gevin建议在实战应用中采用OAuth2.0认证机制。 现在网上关于OAuth的资料非常丰富也有大量开源的第三方库实现了OAuth机制不熟悉OAuth的同学从OAuth官网入手即可。
十一 RESTful API 编写指南 本节内容来自这里。
1 Request 和 Response RESTful API的开发和使用无非是客户端向服务器发请求request以及服务器对客户端请求的响应response。本真RESTful架构风格具有统一接口的特点即使用不同的http方法表达不同的行为
GETSELECT从服务器取出资源一项或多项POSTCREATE在服务器新建一个资源PUTUPDATE在服务器更新资源客户端提供完整资源数据PATCHUPDATE在服务器更新资源客户端提供需要修改的资源数据DELETEDELETE从服务器删除资源 客户端会基于GET方法向服务器发送获取数据的请求基于PUT或PATCH方法向服务器发送更新数据的请求等服务端在设计API时也要按照相应规范来处理对应的请求这点现在应该已经成为所有RESTful API的开发者的共识了而且各web框架的request类和response类都很强大具有合理的默认设置和灵活的定制性Gevin在这里仅准备强调一下响应这些request时常用的Response要包含的数据和状态码status code不完善的内容欢迎大家补充:
当GET, PUT和PATCH请求成功时要返回对应的数据及状态码200即SUCCESS当POST创建数据成功时要返回创建的数据及状态码201即CREATED当DELETE删除数据成功时不返回数据状态码要返回204即NO CONTENT当GET 不到数据时状态码要返回404即NOT FOUND任何时候如果请求有问题如校验请求数据时发现错误要返回状态码 400即BAD REQUEST当API 请求需要用户认证时如果request中的认证信息不正确要返回状态码 401即NOT AUTHORIZED当API 请求需要验证用户权限时如果当前用户无相应权限要返回状态码 403即FORBIDDEN 最后关于Request 和 Response不要忽略了http header中的Content-Type。以json为例如果API要求客户端发送request时要传入json数据则服务器端仅做好json数据的获取和解析即可但如果服务端支持多种类型数据的传入如同时支持json和form-data则要根据客户端发送请求时header中的Content-Type对不同类型是数据分别实现获取和解析如果API响应客户端请求后需要返回json数据需要在header中添加Content-Typeapplication/json。
2. Serialization 和 Deserialization Serialization 和 Deserialization即序列化和反序列化。RESTful API以规范统一的格式作为数据的载体常用的格式为json或xml以json格式为例当客户端向服务器发请求时或者服务器相应客户端的请求向客户端返回数据时都是传输json格式的文本而在服务器内部数据处理时基本不用json格式的字符串而是native类型的数据最典型的如类的实例即对象objectjson仅为服务器和客户端通信时在网络上传输的数据的格式服务器和客户端内部均存在将json转为native类型数据和将native类型数据转为json的需求其中将native类型数据转为json即为序列化将json转为native类型数据即为反序列化。虽然某些开发语言如Python其原生数据类型list和dict能轻易实现序列化和反序列化但对于复杂的API内部实现时总会以对象作为数据的载体因此确保序列化和反序列化方法的实现是开发RESTful API最重要的一步准备工作 题外话序列化和反序列化的便捷造就了RESTful API跨平台的特点使得REST取代RPC成为Web Service的主流 序列化和反序列化是RESTful API开发中的一项硬需求所以几乎每一种常用的开发语言都会有一个或多个优秀的开源库来实现序列化和反序列化因此我们在开发RESTful API时没必要制造重复的轮子选一个好用的库即可如python中的marshmallow如果基于Django开发Django REST Framework中的serializer即可。
3. Validation Validation即数据校验是开发健壮RESTful API中另一个重要的一环。仍以json为例当客户端向服务器发出post, put或patch请求时通常会同时给服务器发送json格式的相关数据服务器在做数据处理之前先做数据校验是最合理和安全的前后端交互。如果客户端发送的数据不正确或不合理服务器端经过校验后直接向客户端返回400错误及相应的数据错误信息即可。常见的数据校验包括
数据类型校验如字段类型如果是int那么给字段赋字符串的值则报错数据格式校验如邮箱或密码其赋值必须满足相应的正则表达式才是正确的输入数据数据逻辑校验如数据包含出生日期和年龄两个字段如果这两个字段的数据不一致则数据校验失败 以上三种类型的校验数据逻辑校验最为复杂通常涉及到多个字段的配合或者要结合用户和权限做相应的校验。Validation虽然是RESTful API 编写中的一个可选项但它对API的安全、服务器的开销和交互的友好性而言都具有重要意义因此Gevin建议开发一套完善的RESTful API时Validation的实现必不可少。
4. Authentication 和 Permission Authentication指用户认证Permission指权限机制这两点是使RESTful API 强大、灵活和安全的基本保障。 常用的认证机制是Basic Auth和OAuthRESTful API 开发中除非API非常简单且没有潜在的安全性问题否则认证机制是必须实现的并应用到API中去。Basic Auth非常简单很多框架都集成了Basic Auth的实现自己写一个也能很快搞定OAuth目前已经成为企业级服务的标配其相关的开源实现方案非常丰富更多。 我在《RESTful 架构风格概述》中对认证机制做了更加详细的描述有兴趣的同学不妨阅读相关章节。 权限机制是对API请求更近一步的限制只有通过认证的用户符合权限要求才能访问API。权限机制的具体实现通常依赖于系统的业务逻辑和应用场景generally speaking常用的权限机制主要包含全局型的和对象型的全局型的权限机制主要指通过为用户赋予权限或者为用户赋予角色或划分到用户组然后为角色或用户组赋予权限的方式来实现权限控制对象型的权限机制主要指权限控制的颗粒度在object上用户对某个具体对象的访问、修改、删除或其行为要单独在该对象上为用户赋予相关权限来实现权限控制。 全局型的权限机制容易理解实现也简单有很多开源库可做备选方案不少完善的web开发框架也会集成相关的权限逻辑object permission 相对难复杂一点但也有很多典型的应用场景如多人博客系统中作者对自己文章的编辑权限即为object permission其对应的开源库也有很多。 注 我写过一篇《Django权限机制的实现》Django 开发者可做延伸阅读。 开发一套完整的RESTful API权限机制必须纳入考虑范围虽然权限机制的具体实现依赖于业务权限机制本身是有典型的模式存在的需要开发者掌握基本的权限机制实现方案以便随时应用到API中去。
5. CORS CORS即Cross-origin resource sharing在RESTful API开发中主要是为js服务的解决javascript 调用 RESTful API时的跨域问题。 由于固有的安全机制js的跨域请求时是无法被服务器成功响应的。现在前后端分离日益成为web开发主流方式的大趋势下后台逐渐趋向指提供API服务为各客户端提供数据及相关操作而网站的开发全部交给前端搞定网站和API服务很少部署在同一台服务器上并使用相同的端口js的跨域请求时普遍存在的开发RESTful API时通常都要考虑到CORS功能的实现以便js能正常使用API。 目前各主流web开发语言都有很多优秀的实现CORS的开源库我们在开发RESTful API时要注意CORS功能的实现直接拿现有的轮子来用即可。 更多关于CORS的介绍有兴趣的同学可以查看阮一峰老师的跨域资源共享 CORS 详解
6. URL Rules RESTful API 是写给开发者来消费的其命名和结构需要有意义。因此在设计和编写URL时要符合一些规范。Url rules 可以单独写一篇博客来详细阐述本文只列出一些关键点。 6.1 Version your API 规范的API应该包含版本信息在RESTful API中最简单的包含版本的方法是将版本信息放到url中如
/api/v1/posts/
/api/v1/drafts//api/v2/posts/
/api/v2/drafts/另一种优雅的做法是使用HTTP header中的accept来传递版本信息这也是GitHub API 采取的策略。 6.2 Use nouns, not verbs RESTful API 中的url是指向资源的而不是描述行为的因此设计API时应使用名词而非动词来描述语义否则会引起混淆和语义不清。即
# Bad APIs
/api/getArticle/1/
/api/updateArticle/1/
/api/deleteArticle/1/上面四个url都是指向同一个资源的虽然一个资源允许多个url指向它但不同的url应该表达不同的语义上面的API可以优化为
# Good APIs
/api/Article/1/article 资源的获取、更新和删除分别通过 GET, PUT 和 DELETE方法请求API即可。试想如果url以动词来描述用PUT方法请求 /api/deleteArticle/1/ 会感觉多么不舒服。 6.3 GET and HEAD should always be safe RFC2616已经明确指出GET和HEAD方法必须始终是安全的。例如有这样一个不规范的API:
# The following api is used to delete articles
# [GET]
/api/deleteArticle?id1试想如果搜索引擎访问了上面url会如何 6.4 Nested resources routing 如果要获取一个资源子集采用 nested routing 是一个优雅的方式如列出所有文章中属于Gevin编写的文章
# List Gevins articles
/api/authors/gevin/articles/获取资源子集的另一种方式是基于filter见下面章节这两种方式都符合规范但语义不同如果语义上将资源子集看作一个独立的资源集合则使用 nested routing 感觉更恰当如果资源子集的获取是出于过滤的目的则使用filter更恰当。 至于编写RESTful API时到底应采用哪种方式则仁者见仁智者见智语义上说的通即可。 6.5 Filter 对于资源集合可以通过url参数对资源进行过滤如
# List Gevins articles
/api/articles?authorgevin分页就是一种最典型的资源过滤。 6.6 Pagination 对于资源集合分页获取是一种比较合理的方式。如果基于开发框架如Django REST Framework直接使用开发框架中的分页机制即可如果是自己实现分页机制Gevin的策略是 返回资源集合是包含与分页有关的数据如下
{page: 1, # 当前是第几页pages: 3, # 总共多少页per_page: 10, # 每页多少数据has_next: true, # 是否有下一页数据has_prev: false, # 是否有前一页数据total: 27 # 总共多少数据
}当想API请求资源集合时可选的分页参数为 参数 含义 page 当前是第几页默认为1 per_page 每页多少条记录默认为系统默认值 另外系统内还设置一个per_page_max字段用于标记系统允许的每页最大记录数当per_page值大于 per_page_max 值时每页记录条数为 per_page_max。 6.7 Url design tricks 1Url是区分大小写的这点经常被忽略即
/Posts /posts
上面这两个url是不同的两个url可以指向不同的资源 2Back forward Slash (/) 目前比较流行的API设计方案通常建议url以/作为结尾如果API GET请求中url不以/结尾则重定向到以/结尾的API上去这点现在的web框架基本都支持因为有没有 /也是两个url即
/posts/ /posts
这也是两个不同的url可以对应不同的行为和资源 3连接符 - 和 下划线 _ RESTful API 应具备良好的可读性当url中某一个片段segment由多个单词组成时建议使用 - 来隔断单词而不是使用 _即
# Good
/api/featured-post/# Bad
/api/featured_post/这主要是因为浏览器中超链接显示的默认效果是文字并附带下划线如果API以_隔断单词二者会重叠影响可读性。 总结 编写本文的初衷是为了整理一套从零开始编写规范、安全的RESTful API的基本思路。本文介绍了开发RESTful API时要考虑的基本内容对于类似Flask这种天生支持RESTful风格的web框架不依赖其他RESTful第三方库开发RESTful 服务时可以从本文内容入手不少强大的RESTful 库虽然其相关接口基本涵盖了本文的全部或大部分内容但本文的总结相信对这些库的理解和使用也是有帮助的。 https://blog.csdn.net/wl_1013/article/details/81049691