【问题标题】:Design RESTful query API with a long list of query parameters [closed]设计带有一长串查询参数的 RESTful 查询 API [关闭]
【发布时间】:2012-12-21 13:18:39
【问题描述】:

我需要设计一个 RESTful 查询 API,它根据几个过滤器返回一组对象。通常的 HTTP 方法是 GET。唯一的问题是,它至少可以有十几个过滤器,如果我们将它们全部作为查询参数传递,URL 可能会变得很长(长到足以被某些防火墙阻止)。

减少参数的数量不是一种选择。

我能想到的另一种选择是在 URI 上使用 POST 方法,并将过滤器作为 POST 正文的一部分发送。这是否反对 RESTfull(发出 POST 调用以查询数据)。

谁有更好的设计建议?

【问题讨论】:

  • 使用短的(1 字符等)参数名称?
  • 它可能不是真正的 RESTful,但我认为在 GET 和 POST 方面你必须实用。如果你有那么多变量要发送并且你不能减少它们,我会发布它们。我不喜欢过度填充 URL,但这只是我自己。
  • 谢谢。即使这个问题已经结束,这正是我需要回答的问题。我很高兴你问。

标签: rest http-parameters


【解决方案1】:

请记住,对于 REST API,这完全取决于您的观点。

REST API 中的两个关键概念是端点和资源(实体)。简单地说,一个端点要么通过 GET 返回资源,要么通过 POST 和 PUT 等(或以上的组合)接受资源。

通过 POST,您发送的数据可能会或可能不会导致创建新资源及其关联的端点,这很可能不会在 POST 的 url 下“活动”,这是公认的。换句话说,当您发布时,您将数据发送到某处进行处理。 POST 端点不是通常可以找到资源的位置。

引用RFC 2616(不相关部分省略,相关部分突出显示):

9.5 发布

POST 方法用于请求源服务器接受 包含在请求中的实体作为资源的新下属 由 Request-Line 中的 Request-URI 标识。 POST 旨在 允许一个统一的方法覆盖以下功能:

  • ...
  • 向数据处理过程提供数据块,例如提交表单的结果;
  • ...

...

POST 方法执行的操作可能不会产生可由 URI 识别的资源。在这种情况下,200(正常)或 204(无内容)是适当的响应状态,具体取决于响应是否包含描述结果的实体

如果在源服务器上创建了资源,则响应应该是 201 (Created)...

我们已经习惯了代表“事物”或“数据”的端点和资源,无论是用户、消息还是书籍——无论问题领域如何规定。但是,端点也可以公开不同的资源 - 例如搜索结果。

考虑以下示例:

GET    /books?author=AUTHOR
POST   /books
PUT    /books/ID
DELETE /books/ID

这是一个典型的 REST CRUD。但是,如果我们添加:

POST /books/search

    {
        "keywords": "...",
        "yearRange": {"from": 1945, "to": 2003},
        "genre": "..."
    }

这个端点没有什么非 RESTful 的。它接受请求正文形式的数据(实体)。该数据就是搜索标准 - 与其他任何数据一样的 DTO。此端点响应请求生成资源(实体):搜索结果。搜索结果资源是一个临时资源,会立即提供给客户端,无需重定向,也不会暴露于其他一些规范的 url。

它仍然是 REST,除了实体不是书籍 - 请求实体是书籍搜索条件,响应实体是书籍搜索结果。

【讨论】:

  • 您能推荐一些 DTO 的类命名约定吗?
  • 我个人会选择BooksSearchCriteriaDTOBooksSearchResultsDTO
  • 对于这种 POST /books/search 情况,最好的 HTTP 响应代码是什么? 201 仍然适用吗?
  • 201 是相反的——它意味着已经创建了一个资源。预计在某处拥有自己唯一 URI 的资源。当POST 用于CRUD 的C 部分时,201 是合适的。我会使用普通的旧 200,也可以选择使用 204 作为空搜索结果。
  • 请记住,现在 GET 在理论上也非常适用——“被称为“HTTP/1.1 规范”的 RFC2616 现在已过时。在 2014 年,它被 RFC 7230-7237 取代。引用“处理请求时应该忽略消息正文”已被删除。现在只是“请求消息框架独立于方法语义,即使该方法没有定义消息正文的任何​​用途”第二个引用“The GET 方法意味着检索任何由 Request-URI 标识的信息......“已删除。” - 来自stackoverflow.com/questions/978061/http-get-with-request-body
