API接口应该如何设计,应该包含哪些信息,怎样设计才能有更好的扩展,更容易理解,更好的后期维护呢?

我们以一个登录接口为例,看应该如何设计接口名才更合适。
最简单的,我们可以设计为:/login,这样的设计在系统非常简单时没有任何问题,但是出现多个系统都有登录接口时就有冲突了。
例如一个复杂点的系统,通常会涉及到:APP登录,管理后台登录,公众号登录。
这些都属于不同的系统,他们都有登录接口。
这时候我们可以在接口增加系统类型,把接口设计为:/app/login/admin/login/xxx/login,这样一看就知道是什么系统了。
如果不用区分系统类型,我们直接写/api/login也行

但是随着系统的不断迭代,登录接口需要重写,例如参数变动,或者手机号登录改为了QQ登录等。
为了兼容之前的用户,我们不应该直接修改之前的接口,而是重新写一个新的接口,重新写接口时,我们就不能再使用跟原来一样的名字了:/app/login

可能有些人会使用/app/login2/app/login-new这类命名方案,但是更好的解决方案是在接口中增加版本号,所以更好的接口方案是:/app/v2/login
我们在接口中增加了版本号,每次迭代这个接口就增加一个版本号,通过接口名就能清晰的知道是新接口。
接口中加版本号是特别有用的,特别是在一些对外的接口,可能经常需要迭代升级。

例如下图中腾讯云的 IM 的接口,就是带了版本号,显然他这是第四次迭代的接口。文档地址
api接口中带版本号

现在我们的接口是/app/v2/login,已经没问题了吗?还有一个需要改进的地方。
一个复杂点的系统,通常都包含多个功能模块,例如一个社交App,通常包含:好友、群组等不同模块。
这两个模块里面都会有添加用户的操作:添加好友、添加群成员。
直接点,我们可以把接口命名为:/app/v1/add-friend/app/v1/add-group-member
更好的方式是在接口中直接区分不同模块:/app/v1/friend/add/app/v1/group/add-member
这样我们就很容易通过接口区分不同模块,也可以避免不同模块的接口命名冲突。

另外,统一的接口命名规范,还有利于服务端 nginx 根据接口前缀做请求转发,可以把不同版本的接口转发到不同服务器或者不同进程去执行。

最后我们总结下就是,为了更好的扩展性、可读性,API的结构可以这样:
/{系统类型或者api}/{版本号}/{功能模块}/{具体操作}

举例:
App登录:/app/v1/user/login
管理后台登录:/admin/v1/user/login
创建群:/app/v1/group/create
群列表:/app/v1/group/list
加好友:/api/v1/friend/add
发送聊天消息:/api/v2/chat/send