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

关于 HTTP 请求, POST 请求为什么有的接口还在 url 里传参数呢?

  •  1
     
  •   JieS · 2020-06-17 18:05:58 +08:00 · 7619 次点击
    这是一个创建于 1618 天前的主题,其中的信息可能已经有所发展或是发生改变。

    POST 可以直接将参数放在 body 里面,为什么多此一举呢? 或者什么情况下需要在 url 拼接参数呢?

    比如 POST body 是 json 格式,但又需要传 x-www-form-urlencoded 的时候?

    44 条回复    2020-06-21 09:25:42 +08:00
    myCupOfTea
        1
    myCupOfTea  
       2020-06-17 18:17:09 +08:00 via Android
    post 用 path var 倒是可以理解,还用 params 我不太能理解为啥要这么干
    halk
        2
    halk  
       2020-06-17 18:19:16 +08:00   ❤️ 19
    因为 HTTP 协议并没有禁止
    domybestFujian
        3
    domybestFujian  
       2020-06-17 18:19:42 +08:00
    因为偷懒
    shiny
        4
    shiny  
       2020-06-17 18:19:57 +08:00
    比如钉钉的设计,不管是 GET 还是 POST,AccessToken 都放 query string 中,风格保持统一。
    bitholic
        5
    bitholic  
       2020-06-17 18:21:00 +08:00 via iPhone
    Nginx 等比较好把 query string 打印出来
    GM
        6
    GM  
       2020-06-17 18:21:19 +08:00
    有时候这样比较方便。
    比如 /api/wtf?v=a 和 /api/wtf?v=b

    代码里可以根据 v 的值的不同,用不同版本的 handler 来处理 body 。
    zhuweiyou
        7
    zhuweiyou  
       2020-06-17 18:21:51 +08:00
    qs 和 body 又不冲突
    GM
        8
    GM  
       2020-06-17 18:22:12 +08:00
    补充上面:
    然后 handler 里就可以保持纯净,不需要做跟业务无关的判断。
    jinzhongyuan
        9
    jinzhongyuan  
       2020-06-17 18:25:09 +08:00
    @halk 应该是实现的库没有禁止哈
    misaka19000
        10
    misaka19000  
       2020-06-17 18:30:03 +08:00
    为什么晚上吃了肉还要吃蔬菜呢
    marquina
        11
    marquina  
       2020-06-17 18:40:00 +08:00 via Android
    @myCupOfTea path var 不就是 params 吗
    momocraft
        12
    momocraft  
       2020-06-17 18:44:28 +08:00   ❤️ 1
    什么叫多此一举,你 post 过除了 json 和 form 的东西吗

    > 9

    以 RFC 为准,http (包括 uri) 就是没有禁止,请不要自己加戏
    myCupOfTea
        13
    myCupOfTea  
       2020-06-17 18:56:03 +08:00   ❤️ 1
    @marquina 表达不清楚,pathParams 理解,queryParams 不理解
    xiangyuecn
        14
    xiangyuecn  
       2020-06-17 18:59:35 +08:00
    分析一下 HTTP 请求格式就知道了

    部分参数放 url 里,你就不用读取请求 input stream (这玩意往往是只能读一次),就能拿到某些必要的参数,用处很大的,不然 form 、file 、raw stream 等操作是要读取并解析 input stream 后才能拿到参数的
    myCupOfTea
        15
    myCupOfTea  
       2020-06-17 19:00:02 +08:00
    @misaka19000 主要 java spring 里面 一个是 @PathVariable,一个是 @RequestParam,说习惯了
    woodensail
        16
    woodensail  
       2020-06-17 19:03:37 +08:00
    做鉴权很有用。服务端可以在 option 请求过来的时候就把请求干掉,不需要接收 post 的请求体了。降低鉴权服务器的压力。
    ditel
        17
    ditel  
       2020-06-17 19:04:04 +08:00 via Android
    感觉上传文件又需要签名验证的时候
    lxz6597863
        18
    lxz6597863  
       2020-06-17 19:07:48 +08:00
    POST /api/user?username=abc

    { "age":1 }


    update user set age=1 where username=abc
    ai277014717
        19
    ai277014717  
       2020-06-17 19:16:09 +08:00
    @lxz6597863 应该用 put
    sadfQED2
        20
    sadfQED2  
       2020-06-17 19:17:20 +08:00 via Android   ❤️ 1
    只要你高兴,get 请求还能在 body 体里面传参呢
    wangyzj
        21
    wangyzj  
       2020-06-17 19:32:16 +08:00
    一种习惯吧
    我习惯 body 里面只提交数据
    不包括已有参数
    Jackeriss
        22
    Jackeriss  
       2020-06-17 19:37:05 +08:00
    想怎么传就怎么传,你甚至可以把参数写 header 里
    Vegetable
        23
    Vegetable  
       2020-06-17 19:37:28 +08:00   ❤️ 1
    @sadfQED2 #20 NO,这个不行。https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods/GET
    规范中 GET 方法是没有 BODY 的,如果你传了是有可能被某些实现丢弃的,属于规范禁止的行为。
    kidtest
        24
    kidtest  
       2020-06-17 19:42:27 +08:00
    nginx hash 可以用到
    mmdsun
        25
    mmdsun  
       2020-06-17 20:10:43 +08:00 via Android
    因为 body 里面大多是实体之类的映射的。

    像 accesstoken 统一要传的,不可能往实体里面扩展吧。

    这种要么放 URL,要么放 head 了。
    sadfQED2
        26
    sadfQED2  
       2020-06-17 20:34:52 +08:00 via Android
    @Vegetable 浏览器会丢掉,但是如果你只是实现 rpc 调用的话,也能带 body 体,比如 es 的 api 接口就支持 get 请求带 body 体
    ClericPy
        27
    ClericPy  
       2020-06-17 20:37:53 +08:00
    1. 设计
    2. 日志分析
    3. 历史遗留
    liut2016
        28
    liut2016  
       2020-06-17 20:44:45 +08:00 via Android
    @GM 那可以把版本信息放在 path 里啊
    rioshikelong121
        29
    rioshikelong121  
       2020-06-17 21:07:56 +08:00
    为什么不行呢?有的参数我觉得完全可以放在 querystring 里面。
    EminemW
        30
    EminemW  
       2020-06-17 21:23:35 +08:00
    我把 token 放在 queryString
    yukiloh
        31
    yukiloh  
       2020-06-17 21:27:25 +08:00
    我刚用 axios 的时候控制不好,经常就是想传个 json,结果传到 path 上
    jerry
        32
    jerry  
       2020-06-17 21:31:54 +08:00 via iPhone
    比如全局参数
    JieS
        33
    JieS  
    OP
       2020-06-17 21:38:18 +08:00 via iPhone
    @momocraft 不懂就问,激动个什么寂寞?
    DOLLOR
        34
    DOLLOR  
       2020-06-17 21:54:43 +08:00
    有些中转代理工具处理 url 比 body 方便一些。
    当然,更多的是保持 get 和 post 风格统一,action 之类的参数就直接写在 url search 里了。
    otakustay
        35
    otakustay  
       2020-06-17 22:04:49 +08:00
    你看嘛,一个 HTTP 请求的 URL 放在第一行的
    然后 body 可能是很大的,甚至可能是一个文件,所以 body 有可能是流式处理的
    这也就代表着,如果你需要将一个请求分配到一个具体的函数上去的话,等 body 全部解析完是很慢的也很没必要的
    举个例子,body 是一个文件流的话,只要我分配到了“把文件存起来”这个函数上,这个函数就可以把 body 流对接到 file 流。但如果我没办法分配到函数上,我就要等 body 流读完,把这个流放在内存里(假设内存没爆掉),然后解析 body 分析函数,把整个内存里的流给它,它再存到文件里,这效率多低啊
    所以一些参数放在 URL 是非常合理的,特别是用来鉴权的、判断路由的等等
    当然我可以不用 URL 而用 HTTP 头,但 HTTP 头的危险性在于你不知道中间有哪个 SB 一样的代理自说自画给你改了或者弄丢了……
    jiangzm
        36
    jiangzm  
       2020-06-17 22:07:30 +08:00
    这有啥不能理解的,POST 请求中 url 有 query params 一般和接口结构相关,body 里面一般放业务相关的参数。 这好理解了没。
    @JieS @myCupOfTea
    Vegetable
        37
    Vegetable  
       2020-06-17 22:55:36 +08:00
    @sadfQED2 #26 没错呀,还有些骚的不行的也能自定义 HTTP 方法,规范毕竟只是一种规范,不推荐这么用大家还是别太奔放的好,如果两边都可控的话怎么玩都行
    also24
        38
    also24  
       2020-06-17 23:18:34 +08:00
    今天还在和朋友说,GET 请求也是可以传 body 的啊,RFC 里面并没有禁止这么做 hhh
    myCupOfTea
        39
    myCupOfTea  
       2020-06-18 09:22:43 +08:00
    @also24 但实际上那天你的小伙伴升级成 fetch 来请求,就全部报错了
    wangyanrui
        40
    wangyanrui  
       2020-06-18 09:26:42 +08:00
    方便且团队中大多数人认可,就可行!
    weixiangzhe
        41
    weixiangzhe  
       2020-06-18 10:17:01 +08:00 via Android
    querystring 有长度限制啊, 放 body 里好
    GM
        42
    GM  
       2020-06-18 12:14:17 +08:00
    @liut2016
    放 path 上跟放 querystring 没有本质区别,都是把一些参数单独放外面不放 body 里,而且有些框架不支持 path 参数。
    GM
        43
    GM  
       2020-06-18 12:15:21 +08:00
    @ai277014717 put,语义是用提交的数据替换目标对象,你这么做的话 username 就没了
    liut2016
        44
    liut2016  
       2020-06-21 09:25:42 +08:00 via Android
    @GM rustfull 吧。querysyribng 是用了查询的,post 是推数据的,一般这两个应用场景不重叠
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1292 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 23:37 · PVG 07:37 · LAX 15:37 · JFK 18:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.