Skip to main content

resful api

什么是resful api

resful api是一套规范,可规范我们如何对服务器上的资源进行操作

http method

在介绍resful api之前,我们需要了解一下HTTP Method,因为resful api和它密不可分

最常见的就是GET和POST,最早在HTTP0.9版本只有一个GET方法,该方法是一个幂等方法,用于获取服务器上的资源,也就是在浏览器中直接输入网址,然后回车请求的方法

在HTTP1.0版本中又增加了HEAD和POST方法

其中常用的是POST方法,一般用于给服务端提交一些资源,导致服务器的资源发生变化

后来发现方法不够用,一口气增加到9个方法,新增的方法有:

  • HEAD
  • OPTIONS
  • PUT
  • DELETE
  • TRACE
  • PATCH
  • CONNECT

GET方法:

可请求一个指定资源的表示形式,使用GET的请求应该只用于获取数据

HEAD方法:

请求一个与GET请求的响应相同的响应,但是没有响应体

POST方法:

将实体提交到指定的资源,通常导致服务器上的状态变化或副作用

PUT方法:

请求有效载荷替换目标资源的所有当前表示

DELETE方法:

删除指定资源

CONNECT方法:

建立一个到由目标资源标识的服务器的隧道

OPTIONS方法:

描述目标资源的通信选项

TRACE方法:

沿着到目标资源的路径执行一个消息环回测试

PATCH方法:

对资源应用部分修改

HTTP针对每个方法都给出了明确的定义,我们应该尽可能的遵循HTTP的规范,这样我们在开发中才能更好的协作,因为它是一套通用的规范,大家都在遵守

理解了HTTP的方法,就能更好的理解RESFUL API

RESFUL API规范就是基于这些HTTP方法规范我们对服务器资源的操作

同时规范了URL的样式和HTTP STATUS CODE

resful api 主要使用下面5种http方法

服务器上的资源通过特定的url表示,接下来通过下面的一些示例让我们更好的理解resful api

#GET方法示例

#获取所有用户的信息
HTTP GET https://www.xxx.com/users
#获取用户id为123的用户
HTTP GET https://www.xxx.com/users/123
#POST方法示例,这个示例创建了一个用户

#通过POST方法给服务器提供创建这个用户的所有信息
#需要注意的是url中的users复数
HTTP POST https://www.xxx.com/users
#PUT方法示例,
#更新单个服务器资源:更新用户id为123的资源
HTTP PUT https://www.xxx.com/users/123
#如果要更新一个用户的部分信息,用PATCH更为合适
#DELETE方法示例,
#删除用户id为123的资源
HTTP DELETE https://www.xxx.com/users/123

resful api实例之标准库

go语言很大的一个优势就是很容易开发出网络后台服务,而且性能快、效率高

常见的resful api服务: 处理很多http服务,然后吧处理的消息返回给使用者

下面我们来看一个简单http实现:

package main

import (
"fmt"
"net/http"
)

func main() {
http.HandleFunc("/users",handleUsers)
http.ListenAndServe(":8080",nil)
}

func handleUsers(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w,"ID:1,Name:张三")
fmt.Fprintf(w,"ID:2,Name:李四")
fmt.Fprintf(w,"ID:3,Name:王五")
}

当在浏览器访问 http://127.0.0.1:8080/users 时,可以看到我们可以获取所有的用户信息

但是它并不是resful风格的api,因为我们还可以用POST,PUT,DELETE等所有的方法来获取所有的用户信息

下面我们对代码进行修改,使其符合resful风格的规范

package main

import (
"fmt"
"net/http"
)

func main() {
http.HandleFunc("/users",handleUsers)
http.ListenAndServe(":8080",nil)
}

func handleUsers(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w,"ID:1,Name:张三")
fmt.Fprintf(w,"ID:2,Name:李四")
fmt.Fprintf(w,"ID:3,Name:王五")
default:
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w,"NOT FOUND")
}

}

这时你会发现只有GET才能访问了

在项目中最常见的是使用json格式传输信息,也就是我们提供的resful api要返回json内容给使用者

我们再来改造下代码:

package main

import (
"encoding/json"
"fmt"
"net/http"
)

type User struct {
ID int
Name string
}

//数据源,类似于mysql中的数据
var users = []User{
{ID:1,Name: "张三"},
{ID:2,Name: "李四"},
{ID:3,Name: "王五"},
}

func main() {
http.HandleFunc("/users",handleUsers)
http.ListenAndServe(":8080",nil)
}

