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

问个 RESTful API 设计的问题

  •  
  •   Orenoid ·
    Orenoid · 2019-03-28 10:25:17 +08:00 · 3210 次点击
    这是一个创建于 2052 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我现在想要对某个资源进行更新,路径 /path/to/resource 方法用 PUT 或者 PATCH
    这个资源有多个属性,例如 A、B、C 属性
    而我在不同场景下需要对不同属性进行更新,并且在业务上需要进行额外的判断,而不是简单的把前端给的值直接覆盖进去
    更复杂的情况可能还会有更新 A、B,或者更新 B、C 这种交错的情况,说白了就是一个资源上有多个场景下的更新逻辑
    这种情况下感觉在一个 URI 下很难实现啊,通过在接口里加字段来判断执行哪种逻辑的话,感觉本质上跟区分不同的 URI 没什么区别。。

    18 条回复    2019-03-29 15:08:31 +08:00
    alexmy
        1
    alexmy  
       2019-03-28 10:33:52 +08:00
    用 Graphql ? 之前看了看这东西,还没有实际应用。

    比如 两个用户共同关注的对象,这个...
    zivyou
        2
    zivyou  
       2019-03-28 10:42:56 +08:00
    我觉得这个 URI 设计的不合理,得定位到资源 A, B, 或 C。
    mcfog
        3
    mcfog  
       2019-03-28 10:45:32 +08:00 via Android
    一个 uri 用 patch, 传一个 array of business operation 进去就行了

    https://williamdurand.fr/2014/02/14/please-do-not-patch-like-an-idiot/
    FingerLiu
        4
    FingerLiu  
       2019-03-28 10:47:29 +08:00
    @alexmy graphQL 不是干这个事的。
    这个场景,感觉应该根据业务定义不同的 action
    mooncakejs
        5
    mooncakejs  
       2019-03-28 10:50:13 +08:00   ❤️ 1
    rest 不处理事务相关的,要不就是 abc 分开更新,要不就定一个组合的 resource 进行 patch
    ZSeptember
        6
    ZSeptember  
       2019-03-28 11:18:54 +08:00
    rest 这种所有操作都要对应资源还是不够用,明明是一个动作,就不要强行对应到一个资源上去了。
    index90
        7
    index90  
       2019-03-28 11:25:19 +08:00
    我觉得没有问题啊。
    PATCH 更新部分字段,PUT 更新所有字段,如果前端用 PATCH,他传什么属性就修改什么属性啊。问题在哪里?我没读懂
    index90
        8
    index90  
       2019-03-28 11:27:12 +08:00
    如果你是希望一个 URI 可以显式限定可修改字段,可以这样设计:
    PUT /path/to/resource/A,B // 修改 A,B 属性
    PUT /path/to/resource/B,C // 修改 B,C 属性
    wizardoz
        9
    wizardoz  
       2019-03-28 12:03:07 +08:00
    可能需要在 Restful API 之上再加一个业务层,提供业务 API。
    lhx2008
        10
    lhx2008  
       2019-03-28 12:07:47 +08:00 via Android
    是不是粒度太大了,如果有联动的操作的话,可以再细分二级的资源比较好
    MoHen9
        11
    MoHen9  
       2019-03-28 12:35:31 +08:00 via Android
    7 楼说的对
    hubqin
        12
    hubqin  
       2019-03-28 13:10:31 +08:00 via Android
    我们做过的一个是传个 type 参数,后端根据这个类型决定执行哪些操作。
    freakxx
        13
    freakxx  
       2019-03-28 17:05:01 +08:00
    Patch /path/to/resource/<id>/

    data :
    {
    "a" : "test",
    "b": "test"
    }

    ----
    Patch /path/to/resource/<id>/

    data :
    {
    "b" : "test",
    "c": "test"
    }


    在渲染层再做业务的处理
    Variazioni
        14
    Variazioni  
       2019-03-28 17:24:50 +08:00
    #7 没毛病。。
    mayorbryant
        15
    mayorbryant  
       2019-03-28 17:37:47 +08:00
    7 楼说了我想说的
    libook
        16
    libook  
       2019-03-29 10:23:54 +08:00   ❤️ 1
    REST 是围绕资源来设计的,而资源不一定是我们底层的数据结构;
    接口提现的不是数据,更多体现的是业务,所以简单粗暴把数据结构的 CRUD 直接作为 REST 接口来设计,会遇到很多问题。

    建议的思路是,将修改 A 和 B 与修改 B 和 C 看做两个业务,然后再抽象出一个或两个不同的资源,然后再以资源设计 API。

    比如底层 User 数据结构有 password、salt 这两个字段用来支持修改密码的业务,还有 company、job 用来支持修改工作信息的业务,那么可以抽象成密码和工作两个资源,各为一套接口。如果存在类似但不同的概念,为了避免歧义,可以分层,用户资源下面有密码和工作两个子资源。
    superZzr
        17
    superZzr  
       2019-03-29 10:32:06 +08:00
    #7 说的的确是没毛病,但是问题是,这样的不同业务场景识别,能放到前端去做么?
    index90
        18
    index90  
       2019-03-29 15:08:31 +08:00 via iPhone
    @superZzr 看 #16

    面向前端的接口要站在前端的角度去设计,所谓资源,也是前端角度的资源
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2884 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 02:25 · PVG 10:25 · LAX 18:25 · JFK 21:25
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.