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