func handleUsers(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
users, err:= json.Marshal(users)
if err!=nil{
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(w,"{\"message\":\""+err.Error()+"\"}")
}else {
w.WriteHeader(http.StatusOK)
w.Write(users)
}
default:
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w,"{\"message\":\"NOT FOUND\"}")
}
}

此时,再去访问浏览器

resful api实例之开源库-gin

可以看到标准包net/http非常强大,但是还是有一些不足,如下:

基于以上不足,出现了很多优秀的开源的web框架,比如gin,mux,beego

今天介绍的是使用最多的gin框架

gin框架简介: gin框架是一个在github上开源的web框架,封装了很多web开发需要的通用功能,性能非常高,可以容易的写出性能高效的RESFUL API

使用gin框架需要先下载安装:

go get -u github.com/gin-gonic/gin

然后在go语言代码中导入即可使用

import "github.com/gin-gonic/gin"

gin http demo

package main

import (
"github.com/gin-gonic/gin"
"log"
)

func main() {
//gin.SetMode(gin.ReleaseMode)
router := gin.New()
router.GET("/", index)
log.Println("server is running at http://127.0.0.1:3333")
router.Run(":3333")
}

func index(c *gin.Context) {
//db operation
c.JSON(200, gin.H{
"code": "2000",
"msg": "ok",
"likes": []string{"apple", "pear", "orange"},
})
}

下面就用gin框架重写上面的示例

查询所有用户

package main

import (
"github.com/gin-gonic/gin"
)

type User struct {
ID int
Name string
}

//数据源,类似于mysql中的数据
var users = []User{
{ID:1,Name: "张三"},
{ID:2,Name: "李四"},
{ID:3,Name: "王五"},
}

func main() {
r:= gin.Default()
r.GET("/users",handleUsers)
r.Run(":8080")
}

func handleUsers(c *gin.Context) {
c.JSON(200,users)
}

相对于标准库,gin更加简洁

查询特定用户

现在我们已经掌握了如何使用gin框架创建一个简单的resful api且可返回所有的用户信息,那如何获取特定用户的信息呢

HTTP GET http://127.0.0.1:8080/users/123
package main

import (
"github.com/gin-gonic/gin"
"strconv"
"strings"
)

type User struct {
ID int
Name string
}

//数据源,类似于mysql中的数据
var users = []User{
{ID:1,Name: "张三"},
{ID:2,Name: "李四"},
{ID:3,Name: "王五"},
}

func main() {
r:= gin.Default()
r.GET("/users/:id",handleUsers)
r.Run(":8080")
}

func handleUsers(c *gin.Context) {
id:=c.Param("id") //注意:param里的参数要和路径里的参数保持一致 =》 "/users/:id"
var user User
found:=false
//模拟数据库的sql查询
for _, u:= range users{
if strings.EqualFold(id,strconv.Itoa(u.ID)){
user = u
found = true
break
}
}

if found{
c.JSON(200,user)
}else {
c.JSON(404,gin.H{
"message":"用户不存在",
})
}
}

运行,并用浏览器打开:

再访问一个不存在的id

新增一个用户

根据resful api规范,实现新增使用的是POST方法

并且URL的格式为:http://127.0.0.1:8080/users

向URL发送数据,即可新增一个用户,然后返回创建的用户信息

package main

import (
"github.com/gin-gonic/gin"
"net/http"
)

type User struct {
ID int
Name string
}

//数据源,类似于mysql中的数据
var users = []User{
{ID:1,Name: "张三"},
{ID:2,Name: "李四"},
{ID:3,Name: "王五"},
}

func main() {
r:= gin.Default()
r.POST("/users",createUser)
r.Run(":8080")
}

func createUser(c *gin.Context) {
name:=c.DefaultPostForm("name","")
if name!=""{
u:=User{
ID: len(users)+1,
Name: name,
}
users = append(users,u)
c.JSON(http.StatusCreated,u)
}else {
c.JSON(http.StatusOK,gin.H{
"message":"请输入用户名称",
})
}
}

启动服务,然后通过terminal发送POST请求

curl -X POST -d 'name=scott' http://127.0.0.1:8080/users

练习

在做项目时,会有增删改查,现在已经有了增查,还差改删,想一想如何实现下面的功能:

  • 1,修改一个用户的名字
  • 2,删除一个用户

总结

go语言已经提供了比较强大的SDK,可以很容易的开发网络服务的应用,而借助第三方的web框架可让这件事情更容易、更高效

在做项目开发的时候,要善于借助已有的轮子,不要重复造轮子