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

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

  •  
  •   dunhanson · 56 天前 · 3886 次点击
    这是一个创建于 56 天前的主题,其中的信息可能已经有所发展或是发生改变。

    感觉进入了死胡同了

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

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

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

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

    { }

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

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

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

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


    你已经不 restful 了


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



    你可以美其名曰 lite-json-rpc
    Rocketer
        50
    Rocketer  
       55 天前 via iPhone
    又见 RESTful 八股文。

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

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

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

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

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

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

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

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

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

    https://www.elastic.co/guide/cn/elasticsearch/guide/current/_empty_search.html
    erquiasz0825
        70
    erquiasz0825  
       53 天前
    @fuxinya 根据 elastic 文档的说法,他们其实更倾向于 GET ,但由于某些框架不支持,所以同时支持 POST ,见楼上的链接
    dalianliyan
        71
    dalianliyan  
       53 天前
    odata
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2424 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 12:17 · PVG 20:17 · LAX 05:17 · JFK 08:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.