REST,全拼为 Representational State Transfer,或者说 ReSTful API 是一套系统化约定的风格集合,既不是协议也不是标准,只是一种风格。API 开发者可以有不同的实现方式,这就意味者 API URI 中路径(Path)、QueryString 请求参数和请求体参数命名风格,也可以有多种选择。那么,那种命名风格最好呢?
例如,如果我们提供一个 API 返回 Hello World! 信息,可选的风格可能有如下几种:
- 小驼峰:
https://zqfan.cc/api/v1/helloWorld - 大驼峰:
https://zqfan.cc/api/v1/HelloWorld - 全小写:
https://zqfna.cc/api/v1/helloworld - 下划线:
https://zqfan.cc/api/v1/hello_world - 横杠:
https://zqfan.cc/api/v1/hello-world 
答案也很简单,任意选一个,并贯彻到所有接口就可以了。但是知易行难,这并不是一件容易的事情。
我们挑选比较有名的商业云计算代表 AWS 和 开源云计算代表 OpenStack 两家的 API 分析一下。
AWS S3 API
AWS S3 API 几乎是对象存储领域的业界标准了,其他厂商提供对象存储服务的时候,是否兼容 AWS S3 API 是用户 的一大诉求。我们将目前(2023-02-27)S3 所有 API 分类如下:
一元单词,无法区分风格的(注意,由于 REST API 本身没有名称,此处仅为代称):
- CopyObject
 - CreateBucket
 - CreateMultipartUpload
 - DeleteBucket
 - DeleteBucketAnalyticsConfiguration
 - DeleteBucketCors
 - DeleteBucketEncryption
 - DeleteBucketInventoryConfiguration
 - DeleteBucketLifecycle
 - DeleteBucketMetricsConfiguration
 - DeleteBucketPolicy
 - DeleteBucketReplication
 - DeleteBucketTagging
 - DeleteBucketWebsite
 - DeleteObjects
 - GetBucketAccelerateConfiguration
 - GetBucketAcl
 - GetBucketAnalyticsConfiguration
 - GetBucketCors
 - GetBucketEncryption
 - GetBucketInventoryConfiguration
 - GetBucketLifecycle
 - GetBucketLifecycleConfiguration
 - GetBucketLocation
 - GetBucketLogging
 - GetBucketMetricsConfiguration
 - GetBucketNotification
 - GetBucketNotificationConfiguration
 - GetBucketPolicy
 - GetBucketReplication
 - GetBucketTagging
 - GetBucketVersioning
 - GetBucketWebsite
 - GetObjectTorrent
 - HeadBucket
 - ListBuckets
 - PutBucketAccelerateConfiguration
 - PutBucketAcl
 - PutBucketAnalyticsConfiguration
 - PutBucketCors
 - PutBucketEncryption
 - PutBucketInventoryConfiguration
 - PutBucketLifecycle
 - PutBucketLifecycleConfiguration
 - PutBucketLogging
 - PutBucketMetricsConfiguration
 - PutBucketNotification
 - PutBucketNotificationConfiguration
 - PutBucketPolicy
 - PutBucketReplication
 - PutBucketTagging
 - PutBucketVersioning
 - PutBucketWebsite
 - PutObject
 
小驼峰风格,共计:
- AbortMultipartUpload, uploadId
 - CompleteMultipartUpload, uploadId
 - DeleteBucketOwnershipControls, ownershipControls
 - DeleteObject, versionId
 - DeleteObjectTagging, versionId
 - DeletePublicAccessBlock, publicAccessBlock
 - GetBucketOwnershipControls, ownershipControls
 - GetBucketPolicyStatus, policyStatus
 - GetBucketRequestPayment, requestPayment
 - GetObjectAcl, versionId
 - GetObjectAttributes, versionId
 - GetObjectRetention, versionId
 - GetObjectTagging, versionId
 - GetPublicAccessBlock, publicAccessBlock
 - HeadObject, partNumber, versionId
 - PutBucketOwnershipControls, ownershipControls
 - PutBucketRequestPayment, requestPayment
 - PutObjectAcl, versionId
 - PutObjectRetention, versionId
 - PutObjectTagging, versionId
 - PutPublicAccessBlock, publicAccessBlock
 - RestoreObject, versionId
 - UploadPart, partNumber, uploadId
 - UploadPartCopy, partNumber, uploadId
 
横杠风格,共计:
- DeleteBucketIntelligentTieringConfiguration, intelligent-tiering
 - GetBucketIntelligentTieringConfiguration, intelligent-tiering
 - GetObjectLockConfiguration, object-lock
 - ListBucketAnalyticsConfigurations, continuation-token
 - ListBucketIntelligentTieringConfigurations. intelligent-tiering, continuation-token
 - ListBucketInventoryConfigurations, continuation-token
 - ListBucketMetricsConfigurations, continuation-token
 - ListMultipartUploads, encoding-type, key-marker, max-uploads, upload-id-marker
 - ListObjects, encoding-type, max-keys
 - ListObjectsV2, list-type, continuation-token, encoding-type, fetch-owner, max-keys, start-after
 - ListObjectVersions, encoding-type, key-marker, max-keys, version-id-marker
 - PutBucketIntelligentTieringConfiguration, intelligent-tiering
 - PutObjectLockConfiguration, object-lock
 - SelectObjectContent, select-type
 
