RPC 调用机制

概述

本文介绍了阿里云 OpenAPI 的 RPC 调用风格。如果您想要自研阿里云 RPC 调用风格的 OpenAPI SDK,请参看此文,请务必先参看[阿里云开放 API 自研 SDK 开发指南]。如果您可以使用官方 SDK,请参看 [阿里云开放 API 官方 SDK 开发指南]。

阿里云 RPC OpenAPI 向开发者提供HTTP接口,您可以参看如下文档,来构造 HTTP 接口以调用对应的 OpenAPI 。

本文将介绍 RPC OpenAPI 请求的组成部分,然后介绍如何通过这些组成部分构造一个 OpenAPI 请求,以及如何获取返回结果。

HTTP 请求结构

一个完整的阿里云 OpenAPI 请求,包含以下部分。

名称

是否必选

描述

示例值

协议

您可以查阅不同云产品的 API 参考文档进行配置。支持通过HTTPHTTPS协议进行请求通信。为了获得更高的安全性,推荐您使用HTTPS协议发送请求。取值范围为https://或者 http://

https://

服务地址

即 Endpoint。您可以查阅不同云产品的 服务接入地址文档,查阅不同服务区域下的服务地址。更多信息,请查看[阿里云OpenAPI服务地址介绍]

ecs.aliyuncs.com

公共请求参数

阿里云 OpenAPI 的公共请求参数,后文将详细说明。参见后文公共请求参数

接口自定义请求参数

每个 OpenAPI 自定义的请求参数,建议您在阿里云 OpenAPI 开发者门户进行试用。

HTTPMethod

RPC 请求Method支持 POST 或者 GET。其中 POST 请求。

GET

公共请求参数

阿里云 OpenAPI 公共请求参数介绍如下:

名称

类型

是否必选

描述

示例值

Action

String

API的名称。您可以访问阿里云OpenAPI开发者门户,搜索您想调用的 OpenAPI

CreateInstance

Version

String

API 版本。您可以访问阿里云OpenAPI开发者门户,查看您调用 OpenAPI 对应的 API 版本

2014-05-26

Format

String

指定接口返回数据的格式。可以选择 JSON 或者 XML。默认为 XML。

JSON

AccessKeyId

String

阿里云访问密钥ID。您可以在RAM 控制台 查看您的 AccessKeyId。如需创建 AccessKey,请参见创建 AccessKey

***

SignatureNonce

String

签名唯一随机数。用于防止网络重放攻击,建议您每一次请求都使用不同的随机数。

15215528852396

Timestamp

String

请求的时间戳。按照ISO8601标准表示,并需要使用UTC时间,格式为yyyy-MM-ddTHH:mm:ssZ

示例:2018-01-01T12:00:00Z表示北京时间2018年01月01日20点00分00秒。

2018-01-01T12:00:00Z

SignatureMethod

String

签名方式。目前为固定值 HMAC-SHA1

HMAC-SHA1

SignatureVersion

String

签名算法版本。目前为固定值 1.0

1.0

Signature

String

请求签名,用户请求的身份验证。详细签名机制,请参见签名机制

Pc5WB8gokVn0xfeu%2FZV%2BiNM1dgI%3D

接口请求构造

步骤一:构造接口 URL

1、接口URL的组成部分为:[协议][服务地址]?[公共参数][业务请求参数]。其中 POST 方法的接口,为了避免 URL 过长,我们建议业务请求参数在 body 中传入。

2、对请求参数进行规范化编码。编码方式请参看参数编码方式。例如 Timestamp 的参数值为 2016-02-23T12:46:24Z ,编码后为 2016-02-23T12%253A46%253A24Z

接口URL示例:http://ecs.aliyuncs.com/?SignatureVersion=1.0&Action=DescribeDedicatedHosts&Format=XML&SignatureNonce=3ee8c1b8-xxxx-xxxx-xxxx-xxxxxxxxx&Version=2014-05-26&AccessKeyId=testid&Signature=OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D&SignatureMethod=HMAC-SHA1&Timestamp=2016-02-23T12%253A46%253A24Z&RegionId=cn-hangzhou&Status=Available

步骤二:发起接口调用

阿里云 OpenAPI RPC 接口,只有 GET 和 POST 两种 method。

对于 GET 方法的接口,您可以使用浏览器、curl或者wget等工具,用步骤一的接口URL发送HTTP请求。

对于 POST 方法的接口,我们建议业务请求参数在 body 中传入,其中请求头的 Content-Type 需要设置为 application/x-www-form-urlencoded

接口返回结果

返回结果主要有XML和JSON两种格式,默认为XML,您可以指定公共请求参数Format变更返回结果的格式。为了便于您查看,API文档返回示例均进行了换行和缩进等处理,实际返回结果无换行和缩进处理。

接口调用成功后,会返回接口的返回参数请求ID,HTTP状态码为2xx。示例如下:
  • XML示例

<?xml version="1.0" encoding="UTF-8"?> <!--结果的根结点-->
<ActionResponse> <!--返回请求标签-->
    <RequestId>4C467B38-3910-447D-87BC-AC049166F216</RequestId> <!--返回结果数据-->
</ActionResponse>
  • JSON示例

{
    "RequestId": "4C467B38-3910-447D-87BC-AC049166F216" /* 返回结果数据 */
}

接口调用出错后,会返回错误码、错误信息和请求ID,HTTP状态码为4xx或者5xx。示例如下:

  • XML示例

