Files
build-web-application-with-…/8.3.md
2012-10-10 22:08:41 +08:00

99 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#8.3 REST
RESTful架构就是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便所以正得到越来越多网站的采用。接下来让我们来了解这种架构到底是怎么样的Go里面如何来实现RESTful。
##什么是REST
REST(REpresentational State Transfer)描述了一个架构样式的网络系统比如Web应用程序。它首次出现在 2000年Roy Thomas Fielding的博士论文中他是HTTP规范的主要编写者之一。REST指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是RESTful。
Web应用程序最重要的REST原则是客户端和服务器之间的交互在请求之间是无状态的。从客户端到服务器的每个请求都必须包含理解请求所必需的信息。如果服务器在请求之间的任何时间点重启客户端不会得到通知。此外无状态请求可以由任何可用服务器回答这十分适合云计算之类的环境。客户端可以缓存数据以改进性能。
在服务器端应用程序状态和功能可以分为各种资源。资源是一个有趣的概念实体它向客户端公开。资源的例子有应用程序对象、数据库记录、算法等等。每个资源都使用URI(Universal Resource Identifier)得到一个惟一的地址。所有资源都共享统一的界面以便在客户端和服务器之间传输状态。使用的是标准的HTTP方法比如 GET、PUT、POST 和 DELETE。
另一个重要的REST原则是分层系统这表示组件无法了解它与之交互的中间层以外的组件。通过将系统知识限制在单个层可以限制整个系统的复杂性促进了底层的独立性。
我们看下图展示了REST的架构图如何实现
![](images/8.3.rest2.png?raw=true)
当REST架构的约束条件作为一个整体应用时将生成一个可以扩展到大量客户端的应用程序。它还降低了客户端和服务器之间的交互延迟。统一界面简化了整个系统架构改进了子系统之间交互的可见性。REST简化了客户端和服务器的实现。而且对于使用REST开发的应用程序更加容易扩展。
下图展示了REST的扩展新性
![](images/8.3.rest.png?raw=true)
##RESTful的实现
Go语言对于REST没有标准包直接支持但是因为RESTful是基于HTTP协议实现的所以我们可以利用Go语言的`net/http`包来实现当然需要针对REST需要做一些改造REST是根据不通的method来处理相应的资源我们先来看一下REST的几个分级请看下图
![](images/8.3.rest3.png?raw=true)
上图展示了我们目前实现REST的三个level我们在应用开发的时候也不一定全部按照RESTful的规则全部实现他的方式因为有些时候完全按照RESTful的方式未必是可行的RESTful服务充分利用每一个HTTP方法包括`DELETE``PUT`。可有时HTTP客户端只能发出`GET``POST`请求:
- HTML标准只能通过链接和表单支持`GET``POST`。在没有Ajax支持的网页浏览器中不能发出`PUT``DELETE`命令
- 有些防火墙会挡住HTTP `PUT``DELETE`请求要绕过这个限制,客户端需要把实际的`PUT``DELETE`请求通过 POST 请求穿透过来。RESTful 服务则要负责在收到的 POST 请求中找到原始的 HTTP 方法并还原。
我们现在可以通过`POST`里面增加隐藏字段`_method`这种方式可以来模拟`PUT``DELETE`等方式但是服务器端需要做转换。我现在的项目里面就按照这种方式来做的REST接口。当然Go语言里面完全按照RSETful来实现是很容易的我们通过下面的例子来说明如何实现RESTful的应用设计。
package main
import (
"fmt"
"github.com/drone/routes"
"net/http"
)
func getuser(w http.ResponseWriter, r *http.Request) {
params := r.URL.Query()
uid := params.Get(":uid")
fmt.Fprintf(w, "you are get user %s", uid)
}
func modifyuser(w http.ResponseWriter, r *http.Request) {
params := r.URL.Query()
uid := params.Get(":uid")
fmt.Fprintf(w, "you are modify user %s", uid)
}
func deleteuser(w http.ResponseWriter, r *http.Request) {
params := r.URL.Query()
uid := params.Get(":uid")
fmt.Fprintf(w, "you are delete user %s", uid)
}
func adduser(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "you are add user %s", uid)
}
func main() {
mux := routes.New()
mux.Get("/user/:uid", getuser)
mux.Post("/user/:uid", modifyuser)
mux.Del("/user/:uid", deleteuser)
mux.Put("/user/", adduser)
http.Handle("/", mux)
http.ListenAndServe(":8088", nil)
}
上面的代码我们演示如何编写一个REST的应用我们访问的资源是用户然后我们通过不同的method来访问不同的函数这里我们使用了一个第三方库`github.com/drone/routes`这个库实现了方便的路由规则映射我们在上面章节也介绍过可以实现自定义的路由器这个库就实现了自定义的路由我们可以很方便的实现REST的架构。通过上面的代码我们知道REST就是根据不同的method访问同一个资源的时候实现不同的逻辑处理。一般这些method的定义如下
- Get表示获取请求的资源信息
- Post表示修改相应的资源信息
- Put表示添加一个新的资源
- Delete表示删除请求的资源信息
- Patch表示对资源进行部分更新的一个特殊方法
通过上面的代码演示我们知道资源是通过URI来确定的然后通过不同的方式执行不同的操作方式这就是RESTful的实现。
##总结
REST是一种架构风格汲取了WWW的成功经验无状态以资源为中心充分利用HTTP协议和URI协议提供统一的接口定义使得它作为一种设计Web服务的方法而变得流行。在某种意义上通过强调URI和HTTP等早期Internet标准REST是对大型应用程序服务器时代之前的Web方式的回归。目前Go对于REST的支持还是很简单的通过实现自定义的路由规则我们就可以实现不同的method实现不同的handle这样就实现了REST的架构。
## links
* [目录](<preface.md>)
* 上一节: [WebSocket](<8.2.md>)
* 下一节: [RPC](<8.4.md>)
## LastModified
* $Id$