“REST API最佳实践路由”

huangapple go评论63阅读模式
英文:

REST API best practise for routes

问题

Sure, here is the translation of your request:

  1. 获取数据库中的所有订单。(这个场景通常不实际,仅用于理解目的)
  2. 通过订单ID获取订单。
  3. 通过订单ID获取单个订单。

• 是否可以使用单个GET路由处理所有这些情况?

• 还是应该为这些情况创建单独的路由?

任何帮助都将不胜感激!!(如果有关的话,这里使用了Express JS框架)

英文:

I wonder what is the best practise when creating REST APIs for the following scenarios when an Order is a resource:

  1. Get all the orders in the Database. (surely not a practical scenario, only for understanding purpose)
  2. Get orders by order IDs.
  3. Get a single order by order ID

• Can a single GET route be used for all these scenarios?

• Or should we have separate routes for these scenarios?

Any help would be much appreciated!! (Express JS framework is used if that matters)

答案1

得分: 3

以下是翻译好的部分:

"Can a single GET route be used for all these scenarios?"
您可以为所有这些情况使用单一路由:

GET /orders                              // 获取所有订单
GET /orders?id=409,5678,2987             // 根据id获取这些订单
GET /orders?id=9463                      // 根据id获取这个订单
GET /orders?person=jackwelch             // 获取此人的订单
GET /orders?company=aaWidget             // 获取此公司的订单

"Or should we have separate routes for these scenarios?"
这在很大程度上是一种设计观点。我通常喜欢将不同的URL形式数量尽量保持得尽可能少,当有多个输入时,通过重载同一路由以适应不同情况是有意义的,而且不会感到过于随意。但最终,这是基于对您需要支持的查询总体情况以及如何最可能使用它的理解来做出的判断。

此外,请记住,要添加新订单,您将使用POST,要修改现有订单,您将使用PUT,要删除订单,您将使用DELETE

POST   /orders                    // 创建新订单,数据在请求的主体中
PUT    /orders/:id                // 修改现有订单,数据在请求的主体中
DELETE /orders/:id                // 删除订单

因此,所有这些操作都可以使用一个/orders URL结构对外界进行操作。在内部,它可能会被结构化为几个不同的路由处理程序,以使处理它的代码更简单:

app.get("/orders", ...);         // 处理订单查询(使用req.query)
app.post("/orders", ...);        // 创建新订单(使用req.body)
app.put("/orders/:id", ...);     // 修改现有订单(使用req.params.id和req.body)
app.delete("/orders/:id", ...);  // 删除现有订单(使用req.params.id)

这种结构的另一个好处是,它非常可扩展。您可以通过仅添加附加的查询字符串参数来添加更多查询订单的方式,而无需对整体结构或甚至任何新的路由处理程序进行更改。

英文:

> Can a single GET route be used for all these scenarios?

You could use a single route for all these scenarios:

GET /orders                              // get all
GET /orders?id=409,5678,2987             // get these orders by id
GET /orders?id=9463                      // get this order by id
GET /orders?person=jackwelch             // get orders for this person
GET /orders?company=aaWidget             // get orders for this company 

> Or should we have separate routes for these scenarios?

This is largely a matter of design opinion. I'm generally a fan of keeping the number of distinct URL forms to as few as practical and overloading the same route for different inputs when it makes sense and doesn't feel too arbitrarily stretched to make it all a fit. But ultimately, it's a judgment call based on an understanding of the overall landscape of queries you need to support and how it will most likely be used.

And, keep in mind that for adding a new order, you would use POST and modifying an existing order, you would use PUT and deleting an order, you use DELETE

POST   /orders                    // create new order, data in body of request
PUT    /orders/:id                // modify existing order, data in body of request
DELETE /orders/:id                // delete an order

So, all of these can be done with one /orders URL structure to the outside world. Internally, it would probably be structured as several different route handlers, just to make the code for handling it simpler:

app.get("/orders", ...);         // handle order queries   (use req.query)
app.post("/orders", ...);        // create new order       (use req.body)
app.put("/orders/:id", ...);     // modify existing order  (use req.params.id and req.body)
app.delete("/orders/:id", ...);  // delete existing order  (use req.params.id)

Another nice thing about this structure, is that it's very extensible. You can add more ways to query the orders by only adding additional query string parameters with no overall change to the structure or even any new route handlers.

答案2

得分: 3

RESTful APIs使用HTTP方法作为动词。这意味着相同的端点可用于获取订单列表和创建新订单;或者获取特定订单,更新它,甚至删除它。

考虑到这一点,您可以设计API结构如下:

GET /orders // 获取所有订单列表
GET /orders/:id // 获取特定订单的信息

这将帮助您轻松添加更多方法,而无需更改API设计:

POST /orders // 创建新订单
PUT /orders/:id // 更新特定订单
DELETE /orders/:id // 删除它

如果您想在端点上添加搜索功能,使用查询字符串是相当常见的。例如:

GET /orders?email=john@example.org // 检索该客户的所有订单
GET /orders?limit=10 // 仅检索每个结果的前10个命中
GET /orders?limit=10&total=99.99 // 检索前10个总金额为99.99的订单

您可以添加专用的搜索参数来按ID返回订单(如所请求),但这不太常见,因为您已经可以使用端点/orders/:id按ID查询。您可能考虑避免额外的请求,但一般来说,性能提升相当有限 - 除非您的应用程序关键要求多次按ID检索.

英文:

RESTful APIs use HTTP methods as verbs. This means that the same endpoint shall be used to get a list of orders and create a new one; or get one specific order, update it or event delete it.

With this in mind, you could design your API structure as follow:

GET       /orders        // To get a list of all orders
GET       /orders/:id    // To get information about a specific order

This will help you to add more methods quite easily, without changing the API design:

POST     /orders         // To create a new order
PUT      /orders/:id     // To update that specific order
DELETE   /orders/:id     // To delete it

In case you want to add search capabilities on an endpoint, it's quite common to use query string. For examples:

GET   /orders?email=john@example.org  // To retrieve all orders from that customer
GET   /orders?limit=10                // To retrieve only 10 hits per results
GET   /orders?limit=10&total=99.99    // To retrieve top 10 orders with a total of 99.99

You could add a dedicated search parameters to return orders by IDs (as asked), but it's not so common as you can already query by ID using the endpoint /orders/:id. You might think about avoiding extra requests here, but generally speaking the performance gain is quite low - except if it's critical to your application to retrieve by IDs several hits.

huangapple
  • 本文由 发表于 2020年1月6日 16:10:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/59608660.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定