REST API设计模式和反模式

在这篇文章中,我们将探讨一些常见的REST API设计模式和开发者应该注意的反模式。
首页 新闻资讯 行业资讯 REST API设计模式和反模式

RESTful API已经成为构建现代网络应用的事实标准。它们允许一个灵活和可扩展的架构,可以很容易地被广泛的客户端所消费。然而,设计一个既健壮又可维护的REST API是很有挑战性的,特别是对于刚入行的开发者。

在这篇文章中,我们将探讨一些常见的REST API设计模式和开发者应该注意的反模式。我们还将提供Golang和Open API Schema的代码片段来帮助说明这些概念。

7538246766bda91de8a105030f205cbda0d251.jpg

一、REST API设计模式

1.以资源为导向的架构(ROA)

面向资源的架构(ROA)是一种设计模式,强调资源在RESTful API中的重要性。资源是RESTful API的关键构件,它们应该被设计成易于消费和操作的方式。

在Golang中实现ROA的一种方式是使用gorilla/mux包进行路由。这里有一个例子:

r:=mux.NewRouter()r.HandleFunc("/users/{id}",getUser).Methods("GET")r.HandleFunc("/users",createUser).Methods("POST")r.HandleFunc("/users/{id}",updateUser).Methods("PUT")r.HandleFunc("/users/{id}",deleteUser).Methods("DELETE")

在Open API Schema中,你可以使用path参数来定义资源。下面是一个例子:

paths:/users/{id}:get:…put:…delete:…/users:post:…

2. HATEOAS

超媒体作为应用状态的引擎(HATEOAS)是一种设计模式,允许客户动态地浏览RESTful API。API提供超媒体链接,客户可以按照这些链接来发现资源并与之互动。

为了在GoLang中实现HATEOAS,你可以使用go-jsonapi包。这里有一个例子:

type User struct{IDstring`json:"id"`Name string`json:"name"`Links*Links`json:"links,omitempty"`}type Links struct{Self*Link`json:"self,omitempty"`}type Link struct{Href string`json:"href,omitempty"`}funcgetUser(w http.ResponseWriter,r*http.Request){userID:=mux.Vars(r)["id"]user:=User{ID:userID,Name:"John Doe"}user.Links=&Links{Self:&Link{Href:fmt.Sprintf("/users/%s",userID)},}jsonapi.MarshalOnePayload(w,&user)}

在Open API Schema中,你可以使用links参数来定义超媒体链接。这里有一个例子:

paths:/users/{id}:get:responses:'200':content:application/json:schema:$ref:'#/components/schemas/User'links:self:href:'/users/{id}'

二、REST API反模式

1.RPC式的API

远程过程调用(RPC)风格的API是RESTful API设计中一个常见的反模式。RPC风格的API暴露了直接映射到底层实现的方法,而不是专注于资源。

下面是一个GoLang中RPC风格API的例子:

funcgetUser(w http.ResponseWriter,r*http.Request){userID:=r.FormValue("id")user:=userService.GetUser(userID)json.NewEncoder(w).Encode(user)}

在Open API Schema中,你可以使用operationId参数来定义RPC风格的API。下面是一个例子:

paths:/users:get:operationId:getUser

2.过度的工程设计

过度工程是RESTful API设计中另一个常见的反模式。当开发者试图预测每一个可能的用例并建立一个复杂的API来适应它们时,就会出现过度设计。

这里有一个Golang中过度工程的例子:

funcgetUser(w http.ResponseWriter,r*http.Request){userID:=mux.Vars(r)["id"]user,err:=userService.GetUser(userID)iferr!=nil{handleError(w,err)return}json.NewEncoder(w).Encode(user)}funccreateUser(w http.ResponseWriter,r*http.Request){varuser Usererr:=json.NewDecoder(r.Body).Decode(&user)iferr!=nil{handleError(w,err)return}user.ID=uuid.New().String()user.CreatedAt=time.Now()user.UpdatedAt=time.Now()err=userService.CreateUser(user)iferr!=nil{handleError(w,err)return}json.NewEncoder(w).Encode(user)}funcupdateUser(w http.ResponseWriter,r*http.Request){userID:=mux.Vars(r)["id"]varuser Usererr:=json.NewDecoder(r.Body).Decode(&user)iferr!=nil{handleError(w,err)return}user.ID=userID
 user.UpdatedAt=time.Now()err=userService.UpdateUser(user)iferr!=nil{handleError(w,err)return}json.NewEncoder(w).Encode(user)}funcdeleteUser(w http.ResponseWriter,r*http.Request){userID:=mux.Vars(r)["id"]err:=userService.DeleteUser(userID)iferr!=nil{handleError(w,err)return}w.WriteHeader(http.StatusNoContent)}funchandleError(w http.ResponseWriter,err error){w.WriteHeader(http.StatusInternalServerError)fmt.Fprint(w,err.Error())}

在Open API Schema中,你可以使用x-go-genie扩展定义过度工程。这里有一个例子:

paths:/users/{id}:get:x-go-genie:serviceName:UserServicemethodName:GetUserput:x-go-genie:serviceName:UserServicemethodName:UpdateUserdelete:x-go-genie:serviceName:UserServicemethodName:DeleteUser/users:post:x-go-genie:serviceName:UserServicemethodName:CreateUser

总结

设计一个既健壮又可维护的RESTful API可能具有挑战性,但通过遵循最佳实践并避免常见的反模式,开发人员可以创建易于消费和操作的API。在这篇文章中,我们探讨了一些常见的REST API设计模式和反模式,并提供了GoLang和Open API Schema的代码片段来帮助说明这些概念。

27    2023-10-30 18:59:38    REST API 开发