V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dunhanson
V2EX  ›  程序员

RESTFul API 接口规范, GET 请求如何传递复杂对象?

  •  
  •   dunhanson · 2022-06-17 18:16:56 +08:00 · 6635 次点击
    这是一个创建于 650 天前的主题,其中的信息可能已经有所发展或是发生改变。

    感觉进入了死胡同了

    GET 用于查询,POST 用于创建,GET 传递 body 不符合规范

    第 1 条附言  ·  2022-06-17 18:48:37 +08:00
    还有一个参数命名规范,是驼峰还是下划线?单词之间
    第 2 条附言  ·  2022-06-18 11:01:20 +08:00
    准备复杂的查询还是用 Post
    72 条回复    2023-05-27 09:20:24 +08:00
    TWorldIsNButThis
        1
    TWorldIsNButThis  
       2022-06-17 18:18:47 +08:00 via iPhone   ❤️ 3
    规范没限制 get 传 body
    只是一些框架不支持
    dzdh
        2
    dzdh  
       2022-06-17 18:19:35 +08:00   ❤️ 5
    ![]( )
    wolfie
        3
    wolfie  
       2022-06-17 18:19:55 +08:00
    get 没 body
    dingyaguang117
        4
    dingyaguang117  
       2022-06-17 18:22:08 +08:00
    GET 传 body 有很多隐患。 要考虑整个链路上的库是否都支持。只要有一环不支持,就麻烦得很。

    感觉直接参数 base64 一下放到 querystring 好点
    dunhanson
        5
    dunhanson  
    OP
       2022-06-17 18:23:02 +08:00
    @TWorldIsNButThis 有一些文章又说规范不建议,感觉都摸棱两可
    dunhanson
        6
    dunhanson  
    OP
       2022-06-17 18:24:04 +08:00
    @dingyaguang117 是可以这样子,但是好麻烦,也不直观
    qunqun
        7
    qunqun  
       2022-06-17 18:24:19 +08:00 via Android
    post 一个 task, 然后 get 取结果 ?
    DoveAz
        8
    DoveAz  
       2022-06-17 18:25:22 +08:00
    @TWorldIsNButThis chrome 都不支持,这直接没得玩
    Chad0000
        9
    Chad0000  
       2022-06-17 18:26:49 +08:00 via iPhone
    所以有时候不需要完全按 restful 来。比如你有一个接口用来验证订单是否可提交,传的参数会很多,post 更合适。
    Trim21
        10
    Trim21  
       2022-06-17 18:30:57 +08:00
    太过复杂就不用 rest 了呗。restful 本来就是为了方便理解 api 的,最后搞的又不直观又难用就本末倒置了。
    dunhanson
        11
    dunhanson  
    OP
       2022-06-17 18:32:00 +08:00
    @qunqun 这个增加工作量吧
    dunhanson
        12
    dunhanson  
    OP
       2022-06-17 18:34:35 +08:00
    @Trim21 现在进退两难
    beginor
        13
    beginor  
       2022-06-17 18:34:48 +08:00 via Android
    大对象用 post 吧,post 也属于 rest 吧
    eason1874
        14
    eason1874  
       2022-06-17 18:39:00 +08:00
    这才多长,才几百字节,放 URL 没问题啊,连最落后的 IE 也支持 2K 长度 URL

    二维展开到一维就好了,比如 searchWord=&areaProvince=&areaCity=,懒得处理就直接 area=encodeURIComponent(data json)
    xuelu520
        15
    xuelu520  
       2022-06-17 18:39:22 +08:00
    base64 传过去呗。确实需要用 get 只能考虑改下接口参数,自己解析。
    另外规范灵活一点,改成 post 的
    Chad0000
        16
    Chad0000  
       2022-06-17 18:39:44 +08:00 via iPhone
    op 如果过于较真的话,那么 OCR 识别接口是不是应该使用 get ?然后你 get 传一张图片是不是更难了哈,这样真变成为了 restful 而 restful 了。
    cpstar
        17
    cpstar  
       2022-06-17 18:49:03 +08:00
    OP 的确进入一个死胡同了,这个 searchCondition 不能这么弄
    如果严格 RESTful ,那应该 GET /search/{searchWord}/{area}/{channel}/{pageSize}/...
    该这么整么?显然不是啊,search 以及带有 searchCondition 的,并不是严格遵从 RESTful ,RESTful 可以理解对实体的,比如 GET /product/{id},
    dunhanson
        18
    dunhanson  
    OP
       2022-06-17 18:49:52 +08:00 via iPhone
    @Chad0000 这种属于 POST 吧?
    dunhanson
        19
    dunhanson  
    OP
       2022-06-17 18:51:18 +08:00 via iPhone
    @xuelu520 最早用的这种,但是不直观
    dunhanson
        20
    dunhanson  
    OP
       2022-06-17 18:52:07 +08:00 via iPhone
    @eason1874 在想有没有其他更好的方式
    XCFOX
        21
    XCFOX  
       2022-06-17 18:55:20 +08:00
    GraphQL 解君愁
    dcsuibian
        22
    dcsuibian  
       2022-06-17 19:02:16 +08:00
    POST /search-results
    POST 是新建资源,“搜索”不能作为一种资源,但“搜索结果”呢?
    knives
        23
    knives  
       2022-06-17 19:05:32 +08:00
    可以用 Content-Type 区分。POST application/json 为创建,POST application/x-www-form-urlencoded 为查询
    oxromantic
        24
    oxromantic  
       2022-06-17 19:14:50 +08:00
    你这个业务场景就是创建啊,创建一个查询结果集
    jorneyr
        25
    jorneyr  
       2022-06-17 19:16:59 +08:00
    JSON Base64 编码一下,作为一个 URL Query 参数传给后端。
    imycc
        26
    imycc  
       2022-06-17 19:18:08 +08:00
    执着于 RESTFul 的话,那就是用 POST 创建一个查询请求,返回的就是查询请求的结果。(是不是很合理)
    不执着于 RESTFul 的话,GET 的 querystring 里面直接塞一段 json 字符串。之前用 steam 的 API ,他们就是这么干的
    version0
        27
    version0  
       2022-06-17 19:22:30 +08:00
    不用纠结 restful 啦,以前我也纠结,直到我看到了一些出名的工具咋查询的,比如 elasicSearch
    chendy
        28
    chendy  
       2022-06-17 19:27:15 +08:00
    直接 POST /xxx/_search
    规范是死的,人是活的
    Opportunity
        29
    Opportunity  
       2022-06-17 19:36:31 +08:00   ❤️ 1
    POST /xxx
    X-HTTP-Method-Override: GET

    { }

    按照 REST 规范应该是这么搞,尤其是有些代理服务器对 DELETE 之类方法支持不好的时候

    IBM 用的 x-method-override
    pengtdyd
        31
    pengtdyd  
       2022-06-17 19:42:04 +08:00
    @chendy 同意!规范是死的,如果 java 都按照阿里的 java 开发手册来,那估计大部分项目都要重构了
    sujin190
        32
    sujin190  
       2022-06-17 19:47:37 +08:00 via Android
    @TWorldIsNButThis 绝大部分库和软件的实现才叫规范,写在纸上的可不叫规范,别说其他了,浏览器估计都不支持 get 传 body
    ijse
        33
    ijse  
       2022-06-17 19:53:15 +08:00
    可以用 tj 的 npm 包:
    https://www.npmjs.com/package/qs

    nodejs 官方文档有介绍,这种基本算规范了吧
    https://nodejs.org/api/querystring.html
    kytrun
        34
    kytrun  
       2022-06-17 19:58:48 +08:00
    本质还是强迫症导致的。这么看:符合规范时你的接口叫 RESTful ,不符合规范叫接近 RESTful ,为了高效率工程化做出取舍,达到最佳状态,没毛病
    comoyi
        35
    comoyi  
       2022-06-17 20:38:31 +08:00
    进死胡同了就换大路走
    规范并不一定就是好的,一个规范不好用的时候就使用其他规范。
    之前也纠结过,多层级的参数该 POST 还是得用
    cedoo22
        36
    cedoo22  
       2022-06-17 20:42:02 +08:00
    emmm, 我在想,非得明文嘛, 直接参数格式化转 base64 ,后台在解一下。
    iseki
        37
    iseki  
       2022-06-17 20:42:46 +08:00 via Android
    别让自己难受…规范不合适的时候就别按规范做了
    lovedebug
        38
    lovedebug  
       2022-06-17 20:54:54 +08:00
    参考微软,谷歌规范,这一类情况应该用 POST, 微软和谷歌针对复杂情况扩展了 RESTful 方案
    类似 POST /v1/logs/:search Req Body {} 这样做适合你的情况,Path 最后是一个动作
    cutchop
        39
    cutchop  
       2022-06-17 21:22:22 +08:00
    我所有请求都用 POST
    dunhanson
        40
    dunhanson  
    OP
       2022-06-17 21:41:15 +08:00
    @chendy 以前就是这样,想改变下
    dunhanson
        41
    dunhanson  
    OP
       2022-06-17 21:42:18 +08:00
    @cedoo22 确实可以这样,以前也这么干过,但是不直观这种,想要看细节,还要 base decode 一下
    dunhanson
        42
    dunhanson  
    OP
       2022-06-17 21:43:32 +08:00
    @version0 是的,ES 这个问题我看别人在 github 的 issue 上面都吐槽了。
    dunhanson
        43
    dunhanson  
    OP
       2022-06-17 21:45:04 +08:00
    @XCFOX 估计普及没那么快
    dunhanson
        44
    dunhanson  
    OP
       2022-06-17 21:46:49 +08:00
    @kytrun
    @comoyi
    @iseki 哈哈哈 准备复杂查询用 POST 了
    Jooooooooo
        45
    Jooooooooo  
       2022-06-17 21:55:57 +08:00
    都扔进 post 的 body 里呀.

    你这这么复杂的请求体, 还强行用 get 要不得.
    Felldeadbird
        46
    Felldeadbird  
       2022-06-17 22:39:11 +08:00
    复杂体不要用 GET 。 或者将上面的 value 数值化,就是调试问题变得可读性奇差。
    DOLLOR
        47
    DOLLOR  
       2022-06-17 22:44:44 +08:00
    写在 body 不行,那就写在 http header 里面。
    可以把对象 base64 之后,写在自定义的请求报头里面(认真
    leonme
        48
    leonme  
       2022-06-17 22:45:12 +08:00 via iPhone
    @XCFOX 这都不是一个维度的东西……
    GeruzoniAnsasu
        49
    GeruzoniAnsasu  
       2022-06-17 22:48:17 +08:00
    你的接口是一个动作语义


    你已经不 restful 了


    趁早放弃残废的 restful 开始 post 一把梭还有救



    你可以美其名曰 lite-json-rpc
    Rocketer
        50
    Rocketer  
       2022-06-17 22:50:25 +08:00 via iPhone
    又见 RESTful 八股文。

    RESTful 根本没有确定的标准,只是一个大概的方向。你死抠细节……哪有细节让你抠?

    所以大概方向对,团队内部统一,好使,就行了。
    terranboy
        51
    terranboy  
       2022-06-17 22:53:57 +08:00
    qs 能行吗
    dddd1919
        52
    dddd1919  
       2022-06-18 00:08:25 +08:00
    参考 ElasticSeach 的结构化查询:
    POST /resources/_search
    sneezry
        53
    sneezry  
       2022-06-18 00:10:26 +08:00
    看其实这是个 query API ?为什么要设计成 GET 啊,是有什么限制吗
    hhyyd
        54
    hhyyd  
       2022-06-18 00:29:58 +08:00
    碰到过类似问题。我们当时的方案

    有直接用 get 传 body (楼上说可能有问题,这个我没碰到不清楚);

    也有直接拼 query ,虽然不好看但是容量限制很大,一般超不了;

    还有就是用 post ,个别复杂搜索接口用 post ,毕竟规矩是死的,人是活的,不要被限制死。
    guoqiao
        55
    guoqiao  
       2022-06-18 07:10:40 +08:00
    方法 1: 参数结构不要嵌套, 然后 url 参数是可以重复的,比如 /search?city=广州&city=深圳. 当然后端需要正确的解析.
    方法 2: GET 可以带 body, 相应的, 只要你的后端去读取 body 并解析就行了.
    方法 3: 用 POST, 代码的首要意义在于实现功能, 不必拘泥于繁文缛节.
    xuanbg
        56
    xuanbg  
       2022-06-18 08:51:14 +08:00
    @Chad0000 OCR 这个要先 POST 传图创建一个任务,然后根据返回的 id 把识别出来的内容 GET 回来啊。。。狗头保命。

    不过 OCR 还真的需要这样,这并不是为了 restful ,而是异步任务可以提高效率。
    yueye115
        57
    yueye115  
       2022-06-18 10:21:28 +08:00
    @dingyaguang117 正解, query 有长度限制, 而且 query 都是字符串, 没有其他类型吧. http 就是这么设计的, 你非要传个复杂对象去查, 只能说你就不符合 http 的规范.
    dunhanson
        58
    dunhanson  
    OP
       2022-06-18 11:02:05 +08:00
    @GeruzoniAnsasu
    @Rocketer
    @hhyyd
    @guoqiao 准备改成复杂的查询用 POST
    liyunlong41
        59
    liyunlong41  
       2022-06-18 12:19:42 +08:00 via iPhone
    我也遇到过这种,批量查询的 API ,uid 可能有几千个,直接用了 post
    dingyaguang117
        60
    dingyaguang117  
       2022-06-18 13:00:15 +08:00
    POST 有个问题是你这个查询链接就不可以分享了
    leoleoasd
        61
    leoleoasd  
       2022-06-18 13:29:02 +08:00
    这类查询,可以视为『创建一个查询请求』,用 POST 也合理
    LeegoYih
        62
    LeegoYih  
       2022-06-18 13:33:25 +08:00
    业务项目就不要考虑完美 restful 了
    bxb100
        63
    bxb100  
       2022-06-18 13:52:28 +08:00
    graphql 适合你
    saltbo
        64
    saltbo  
       2022-06-18 14:33:36 +08:00
    restful 是要在接口设计时就要按照规范来。也就是说 api 描述的是资源,不是动作,不是业务逻辑。你这接口 search 明显是个动作,直接就不符合 restful 规范,所以就别提 GET 不能传递复杂参数了。

    如果你这么设计 api ,就不要说什么 restful 了。或者自己定规范,或者用 GraphQL 。
    cheng6563
        65
    cheng6563  
       2022-06-18 15:08:21 +08:00
    @xuanbg 但是类似 webhook ,就是长时间阻塞请求当异步回调用的。。。
    Torpedo
        66
    Torpedo  
       2022-06-18 18:02:49 +08:00
    协议是不限制的,基本框架都可以。主要是浏览器的 get 不支持 body 。

    另外,按照 restful 写业务的,基本都妥协的挺多的
    evan1024
        67
    evan1024  
       2022-06-18 19:21:50 +08:00 via Android
    推荐先拿一个标准比如 openapi3 swagger2 定义
    fuxinya
        68
    fuxinya  
       2022-06-18 22:47:50 +08:00 via Android   ❤️ 1
    es 的查询请求就是传的 body ,而且是 get 请求
    erquiasz0825
        69
    erquiasz0825  
       2022-06-19 23:07:08 +08:00
    @TWorldIsNButThis 对,GET 方法没有规定说不能传 body ,但前端有些框架不支持,我之前也遇到过,就约定用 post 了。

    看到 elastic 官方文档对这个问题也有讨论:

    https://www.elastic.co/guide/cn/elasticsearch/guide/current/_empty_search.html
    erquiasz0825
        70
    erquiasz0825  
       2022-06-19 23:09:36 +08:00
    @fuxinya 根据 elastic 文档的说法,他们其实更倾向于 GET ,但由于某些框架不支持,所以同时支持 POST ,见楼上的链接
    dalianliyan
        71
    dalianliyan  
       2022-06-20 11:18:09 +08:00
    odata
    veike
        72
    veike  
       306 天前
    @cpstar GET /search/{searchWord}/{area}/{channel}/{pageSize}/,这种风格明显和 restful api 风格不符合,searchCondition 是规范里有明确提到?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1375 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 17:40 · PVG 01:40 · LAX 10:40 · JFK 13:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.