小驼峰和横杠混合风格,共计:
- GetObject, partNumber, versionId, response-cache-control, response-content-disposition, response-content-encoding, response-content-language, response-content-type, response-expires
 - GetObjectLegalHold, versionId, legal-hold
 - ListParts, uploadId, max-parts, part-number-marker
 - PutObjectLegalHold, versionId, legal-hold
 
大驼峰风格,共计:
- WriteGetObjectResponse, WriteGetObjectResponse
 
可以看到,小驼峰和横杠风格的大致相同,并且有个别接口两者都出现了(均为请求参数),此外还有极个别的大驼峰参数。
阅读 AWS S3 API 文档还能够发现,许多接口将一些参数定义在 HTTP 头部中,同时也有其他参数定义在 URI 和请求体中。出现在 HTTP 头部的参数基本为全小写横杠分隔(x-amz-前缀,HTTP 标准头部则为大驼峰横杠分隔),但也有例外 GetObject 出现大驼峰和横杠的头部。涉及到术语 MD5 时,采用的是大写,但其他术语又是全小写,如 sdk,mfa,sha1。出现在请求体中的均为大驼峰。
AWS S3 Control API
我们再看看 AWS S3 Control API,分析发现:
一元单词,无法区分风格,共计:
- CreateBucket
 - CreateJob
 - DeleteBucket
 - DeleteBucketPolicy
 - DeleteBucketTagging
 - DeleteJobTagging
 - DescribeJob
 - GetBucket
 - GetBucketPolicy
 - GetBucketTagging
 - GetBucketVersioning
 - GetJobTagging
 - GetMultiRegionAccessPoint
 - GetMultiRegionAccessPointPolicy
 - GetMultiRegionAccessPointRoutes
 - PutBucketPolicy
 - PutBucketTagging
 - PutBucketVersioning
 - PutJobTagging
 - UpdateJobPriority
 
全小写风格,共计:
- CreateAccessPoint
 - CreateAccessPointForObjectLambda
 - DeleteAccessPoint
 - DeleteAccessPointForObjectLambda
 - DeleteAccessPointPolicy
 - DeleteAccessPointPolicyForObjectLambda
 - DeleteBucketLifecycleConfiguration
 - DeleteStorageLensConfiguration
 - DeleteStorageLensConfigurationTagging
 - GetAccessPoint
 - GetAccessPointConfigurationForObjectLambda
 - GetAccessPointForObjectLambda
 - GetAccessPointPolicy
 - GetAccessPointPolicyForObjectLambda
 - GetBucketLifecycleConfiguration
 - GetMultiRegionAccessPointPolicyStatus
 - GetStorageLensConfiguration
 - GetStorageLensConfigurationTagging
 - PutAccessPointConfigurationForObjectLambda
 - PutAccessPointPolicy
 - PutAccessPointPolicyForObjectLambda
 - PutBucketLifecycleConfiguration
 - PutStorageLensConfiguration
 - PutStorageLensConfigurationTagging
 - SubmitMultiRegionAccessPointRoutes
 
小驼峰风格,共计:
- DeletePublicAccessBlock
 - GetPublicAccessBlock
 - ListJobs
 - ListMultiRegionAccessPoints
 - ListRegionalBuckets
 - PutPublicAccessBlock
 - UpdateJobStatus
 
全小写和小驼峰混合风格,共计:
- GetAccessPointPolicyStatus
 - GetAccessPointPolicyStatusForObjectLambda
 - ListAccessPoints
 - ListAccessPointsForObjectLambda
 - ListStorageLensConfigurations
 
横杠风格,共计:
- CreateMultiRegionAccessPoint
 - DeleteMultiRegionAccessPoint
 - PutMultiRegionAccessPointPolicy
 
横杠和下划线混合风格,共计:
- DescribeMultiRegionAccessPointOperation
 
我们可以看到,AWS S3 Control API 更偏向全小写风格,也有小驼峰以及小驼峰混合全小写的情况,也有横杠风格,极个别出现横杠和下划线混合的情况。
OpenStack Nova API
OpenStack 是以开源云计算操作系统为目标,运营得较好的社区。代码检视比较严格,尤其是核心项目。我们选择其中最核心的计算模块,也是元老项目的 Nova 为例,分析下 OpenStack Nova API 的风格。
Nova 的 API 风格更为彻底的遵循了 REST 风格,和 AWS S3 API 还在使用 XML 不同,Nova 使用 Json 格式进行数据交互。但是风格统一程度和 AWS 一样,并不高。
Path 中参数命名风格:
- 变量参数统一下划线风格
 - 固定路径名横杠风格,较多,例如 
/servers/{server_id}/remote-consoles - 固定路径名横杠和下划线混用,较少,例如 
/servers/{server_id}/os-volume_attachments 
QueryString 中参数命名风格:
- 下划线风格,最多,例如 
access_ip_v4 - 横杠风格,较多,例如 
changes-since - 小驼峰,较少,例如 
minDisk 
请求体中参数命名风格:
- 小驼峰风格,较多,例如 
flavorRef - 下划线风格,较多,例如 
availability_zone - 冒号风格,较多,例如 
os:scheduler_hints.build_near_host_ip - 横杠,较少,例如 
OS-DCF:diskConfig 
对于资源的多种操作,将其定义为 POST /servers/{server_id}/action,在请求体中给出 action 实际参数名,风格为大驼峰。
也有使用 GET 语义的操作,例如 GET /os-hosts/{host_name}/reboot 重启机器。
原文 由 zqfan (zhiqiangfan@tencent.com) 发表。版权声明(License): (CC 4.0) BY-NC-SA