前后端 api 接口 url 格式问题讨论 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
pandazhong123
V2EX    程序员

前后端 api 接口 url 格式问题讨论

  •  1
     
  •   pandazhong123 2023-09-08 11:48:39 +08:00 5166 次点击
    这是一个创建于 771 天前的主题,其中的信息可能已经有所发展或是发生改变。

    公司的前后端 api 接口统一用 post,对于添加删除用户,是用 /user/add /user/delete 比较好,还是用 /add/user /delete/user 比较好?

    82 条回复    2023-09-09 20:57:25 +08:00
    dumbass
        1
    dumbass  
       2023-09-08 11:50:29 +08:00
    我倾向于前者,虽然我是前端,不关心后端怎么设计接口。
    hervey0424
        2
    hervey0424  
       2023-09-08 11:50:57 +08:00
    我觉得/user/add 比较好, 或者 user_add
    pandazhong123
        3
    pandazhong123  
    OP
       2023-09-08 11:52:16 +08:00
    /add/user 这种阅读起来不是更自然吗?
    @bojackhorseman
    233373
        4
    233373  
       2023-09-08 11:53:00 +08:00
    参考下 JSON-RPC 的格式吧,把行为放在 URL 里面确实不太好
    shakukansp
        5
    shakukansp  
       2023-09-08 11:54:30 +08:00   12
    @pandazhong123 /add/user 会被人觉得你所有乱七八糟的 add 都往这下面塞
    /user/add 说明就是 user 的增删改查
    IvanLi127
        6
    IvanLi127  
       2023-09-08 11:57:12 +08:00 via Android
    前者。
    或者你想要 add user 的顺序,路径可以叫 /add-user
    libook
        7
    libook  
       2023-09-08 12:00:23 +08:00
    都可以,估计要把所有接口都列出来,然后才能知道用哪种方式组织开发起来更方便。

    现在很多是倾向于微服务和 REST 风格设计,所以以资源为主体,其次是围绕资源的各种操作,所以倾向于前者。

    但不同项目的情况可能有很大差异的,没有一种适用所有情况的方案。
    lopda
        8
    lopda  
       2023-09-08 12:03:23 +08:00
    主区分模块(谁
    谓区分行为(做什么

    所以我也倾向于 user/add 这种
    lopda
        9
    lopda  
       2023-09-08 12:04:33 +08:00
    @lopda 对于前端来说,api 请求分模块文件的时候也更清晰点。
    pandazhong123
        10
    pandazhong123  
    OP
       2023-09-08 12:09:20 +08:00
    OK ,看来大家都是主张用/user/add 这种格式,我们也采用这种格式了,谢谢大家。
    xiangyuecn
        11
    xiangyuecn  
       2023-09-08 12:10:44 +08:00
    /user/addUser
    /user/deleteUser
    pandazhong123
        12
    pandazhong123  
    OP
       2023-09-08 12:11:41 +08:00
    @xiangyuecn 这种格式看起来有点冗余了。
    xiangyuecn
        13
    xiangyuecn  
       2023-09-08 12:15:15 +08:00   2
    @pandazhong123 等你调试的时候看浏览器控制台 Network 面板,就会知道这种越完整的越有多香了
    nothingistrue
        14
    nothingistrue  
       2023-09-08 12:22:47 +0800   10
    RESTful 风格添加:POST /user ,删除 DELETE /user 或者 DELETE /user/{id}。
    nothingistrue
        15
    nothingistrue  
       2023-09-08 12:29:11 +08:00   2
    两个都不对。/user/add 是画蛇添足。/add/user 是分组错误。

    RESTful 风格
    添加:POST /user 。删除 DELETE /user 或者 DELETE /user/{id}。如果是一般动作,那就是 POST /user/{id}/%动词%
    ,比如 POST /user/{id}/disable 。
    仅 POST 风格
    添加:/addUser ,或者/user/addUser 。删除:/deleteUser ,或者/user/deleteUser 。对于后面那个,/user 只是用来分组的,不参与接口命名。
    chendy
        16
    chendy  
       2023-09-08 12:50:47 +08:00
    方法全部 post ,url 格式是 名词 / 动词,动词不限于增删改查,名词放前面是因为名词的区分度更高
    rest 是死的,人是活的,硬 rest 得不偿失,命名规范统一易于理解就好
    flyqie
        17
    flyqie  
       2023-09-08 12:54:25 +08:00 via Android   1
    /add/user /delete/user

    这都是什么邪门路径。。

    你这么玩的话,后续路由分组这块怎么做?
    caocong
        18
    caocong  
       2023-09-08 12:54:42 +08:00
    全 post
    /user/addUser
    /user/deleteUser
    +1
    flyqie
        19
    flyqie  
       2023-09-08 12:55:24 +08:00 via Android
    @flyqie #17

    倾向/user/add /user/delete 这种方式
    HAYWAEL
        20
    HAYWAEL  
       2023-09-08 13:08:27 +08:00
    肯定是 /user/add /user/delete 不然 你之后后端代码怎么组织,面向对象
    radiocontroller
        21
    radiocontroller  
       2023-09-08 13:15:30 +08:00
    GET /users 用户列表
    radiocontroller
        22
    radiocontroller  
       2023-09-08 13:15:40 +08:00
    radiocontroller
        23
    radiocontroller  
       2023-09-08 13:16:56 +08:00
    restful
    GET /users 用户列表
    POST /users 新增用户
    GET /users/{id} 用户详情
    PATCH /users/{id} 更新用户
    DELETE /users/{id} 删除用户
    ktqFDx9m2Bvfq3y4
        25
    ktqFDx9m2Bvfq3y4  
       2023-09-08 13:18:32 +08:00
    两种风格都可:

    /user/add
    /user/delete

    post /user
    delete /user/{userId}
    clf
        26
    clf  
       2023-09-08 13:21:13 +08:00
    @radiocontroller #23 RESTFUL 除非是自己的 SSAS 系统,那随便用,交付给客户的还是用 GET 和 POST 。避免遇到客户的安全策略禁了一堆请求方法。

    ----

    /user/add /user/delete 肯定会更好,还有一种是 user/add_user user/delete_user
    gesse
        27
    gesse  
       2023-09-08 13:42:45 +08:00
    推荐 easydoc 的启蒙系列文章
    https://easydoc.net/a/api-design/
    Pastsong
        28
    Pastsong  
       2023-09-08 13:46:03 +08:00
    /user:add

    /user/add 会和 /user/{userId} 或者 /user/{userName} 冲突,万一有用户叫 add 呢
    theqiang
        29
    theqiang  
       2023-09-08 13:46:20 +08:00
    @nothingistrue #15 人家说了用 POST.....
    hidemyself
        30
    hidemyself  
       2023-09-08 13:47:06 +08:00
    上面有 RESTful 风格的 api
    我想问下,
    根据用户 id 删除用户是 DELETE user/{id}
    如果我有个接口是根据用户手机号删除用户,应该怎么命名
    worldqiuzhi
        31
    worldqiuzhi  
       2023-09-08 13:49:35 +08:00   1
    上次 v 站刚有一个用非 POST 方法过等保被拒的 GET /users 用户列表
    POST /users 新增用户
    GET /users/{id} 用户详情
    PATCH /users/{id} 更新用户
    DELETE /users/{id} 删除用户
    lanlanye
        32
    lanlanye  
       2023-09-08 13:56:36 +08:00   1
    全 POST 的话我也有个邪道做法:

    POST '{prefix}/users/{id}' \
    --data-raw '{"method": "DELETE", "data": null}'
    PiersSoCool
        33
    PiersSoCool  
       2023-09-08 14:15:25 +08:00
    都可以

    风格差不多一致就行

    就怕不一致的
    coderxy
        34
    coderxy  
       2023-09-08 14:16:59 +08:00
    有的后端是微服务, 按照 /user /post 这样的前缀去分发服务的。 这种你就只能按照后端规则来了。
    estk
        35
    estk  
       2023-09-08 14:29:20 +08:00
    tRPC 让前后端一起闭嘴
    Crapulence
        36
    Crapulence  
       2023-09-08 14:32:58 +08:00
    第一种 可以一眼看到针对 user 下的资源进行操作
    yugali
        37
    yugali  
       2023-09-08 14:37:19 +08:00
    @hidemyself 根据手机号找到用户,然后 DELETE user/{id}
    johnnyNg
        38
    johnnyNg  
       2023-09-08 14:41:33 +08:00
    post,然后 data 里面包含 path 、method
    arfaWong
        39
    arfaWong  
       2023-09-08 14:42:09 +08:00
    @hidemyself #30 问的 chatgpt

    根据 RESTful 风格的 API 设计原则,您可以将根据用户手机号删除用户的接口进行命名。以下是一个可能的命名方案:

    DELETE /user/phone/{phoneNumber}

    在上述命名中,您可以使用"user"作为资源的基本路径,然后使用"phone"来指示后续路径是基于用户手机号进行操作。最后,使用"{phoneNumber}"作为占位符表示要删除的具体手机号。
    cdwyd
        40
    cdwyd  
       2023-09-08 14:42:35 +08:00 via Android
    第一种更舒服些,把要操作的对象统一放到了最前面,写文档的时候看起来也更好看一点
    corcre
        41
    corcre  
       2023-09-08 14:47:12 +08:00
    要是在我们公司按照第二种命名风格那多大的项目都只有增删改查这 4 个 controller
    G2bN4dbX9J3ncp0r
        42
    G2bN4dbX9J3ncp0r  
       2023-09-08 14:50:49 +08:00
    @worldqiuzhi 正解
    leonshaw
        43
    leonshaw  
       2023-09-08 15:02:02 +08:00
    @hidemyself #30 DELETE users?phOne=xxx
    应该问其它操作应该怎么办(比如通过验证码激活用户)。
    key0323
        44
    key0323  
       2023-09-08 15:35:44 +08:00
    楼主都说了公司要求 post 一群不审题的迫不及待的把自己 rest 知识秀出来
    george2077
        45
    george2077  
       2023-09-08 15:47:59 +08:00
    用 /user/add 和 /user/delete 这种格式,更符合 RESTful API 的设计原则,资源的层级结构,可读性和扩展性,都要更好
    frank42a
        46
    frank42a  
       2023-09-08 15:50:10 +08:00
    全套 POST 本身就反智
    duanzhangplus
        47
    duanzhangplus  
       2023-09-08 15:55:50 +08:00
    等你后续需求是匹配 URL 做 trace 、鉴权 的时候你就发现 /user/* 是非常好的方式
    zx9481
        48
    zx9481  
       2023-09-08 16:02:38 +08:00
    为什么那么多公司做前后端分离项目后端响应的 HTTP 状态一律 200 ? - 知乎
    https://www.zhihu.com/question/513865370/answer/2331933561
    zx9481
        49
    zx9481  
       2023-09-08 16:02:56 +08:00   1
    @zx9481 post+json 团队都下班回家抱老婆了,restful 原教旨主义团队还在加班查错,还拉着运维陪他们。
    irrigate2554
        50
    irrigate2554  
       2023-09-08 16:03:41 +08:00
    区分度都放到后面,否则倒是上线看浏览器的 Network 全是 /user 200 xhr
    lambdaq
        51
    lambdaq  
       2023-09-08 16:06:09 +08:00
    @nothingistrue 那么问题来了,批量删除怎么搞?
    sanqian
        52
    sanqian  
       2023-09-08 16:07:28 +08:00
    你要简单点的话 还是
    /user/add
    /user/delete
    你得考虑路由啊
    35aZ4P8mT576683q
        53
    35aZ4P8mT576683q  
       2023-09-08 16:15:09 +08:00
    用 REST 居然不用 HTTP method 我很难理解

    又不是 GraphQL
    sankooc
        54
    sankooc  
       2023-09-08 16:20:59 +08:00
    这个肯定是前者好吧
    tramm
        55
    tramm  
       2023-09-08 16:37:32 +08:00
    肯定前者吧...
    除非你把不同功能的 add 全写在一个 controller 中
    liuidetmks
        56
    liuidetmks  
       2023-09-08 16:42:13 +08:00
    又到了月经周期了吗
    XueXianqi
        57
    XueXianqi  
       2023-09-08 16:42:18 +08:00
    我的建议:
    遵循 RESTful 规范,根据 URL+Method 进行组合


    POST /user 新增用户
    DELETE /user/{user_id} 删除用户
    UPDATE /user/{user_id} 更新用户(全局字段)
    PATCH /user/{user_id} 更新用户(局部字段)
    GET /user/{user_id} 用户详情
    GET /user 用户列表
    avax
        58
    avax  
       2023-09-08 16:49:43 +08:00
    @xiangyuecn #13 Path 去掉,勾选上 Name 即可,一目了然
    edotac
        59
    edotac  
       2023-09-08 16:49:52 +08:00
    post+json 团队都下班回家抱老婆了,restful 原教旨主义团队还在加班查错,还拉着运维陪他们。
    gogolive
        60
    gogolive  
       2023-09-08 16:50:38 +08:00
    目录由大到小比较合适
    user 是大目录,后面不只有 add ,还有其他的 like 等
    simo
        61
    simo  
       2023-09-08 16:57:40 +08:00
    团队共识就可,可以参考通用做法,有人发文章了。
    如果多了解一下其他协议的业务通信设计,理解不同,自由度会更高
    zhch602
        62
    zhch602  
       2023-09-08 17:01:14 +08:00
    现在又有人在用 RESTful 么
    x86
        63
    x86  
       2023-09-08 17:02:14 +08:00
    说句难听的,培训机构都没这么水教这种写法
    ```
    /add/user
    /delete/user
    ```
    nothingistrue
        64
    nothingistrue  
       2023-09-08 17:03:18 +08:00
    @theqiang #28 按下 SHIFT+ENTER 换行,结果直接提交回复了,下面一楼才是完整回复。但是好多人好像只看到我这个半回复,没看下面的完整回复。

    @hidemyself #29
    DELETE /user?phOne=xxx 跟「根据用户手机号查询用户列表」,是一样的套路。

    @george2077 #44 /user/add /user/delete 并不符合 RESTful API 的设计原则。RESTful API 的基准原则就是,URL 仅表示资源路径故只能是名词或者等效于名词的东西,GET/POST/PUT/PATCH/DELETE 这几个 method 才能表示动作。所以只能是 POST /user ,DELETE/user 。(单复数我忘了,好像应该是复数形式。)如果你用/user/add ,最经典的问题就是 @Pastsong #27 提到的 /user/{id}冲突。但他的 /user:add 这样也不对。

    严格 RESTful API 有一个经典缺点,就是 GET/POST/PUT/PATCH/DELETE 动作不够,无法表示其他方法。当你采用领域模型来设计接口的时候,这个确定会更突出,因为领域模型在增删该查之外会有大量的其他行为方法。这个在后面单独说。

    @lambdaq #50 根据 ID 批量删除:DELETE /user?id=xx,xx,xx 。根据条件(批量)删除:DELETE /user?cOndition=xxx
    liuzhaowei55
        65
    liuzhaowei55  
       2023-09-08 17:09:39 +08:00 via Android
    post /module/action
    离那个所谓的 restful 远一点就对了
    lambdaq
        66
    lambdaq  
       2023-09-08 17:13:54 +08:00
    @nothingistrue 那为啥不直接 POST /user/delete 。。。。
    codehz
        67
    codehz  
       2023-09-08 17:24:20 +08:00
    快进到直接 graphql ,在 body 里 mutation { deleteUser(id: "xxx") { result } }
    nothingistrue
        68
    nothingistrue  
       2023-09-08 17:31:16 +08:00
    关于 RESTful API 如何表示领域行为方法,这个我也是抄别人的,就直接贴链接了。
    原文(也是翻译老外的)链接: https://mp.weixin.qq.com/s/251ql2WhDi-InUgVtIQ6_Q
    我看的是转发: https://blog.didispace.com/use-ddd-design-rest-api/
    请注意,这也是违反 RESTful 的,需要有全局约定才能这么做。他并不存在冲突,因为 PUT /resources/{id}/action 是专有的 URI (原本的 PUT 因为是修改指定资源,其 URL 形式必定是 PUT /resources-level1/{id}/resources-level2/{id}的形式。)

    关于 REST 的参考: https://restfulapi.net/resource-naming/

    关于单复数的部分,需要纠正,REST 接口,资源必须定义成复数,因为单数名词有特殊含义,他是定义可选的前置分组的。当然,这是个认为约定,不是强制规定。如果约定好,全部单数也不是问题。

    再纠正一下 14 楼的回复。「如果是一般动作,那就是 POST /user/{id}/%动词%,比如 POST /user/{id}/disable 。」是错误的。应改为「如果是一般动作,那就是 PUT /users/{id}/%动词%,比如 PUT /users/{id}/disable 。」因为这个动作,是对当前资源的修改,不是新增资源。
    tairan2006
        69
    tairan2006  
       2023-09-08 17:36:07 +08:00
    全 post 的话,动词放最后,get/list/create/update/delete

    其实和 Rest 没啥区别……
    zorui
        70
    zorui  
       2023-09-08 17:37:46 +08:00
    @hidemyself DELETE /user/phonenumber/{phonenumber} ? 或者参数放进 body 中
    nothingistrue
        71
    nothingistrue  
       2023-09-08 17:39:56 +08:00
    @lambdaq #65 会跟新增 「 user 」 的 「 delete 」 冲突。
    sgiyy
        72
    sgiyy  
       2023-09-08 17:40:58 +08:00
    op 工作经验超过一年吗?
    pandazhong123
        73
    pandazhong123  
    OP
       2023-09-08 17:42:02 +08:00
    @x86 哈哈,从 C++转到 web 开发的,对这 Web 不熟。
    其实我还有其他疑问,在 url 中,是 bookDetail 比较好,还是 book_detail,还是 book-detail?
    lambdaq
        74
    lambdaq  
       2023-09-08 17:46:43 +08:00
    @pandazhong123 你扮演一个需要分析服务器访问日志,随时准备骂娘的角色, 就知道哪种 URL 好了。
    blackkkk
        75
    blackkkk  
       2023-09-08 17:47:56 +08:00
    一般是/分组 or 模块/对应操作--》/user/add or /user/addUser ,冗余在这里并不是什么问题,更便于理解,因为在 user 下可能不止 user 一个操作,比如用户和其他的映射等信息。
    ElvY
        76
    ElvY  
       2023-09-08 18:55:50 +08:00
    毫无疑问前者。和命名相同逻辑,后者绝壁要挨打。
    nothingistrue
        77
    nothingistrue  
       2023-09-08 20:13:23 +08:00
    @pandazhong123 #72 如果是面向传统前端的标准 URL ,或者 RESTful ,或者是公开接口,那么应当是 book-detail 。URL 在部分场景(比如 Windows IIS 当服务器),是不区分大小写的。下划线则是在部分字体或者 UI 下,容易看不见。如果仅面向当前项目的前端,那就看团队习惯,对于全 Java 系开发来说,bookDetail 更舒适。
    kkk9
        78
    kkk9  
       2023-09-09 03:19:24 +08:00
    随便后端怎么写,随便前端怎么 mock ,最后都是要在网关那边 rewrite 的,这种东西团队内部 ok 就行了。

    /user/add /模块/动作
    jeesk
        79
    jeesk  
       2023-09-09 08:57:10 +08:00
    用 grpc web ,没有争论。 有这时间,不如多优化一下代码。
    flyqie
        80
    flyqie  
       2023-09-09 10:17:40 +08:00 via Android
    @kkk9 #78

    那/add/user 这种情况就变成网关要骂娘了。。
    kkk9
        81
    kkk9  
       2023-09-09 20:48:48 +08:00
    @flyqie #80 怎么会骂娘呢 VwV ,明明是互相帮助,增加 KPI
    SoloCompany
        82
    SoloCompany  
       2023-09-09 20:57:24 +08:00
    @nothingistrue #77 不要误导别人, 无论是什么环境, 不存在说 web 服务大小写强制不敏感的问题, 你可以说 IIS 的路由分配有可能大小写不敏感, 但如果是你自己写的即使是 cgi 代码, 只要是程序自己接管的路由, 不存在无法区分大小写的问题
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2689 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 49ms UTC 14:19 PVG 22:19 LAX 07:19 JFK 10:19
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86