ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

在 Go 中实现 RESTful 架构:从资源模型到 httprouter 实战(build-web-application-with-golang 第 8.3 节)

在 Go 中实现 RESTful 架构:从资源模型到 httprouter 实战(build-web-application-with-golang 第 8.3 节) 文档教程【免费下载链接】build-web-application-with-golangA golang ebook intro how to build a web with golang项目地址https://gitcode.com/gh_mirrors/bu/build-web-application-with-golang点击查看免费下载RESTREpresentational State Transfer是当今互联网最流行的软件架构风格之一它以资源为中心、充分利用 HTTP 协议与 URI 约定提供了清晰统一的接口定义。本篇指南基于《build-web-application-with-golang》第 8.3 节的内容系统讲解 REST 的三大核心概念、无状态与分层两大架构原则并给出基于net/http与httprouter在 Go 中落地 RESTful 服务的完整可运行示例读完即可在自己的 Go Web 项目中按 HTTP 方法组织资源处理逻辑。什么是 REST三个核心概念REST 这一概念首次出现在 2000 年 Roy Thomas Fielding 的博士论文中他是 HTTP 规范的主要编写者之一。REST 指的是一组架构约束条件和原则满足这些约束条件和原则的应用程序或设计就是 RESTful 的。要理解 REST需要先理解下面三个概念资源ResourcesREST 的中文译名是表现层状态转化其实它省略了主语——表现层指的是资源的表现层。那么什么是资源就是我们上网访问的一张图片、一个文件、一个视频等具体实体。这些资源通过 URI 来定位一个 URI 就代表一个资源。表现层Representation资源是一个具体的实体信息它可以有多种展现方式而把实体展现出来就是表现层。例如一个 txt 文本信息可以输出成 html、json、xml 等格式一张图片可以用 jpg、png 等方式展现。URI 确定了一个资源但如何确定它的具体表现形式呢答案在 HTTP 请求的头部信息中用Accept和Content-Type字段指定这两个字段才是对表现层的描述。状态转化State Transfer访问一个网站就代表了客户端和服务器的一次交互过程这个过程中必然涉及数据和状态的改变。HTTP 协议本身是无状态的这些状态必须保存在服务器端因此客户端想要通知服务器端改变数据和状态就必须通过某种方式传达。客户端能通知服务器端的唯一手段就是 HTTP 协议具体来说是 HTTP 协议中四个表示操作方式的动词HTTP 动词对应操作GET取得读取资源POST建立资源也可以用于更新资源PUT更新资源DELETE删除资源RESTful 架构的三条核心约定综合上面的解释可以总结出 RESTful 架构的三条约定每一个 URI 代表一种资源客户端和服务器之间传递这种资源的某种表现层客户端通过四个 HTTP 动词对服务器端资源进行操作实现表现层状态转化。REST 的两条关键架构原则Web 应用要满足 REST最重要的原则是客户端和服务器之间的交互在请求之间是无状态的即从客户端到服务器的每个请求都必须包含理解该请求所必需的完整信息。由此带来三个直接收益如果服务器在请求之间的任何时间点重启客户端不会得到通知也不需要感知——服务可以随时水平替换同一个请求可以由任何一台可用服务器回答这种特性非常适合云计算之类的环境因为无状态客户端可以缓存数据以改进性能。另一个重要的 REST 原则是系统分层组件无法了解与它直接交互的层次以外的组件。通过将系统知识限制在单个层可以限制整个系统的复杂度从而促进底层组件的独立性。下图为 REST 的架构图清晰展示了 API Front-End表现层 Representation、Business Logic状态转化 State/Transfer与 Data资源 Resource三层之间通过请求/响应闭环协作的关系图 8.5 REST 架构图当 REST 架构的约束条件作为一个整体应用时将产生一个可以扩展到大量客户端的应用程序还能降低客户端与服务器之间的交互延迟。统一接口简化了整个系统架构改进了子系统之间交互的可见性REST 简化了客户端和服务器的实现基于 REST 开发的应用程序也更容易扩展。下图展示了 REST 的可扩展性——前端负载均衡器Front Load Balancer可将请求分发到多个并行的 API Front-End 实例业务逻辑层同样可以横向扩展最终共享统一的数据层图 8.6 REST 的可扩展性RESTful 的实现Go 语言实战Go 对 REST 的支持现状与实现思路Go 语言本身没有为 REST 提供直接支持。但 RESTful 完全建立在 HTTP 协议之上因此我们可以利用标准库net/http自行实现只需要针对 REST 做相应的改造。REST 的核心是根据不同的 HTTP method 处理同一个资源的相应逻辑。从 zh-tw/03.4.md 中关于 HTTP 路由的讲解可知Go 的http.ListenAndServe第二个参数就是用以配置外部路由器的它是一个Handler接口——外部路由器只要实现了Handler接口即具备ServeHTTP方法就可以接入我们可以在自定义路由器的ServeHTTP中实现自定义路由功能。这正是 RESTful 实现在 Go 中可行的基础。REST 实现的 Level 分级目前很多自称 REST 的应用其实并没有真正实现 REST。根据实现的 HTTP method 多少可以将这些应用划分为几个级别见下图图 8.7 REST 的 Level 分级上图展示了目前实现 REST 的三个 levelLevel 0 仅支持GETLevel 1 支持GET与POSTLevel 2 则完整支持GET、POST、PUT、DELETE等标准 HTTP 方法。在应用开发时我们也不一定非要完全按照 RESTful 的规则实现全部方式因为有些场景完全按 RESTful 方式未必可行。RESTful 服务要充分利用每一个 HTTP 方法包括DELETE和PUT但现实中 HTTP 客户端往往只能发出GET和POST请求HTML 标准的限制HTML 标准只能通过链接和表单支持GET和POST在没有 Ajax 支持的网页浏览器中无法发出PUT或DELETE命令防火墙的限制有些防火墙会拦截 HTTPPUT和DELETE请求。要绕过这个限制客户端需要把实际的PUT、DELETE请求通过POST请求穿透过来RESTful 服务则要负责在收到的POST请求中找到原始的 HTTP 方法并还原。用_method隐藏字段模拟 PUT/DELETE一个常见的过渡方案是在POST请求里增加一个隐藏字段_method来模拟PUT、DELETE等方法服务器端负责把_method字段转换为对应的真实方法。原书作者也提到其实际项目正是按照这种方式实现 REST 接口的。这种做法的优点是对老式浏览器与受限网络环境友好代价是服务器端需要多做一次方法转换。当然在 Go 语言里完全按照 RESTful 标准实现是很容易的下面通过一个完整示例来说明如何设计 RESTful 应用。基于 httprouter 的完整 REST 示例原书使用第三方库github.com/julienschmidt/httprouter实现自定义路由与便捷的路由规则映射。完整代码如下package main import ( fmt log net/http github.com/julienschmidt/httprouter ) func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { fmt.Fprint(w, Welcome!\n) } func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { fmt.Fprintf(w, hello, %s!\n, ps.ByName(name)) } func getuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { uid : ps.ByName(uid) fmt.Fprintf(w, you are get user %s, uid) } func modifyuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { uid : ps.ByName(uid) fmt.Fprintf(w, you are modify user %s, uid) } func deleteuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { uid : ps.ByName(uid) fmt.Fprintf(w, you are delete user %s, uid) } func adduser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { // uid : r.FormValue(uid) uid : ps.ByName(uid) fmt.Fprintf(w, you are add user %s, uid) } func main() { router : httprouter.New() router.GET(/, Index) router.GET(/hello/:name, Hello) router.GET(/user/:uid, getuser) router.POST(/adduser/:uid, adduser) router.DELETE(/deluser/:uid, deleteuser) router.PUT(/moduser/:uid, modifyuser) log.Fatal(http.ListenAndServe(:8080, router)) }代码解析路由注册与参数提取上面这段程序展示了如何编写一个 REST 应用其访问的资源是用户通过不同的 method 访问不同的处理函数router.GET(/user/:uid, getuser)查询用户资源对应取得资源router.POST(/adduser/:uid, adduser)新建用户资源对应建立资源router.DELETE(/deluser/:uid, deleteuser)删除用户资源对应删除资源router.PUT(/moduser/:uid, modifyuser)修改用户资源对应更新资源。路由规则中的:uid是路径参数占位符httprouter 会把实际请求路径中该位置的值解析进httprouter.Params处理函数通过ps.ByName(uid)即可取出路径中的用户 ID——这也解释了adduser中那行被注释掉的r.FormValue(uid)URI 定位资源后参数优先从路径中提取而非表单。Index与Hello则展示了 httprouter 与net/http处理函数签名w http.ResponseWriter, r *http.Request的平滑对接多出的第三个参数httprouter.Params正是该库对路由参数的封装。由于router实现了http.Handler接口它可以直接作为http.ListenAndServe(:8080, router)的第二个参数传入这正是 zh-tw/03.4.md 所述外部路由器只需实现 Handler 接口的具体落地。运行该程序后服务监听:8080即可用 curl 等工具按不同方法访问同一资源验证不同逻辑# 取得用户 1 的信息 curl http://localhost:8080/user/1 # 新增用户 1 curl -X POST http://localhost:8080/adduser/1 # 修改用户 1 curl -X PUT http://localhost:8080/moduser/1 # 删除用户 1 curl -X DELETE http://localhost:8080/deluser/1可以看到REST 的本质就是同一个资源URI通过不同的 HTTP 方法触发不同的逻辑处理。除了 httprouter 这类第三方库也可以参考 zh-tw/13.2.md 自行设计路由器在自定义路由器的ServeHTTP中按r.Method分发到不同处理函数同样能实现 RESTful 架构。总结REST 是一种架构风格它汲取了 WWW 的成功经验无状态、以资源为中心、充分利用 HTTP 协议和 URI 协议、提供统一的接口定义这使得它作为设计 Web 服务的方法而变得流行。从某种意义上说通过强调 URI 和 HTTP 等早期互联网标准REST 是对大型应用服务器时代之前 Web 方式的回归。目前 Go 对 REST 的支持还很简单但通过实现自定义路由规则我们就可以为不同的 method 实现不同的 handler从而在 Go Web 应用中实现 REST 架构。延伸阅读目录上一节WebSocket下一节RPC相关章节HTTP 详解含自定义路由器原理、自定义路由器设计赞分享文档教程【免费下载链接】build-web-application-with-golangA golang ebook intro how to build a web with golang项目地址https://gitcode.com/gh_mirrors/bu/build-web-application-with-golang点击查看免费下载相关推荐Go Web 编程中的 RESTful 架构从概念到 httprouter 实战build-web-application-with-golang 第 8.3 节Go Web 编程中的 RESTful 架构从概念到 httprouter 实战build web application with golang 第 8.文档教程用 Go 构建 RESTful Web 服务资源、状态转移与 httprouter 路由实现build-web-application-with-golang 第 8.3 节用 Go 构建 RESTful Web 服务资源、状态转移与 httprouter 路由实现build web application with golan文档教程用 Go 实现 RESTful 架构《Build Web Application with Golang》第 8.3 节精读与实践用 Go 实现 RESTful 架构《Build Web Application with Golang》第 8.3 节精读与实践 本篇技术指南围绕开源电子书文档教程上一篇Three.js 粒子系统终极指南打造惊艳的前端 3D 粒子效果下一篇pragmatic-drag-and-drop 文档示例中的 SVG 头像资源工程化raw/processed 双目录与 CodeSandbox 兼容方案解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表