【解决方案2】:

很多人已经接受这样的做法,即查询字符串太长或太复杂(例如查询字符串不能轻松处理嵌套数据)的 GET 可以作为 POST 发送,而表示复杂/长数据在请求的正文中。

在 HTTP 规范中查找 POST 规范。它非常广泛。 (如果你想通过 REST 中的漏洞驾驶战舰……使用 POST。)

您失去了 GET 语义的一些好处……例如自动重试,因为 GET 是幂等的,但如果您能接受这一点,那么接受使用 POST 处理非常长或复杂的查询可能会更容易。

(lol 题外话...我最近发现,根据 HTTP 规范,GET 可以包含一个文档正文。有一段说,解释说,“任何请求都可以有一个文档正文,除了本节中列出的那些“......并且它所指的部分没有列出任何内容。我搜索并找到了一个HTTP作者正在谈论的线程,这是故意的,因此路由器等不会必须区分不同的消息。然而,在实践中,许多基础设施部分确实放弃了 GET 的主体。因此,您可以使用主体中表示的过滤器进行 GET,例如 POST,但您将掷骰子。)

【讨论】:

  • 另请参阅this 问题以了解有关使用正文的 HTTP GET 的更多讨论。
  • 很多人发明了一些不同于 RESTful 和 HTTP 规范的东西。 RESTful Fielding 的作者对此表示遗憾。
【解决方案3】:

简而言之:创建一个 POST,但使用 X-HTTP-Method-Override 标头覆盖 HTTP 方法。

真实请求

发布/书籍

实体主体

{ "title": "Ipsum", “年份”:2017 }

标题

X-HTTP-Method-Override: GET

在服务器端,检查头 X-HTTP-Method-Override 是否存在,然后将其值作为方法来构建到后端最终端点的路由。此外,将实体主体作为查询字符串。从后端的角度来看,请求变成了一个简单的 GET。

通过这种方式,您可以使设计与 REST 原则保持一致。

编辑:我知道这个解决方案最初是为了解决某些浏览器和服务器中的 PATCH 动词问题,但它也适用于我的 GET 动词,因为 URL 很长,这是问题所在问题中描述。

【讨论】:

【解决方案4】:

如果您使用 Java 和 JAX-RS 进行开发,我建议您使用 @QueryParam 和 @GET

当我需要查看列表时,我也有同样的问题。

查看示例:

import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;

@Path("/poc")
public class UserService {

    @GET
    @Path("/test/")
    @Produces(MediaType.APPLICATION_JSON)
    public Response test(@QueryParam("code") final List<Integer> code) {
                Integer int0 = codigo.get(0);
                Integer int1 = codigo.get(1);

        return Response.ok(new JSONObject().put("int01", int0)).build();
    }
}

URI 模式: “poc/test?code=1&code=2&code=3

@QueryParam会自动将查询参数“orderBy=age&orderBy=name”转换成java.util.List。

【讨论】:

  • 如果你解释你的例子会更好。它是用什么编程语言编写的?
  • 嗨@AleksAndreev。谢谢您的意见。好转了吗? tks
  • 这个问题是关于 RESTful 服务的设计,而不是关于实现。这个答案没有回答问题。
  • @user1331413 恕我直言,是的,现在更好了。感谢您的努力。但是,正如 Mike McCaughan 所说,问题是关于 REST 概念,而不是实现
猜你喜欢
  • 1970-01-01
  • 2019-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-19
  • 1970-01-01
相关资源
最近更新 更多