<?xml version="1.0" encoding="UTF-8"?><!--结果的根结点-->
<Error>
    <RequestId>540CFF28-407A-40B5-B6A5-74Bxxxxxxxxx</RequestId> <!--请求 ID-->
    <HostId>ecs.aliyuncs.com</HostId> <!--服务节点-->
    <Code>MissingParameter.CommandId</Code> <!--错误码-->
    <Message>The input parameter “CommandId” that is mandatory for processing this request is not supplied.</Message> <!--错误信息-->
</Error>
  • JSON示例

{
    "RequestId": "540CFF28-407A-40B5-B6A5-74Bxxxxxxxxx", /* 请求 ID */
    "HostId": "ecs.aliyuncs.com", /* 服务节点 */
    "Code": "MissingParameter.CommandId", /* 错误码 */
    "Message": "The input parameter “CommandId” that is mandatory for processing this request is not supplied." /* 错误信息 */
}

接口调用出错后,您可以根据返回的RequestId,在阿里云OpenAPI开发者门户-诊断中排查。此外,您还可以查阅公共错误码以及API 错误中心。当您无法排查错误时,可以提交工单,并在工单中注明服务节点HostId和RequestId。

签名机制

为保证API的安全使用,在调用API时阿里云会对每个API请求通过签名(Signature)进行身份验证。无论使用HTTP还是HTTPS协议提交请求,都需要在请求中包含签名信息。本文介绍计算签名的方法和示例。

步骤一:构造规范化请求字符串

1、参数排序。按照参数首字母的字典顺序对参数排序,排序参数包括公共请求参数和接口自定义参数,不包括公共请求参数中的Signature参数。 公共请求参数详情,请参见上文公共请求参数

2、对请求参数和参数值进行编码。使用UTF-8字符集按照RFC3986规则编码请求参数和参数取值,编码具体规则请参看参数编码方式。为方便表述,我们将此步骤的编码方法,命名为 encodeURIComponent

3、使用等号(=)连接编码后的请求参数和参数取值。

4、使用与号(&)连接编码后的请求参数,注意参数排序与第1步一致。

5、头部添加协议头和 endpoint。例如 https://ecs.aliyuncs.com

现在,您得到了规范化请求字符串,为方便表述,我们将步骤一得到的字符串命名为 CanonicalizedQueryString

步骤二:构造签名字符串

1、构造待签名字符串 stringToSign。我们以 Java 为例,该字符串构造规则如下:

  1. String stringToSign =
      HTTPMethod + "&" + // HTTPMethod:发送请求的 HTTP 方法,例如 GET。
      encodeURIComponent("/") + "&" + // encodeURIComponent 为步骤一第2步的编码方法
      encodeURIComponent(CanonicalizedQueryString) // CanonicalizedQueryString 为步骤一获取的规范化请求字符串。

2、按照RFC2104的定义,通过您传入的 AccessKeyId 对应的秘钥 AccessSecret,使用 HMAC-SHA1 的签名算法,计算待签名字符串StringToSign的签名。以 Java 为例,计算方法如下:

String signature = Base64(HMAC_SHA1(AccessSecret, UTF_8_Encoding_Of(stringToSign)))

现在您得到了公共参数 Signature 的签名值 signature

签名示例

本示例以调用 ECS DescribeDedicatedHosts 查询一台或多台专有宿主机的详细信息为例。假设您获得了AccessKeyID=testid 以及 AccessKeySecret=testsecret,签名流程如下:

  1. 构造规范化请求字符串。

    http://ecs.aliyuncs.com/?Timestamp=2016-02-23T12%3A46%3A24Z&Format=XML&AccessKeyId=testid&Action=DescribeDedicatedHosts&SignatureMethod=HMAC-SHA1&SignatureNonce=3ee8c1b8-xxxx-xxxx-xxxx-xxxxxxxxxx&Version=2014-05-26&SignatureVersion=1.0
  2. 构造待签名字符串stringToSign

    GET&%2F&AccessKeyId%3Dtestid%26Action%3DDescribeDedicatedHosts%26Format%3DXML%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3D3ee8c1b8-xxxx-xxxx-xxxx-xxxxxxxxx%26SignatureVersion%3D1.0%26Timestamp%3D2016-02-23T12%253A46%253A24Z%26Version%3D2014-05-26
  3. 计算签名值。因为AccessKeySecret=testsecret,用于计算的Key为testsecret,计算得到的签名值为OLeaidS1JvxuMvnyHOwuJ+uX5qY=。本示例使用的是JavaBase64编码方法。

    String Signature = Base64(HMAC_SHA1(AccessSecret,UTF_8_Encoding_Of(stringToSign)))
  4. 添加RFC3986规则编码后的Signature=OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D第1步的URL中。

    http://ecs.aliyuncs.com/?SignatureVersion=1.0&Action=DescribeDedicatedHosts&Format=XML&SignatureNonce=3ee8c1b8-xxxx-xxxx-xxxx-xxxxxxxxx&Version=2014-05-26&AccessKeyId=testid&Signature=OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D&SignatureMethod=HMAC-SHA1&Timestamp=2016-02-23T12%253A46%253A24Z

通过第4步得到的URL,您可以使用浏览器、curl或者wget等工具发起HTTP请求调用DescribeDedicatedHosts,查询一台或多台专有宿主机的详细信息。

附录

参数编码方式

在阿里云 OpenAPI 调用中,我们需要对请求参数和请求值,使用UTF-8字符集按照RFC3986规则进行编码。具体编码规则如下:

    • 字符A~Z、a~z、0~9以及字符-_.~不编码。

    • 对其它ASCII码字符进行编码。编码格式为%加上16进制的 ASCII 码。例如半角双引号(")将被编码为 %22

    • 非 ASCII 码通过 UTF-8 编码。

    • 空格编码成%20,而不是加号(+)。

为方便表述,我们将此步骤的编码方法,命名为 encodeURIComponent