首页 文章

使用一长串查询参数设计RESTful查询API [关闭]

提问于
浏览
104

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

减少参数数量不是一种选择 .

我能想到的另一种选择是在URI上使用POST方法并将过滤器作为POST主体的一部分发送 . 这是不是RESTfull(对查询数据进行POST调用) .

有没有更好的设计建议?

谢谢

4 回答

  • 69

    请记住,使用REST API,这都是您的观点问题 .

    REST API中的两个关键概念是 endpoints 和资源(实体) . 松散地说, endpoints 要么通过GET返回资源,要么通过POST和PUT等接受资源(或者上面的组合) .

    可以接受的是,对于POST,您发送的数据可能会也可能不会导致创建新资源及其关联的 endpoints ,这很可能不会在POSTed网址下“生存” . 换句话说,当您发布POST时,您可以将数据发送到某处进行处理 . POST endpoints 不是通常可以找到资源的位置 .

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

    9.5 POST POST方法用于请求源服务器接受请求中包含的实体,作为请求行中Request-URI标识的资源的新下级 . POST旨在允许统一的方法涵盖以下功能:...提供数据块,例如提交表单的结果,数据处理过程; ...... POST方法执行的操作可能不会产生可由URI标识的资源 . 在这种情况下,200(OK)或204(No Content)是适当的响应状态,具体取决于响应是否包括描述结果的实体 . 如果已在源服务器上创建资源,则响应应为201(已创建)...

    我们已经习惯了代表“事物”或“数据”的 endpoints 和资源,无论是用户,消息还是书籍 - 无论问题域是什么 . 但是, endpoints 也可以公开不同的资源 - 例如搜索结果 .

    请考虑以下示例:

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

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

    POST /books/search
    
        {
            "keywords": "...",
            "yearRange": {"from": 1945, "to": 2003},
            "genre": "..."
        }
    

    这个 endpoints 没有任何非RESTful功能 . 它以请求体的形式接受数据(实体) . 该数据是 Search Criteria - 与任何其他DTO一样 . 此 endpoints 生成响应请求的资源(实体): Search Results . 搜索结果资源是临时资源,立即提供给客户端,没有重定向,也没有从其他规范网址中公开 .

    它仍然是REST,除了实体不是书籍 - 请求实体是书籍搜索标准,而响应实体是书籍搜索结果 .

  • -3

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

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

    你失去了GET语义的一些好处......就像自动重试一样,因为GET是幂等的,但是如果你能接受它,那么接受使用POST处理真正冗长或复杂的查询可能会更容易 .

    (lol long digression ...我最近发现,通过HTTP规范,GET可以包含一个文档正文 . 有's one section that says, paraphrasing, 1665132 ... and the section it refers to doesn' t列出任何 . 我搜索并找到了一个HTTP作者正在讨论的线程,这是故意的,所以路由器等不会骰子滚动 . )

  • 5

    简而言之:使用X-HTTP-Method-Override标头进行POST但覆盖HTTP方法 .

    Real request

    邮寄/书籍

    Entity body

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

    Headers

    X-HTTP-Method-Override:GET

    在服务器端,检查是否存在标头X-HTTP-Method-Override,然后将其值作为构建到后端中最终 endpoints 的路由的方法 . 另外,将实体主体作为查询字符串 . 从后端的角度来看,请求变得简单得到 .

    这样您就可以使设计与REST原则保持一致 .

    Edit: 我知道这个解决方案最初是为了解决某些浏览器和服务器中的PATCH动词问题,但对于我来说,对于我来说,如果是一个非常长的URL,那么问题中描述的问题就是GET动词 .

  • 89

    如果您使用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 Pattern: “poc / test?code = 1&code = 2&code = 3

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

相关问题