すべてのプロダクト
Search
ドキュメントセンター

Simple Message Queue (formerly MNS):リクエストプロトコル

最終更新日:Mar 11, 2026

Simple Message Queue (旧称:MNS)、略して SMQ は、HTTP ベースの API リクエストを使用します。このトピックでは、リクエスト構文、共通ヘッダー、応答フォーマット、およびリクエスト署名について説明します。

重要

SMQ SDK はリクエスト署名を自動的に処理します。手動で生の HTTP リクエストを構築する必要がない限り、SDK を使用してください。

リクエスト構文

リージョンとエンドポイント

SMQ は複数のリージョンで利用可能です。各リージョンは、パブリックエンドポイントと内部エンドポイントを提供します。詳細については、「リージョンとエンドポイント」をご参照ください。

リクエストメソッド

SMQ は HTTP 経由で PUT、POST、GET、および DELETE をサポートしています。リクエストパラメーター、リクエストヘッダー、およびリクエストボディが有効であることを確認してください。すべてのリクエストと応答は UTF-8 エンコーディングを使用します。

共通パラメーター

共通リクエストヘッダー

ヘッダー必須説明
Authorizationはい認証文字列。詳細については、「リクエストの署名」をご参照ください。
Content-Lengthはいリクエストボディのバイトサイズ。
Content-Typeはいリクエストボディの MIME タイプ。有効な値: text および xml
Content-MD5いいえリクエストボディの MD5 ハッシュ。詳細については、「RFC 1864」をご参照ください。
DateはいGMT でのリクエストタイムスタンプ。SMQ は 15 分以上前のリクエストを拒否します。
HostHTTP/1.1 では必須、HTTP/1.0 ではオプションSMQ サーバー。形式: $AccountId.mns.cn-hangzhou.aliyuncs.com$AccountId をご利用の Alibaba Cloud アカウント ID に置き換えます。これは Alibaba Cloud コンソールで確認できます。
x-mns-versionはいAPI バージョン。現在のバージョン: 2015-06-06
x-mns-dateいいえクライアントが Date ヘッダーをサポートしていない場合に Date ヘッダーを置き換えます。

共通レスポンスヘッダー

ヘッダー説明
Content-Length応答ボディのバイトサイズ。
ConnectionHTTP 接続ステータス。
DateGMT でのレスポンスタイムスタンプ。
ServerSMQ サーバー名。
x-mns-request-id一意のリクエスト ID。サポートチケットを開く際にこの値を含めます。
x-mns-versionAPI バージョン。現在のバージョン: 2015-06-06

応答フォーマット

HTTP 2xx 状態コードは成功を示します。HTTP 4xx および 5xx 状態コードは失敗を示します。成功応答は XML を使用します。

<?xml version="1.0" encoding="utf-8"?>
<RootElement xmlns="http://mns.aliyuncs.com/doc/v1/">
  <!-- 応答データ -->
</RootElement>

エラー応答も XML を使用し、エラーコード、エラーメッセージ、リクエスト ID、およびホスト ID を含みます。リクエスト ID はグローバルに一意です。

<?xml version="1.0" encoding="utf-8"?>
<Error xmlns="http://mns.aliyuncs.com/doc/v1/">
  <Code>ErrorCode</Code>
  <Message>詳細なエラーメッセージ。</Message>
  <RequestId>リクエスト ID</RequestId>
  <HostId>ホスト ID</HostId>
</Error>

エラーコードの完全なリストについては、「エラーコード」をご参照ください。

リクエスト署名メソッド

SMQ は、Authorization ヘッダー内の署名を通じてすべての API リクエストを認証します。署名プロセスには 3 つのステップがあります。

  1. 署名対象文字列の構築 -- HTTP メソッド、ヘッダー、およびリソースパスを正規文字列に組み立てます。

  2. 署名の計算 -- HMAC-SHA1 を使用して、ご利用の AccessKey Secret で署名対象文字列をハッシュ化し、結果を Base64 エンコードします。

  3. リクエストへの署名追加 -- Authorization ヘッダーを MNS <AccessKey ID>:<Signature> に設定します。

ステップ 1: 署名対象文字列の構築

以下の値を改行文字 (\n) で連結して StringToSign を構築します。

StringToSign = HttpMethod + "\n"
             + CONTENT-MD5 + "\n"
             + CONTENT-TYPE + "\n"
             + DATE + "\n"
             + CanonicalizedMNSHeaders
             + CanonicalizedResource
コンポーネント説明
HttpMethod大文字の HTTP メソッド: PUTGETPOST、または DELETE
CONTENT-MD5リクエストボディの MD5 ハッシュ。Content-MD5 ヘッダーが設定されていない場合は空白のままにします。
CONTENT-TYPEリクエストボディの MIME タイプ。Content-Type ヘッダーが設定されていない場合は空白のままにします。
DATEGMT でのリクエストタイムスタンプ。例: Thu, 07 Mar 2012 18:49:58 GMT。Date ヘッダーの代わりに x-mns-date ヘッダーを使用する場合は、その値をここに指定します。タイムスタンプが 15 分以上古い場合、SMQ はエラーコード 400 を返します。詳細については、「エラーコード」をご参照ください。
CanonicalizedMNSHeadersx-mns- で始まるすべての HTTP ヘッダーは、次のように処理されます: ヘッダー名を小文字に変換し、アルファベット順にソートし、各ヘッダーを <name>:<value>\n の形式で連結します。
CanonicalizedResourceドメインとポートが削除された、リクエストされたリソースの URI。例: http://123.123.XX.XX:8080/api/test?code=200/api/test?code=200 を生成し、http://www.aliyun.com/mns/help/mns/help を生成します。

CanonicalizedMNSHeaders 構築例 (Java):

// すべてのリクエストヘッダーを取得
Map<String, String> httpHeaders = request.getHeaders();
// ヘッダーをソートして名前を小文字に変換
sortHeadersKeyAndToLowerCase(httpHeaders);
// x-mns-* ヘッダーを連結
Set<String> keySet = httpHeaders.keySet();
for (String key : keySet) {
    if (key.startsWith("x-mns-")) {
        CanonicalizedMNSHeaders.append(key).append(":")
            .append(httpHeaders.get(key)).append("\n");
    }
}
重要

システムにゲートウェイまたはその他の中継プロキシが存在する場合、中間ゲートウェイによって認識される URI ではなく、CanonicalizedResource には元の HTTP リクエストの URI を使用してください。

ステップ 2: 署名の計算

UTF-8 エンコードされた StringToSign に HMAC-SHA1 (RFC 2104) を適用し、ご利用の AccessKey Secret をキーとして使用します。次に、結果を Base64 エンコードします。

Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) )
コンポーネント説明
Base64Base64 エンコーディング。
HMAC-SHA1RFC 2104 で定義されている HMAC-SHA1 アルゴリズム。
AccessSecretAuthorization ヘッダー内の AccessKey ID に対応する AccessKey Secret。
StringToSignステップ 1 で構築された文字列。

ステップ 3: リクエストへの署名追加

Authorization ヘッダーを設定します。

Authorization: MNS <AccessKey ID>:<Signature>

例:

Authorization: MNS 15B4D3461F177624****:xQE0diMbL****f3YB+FIEXAMPLE=

言語別の署名例

以下の例は、SMQ リクエストの Authorization ヘッダー値を生成する方法を示しています。

Python

import base64
import hashlib
import hmac
import os
from datetime import datetime, timezone


def sign_request(access_key_id, access_key_secret, method, resource,
                 content_type="", content_md5="", mns_headers=None):
    """Generate the Authorization header for an SMQ request."""
    date = datetime.now(timezone.utc).strftime("%a, %d %b %Y %H:%M:%S GMT")

    # Build CanonicalizedMNSHeaders
    canonicalized_headers = ""
    if mns_headers:
        for key in sorted(mns_headers.keys()):
            canonicalized_headers += f"{key.lower()}:{mns_headers[key]}\n"

    string_to_sign = (
        f"{method}\n{content_md5}\n{content_type}\n{date}\n"
        f"{canonicalized_headers}{resource}"
    )

    signature = base64.b64encode(
        hmac.new(
            access_key_secret.encode("utf-8"),
            string_to_sign.encode("utf-8"),
            hashlib.sha1,
        ).digest()
    ).decode("utf-8")

    return {
        "Authorization": f"MNS {access_key_id}:{signature}",
        "Date": date,
        "x-mns-version": "2015-06-06",
    }


# Usage
headers = sign_request(
    access_key_id=os.environ["ALIBABA_CLOUD_ACCESS_KEY_ID"],
    access_key_secret=os.environ["ALIBABA_CLOUD_ACCESS_KEY_SECRET"],
    method="PUT",
    resource="/queues/examplequeue?metaOverride=true",
    content_type="text/xml",
    mns_headers={"x-mns-version": "2015-06-06"},
)

Java

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

public class MnsSignature {

    public static Map<String, String> signRequest(
            String accessKeyId, String accessKeySecret,
            String method, String resource,
            String contentType, String contentMd5,
            Map<String, String> mnsHeaders) throws Exception {

        String date = DateTimeFormatter.RFC_1123_DATE_TIME
                .format(ZonedDateTime.now(ZoneOffset.UTC));

        // Build CanonicalizedMNSHeaders
        StringBuilder canonicalizedHeaders = new StringBuilder();
        if (mnsHeaders != null) {
            TreeMap<String, String> sorted = new TreeMap<>();
            mnsHeaders.forEach((k, v) -> sorted.put(k.toLowerCase(), v));
            sorted.forEach((k, v) -> canonicalizedHeaders.append(k)
                    .append(":").append(v).append("\n"));
        }

        String stringToSign = method + "\n" + contentMd5 + "\n"
                + contentType + "\n" + date + "\n"
                + canonicalizedHeaders + resource;

        Mac mac = Mac.getInstance("HmacSHA1");
        mac.init(new SecretKeySpec(
                accessKeySecret.getBytes(StandardCharsets.UTF_8), "HmacSHA1"));
        String signature = Base64.getEncoder().encodeToString(
                mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8)));

        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", "MNS " + accessKeyId + ":" + signature);
        headers.put("Date", date);
        headers.put("x-mns-version", "2015-06-06");
        return headers;
    }
}

Go

package main

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"fmt"
	"os"
	"sort"
	"strings"
	"time"
)

func signRequest(accessKeyID, accessKeySecret, method, resource,
	contentType, contentMD5 string, mnsHeaders map[string]string) map[string]string {

	date := time.Now().UTC().Format(time.RFC1123)

	// Build CanonicalizedMNSHeaders
	var keys []string
	for k := range mnsHeaders {
		keys = append(keys, strings.ToLower(k))
	}
	sort.Strings(keys)

	var canonicalized strings.Builder
	for _, k := range keys {
		canonicalized.WriteString(fmt.Sprintf("%s:%s\n", k, mnsHeaders[k]))
	}

	stringToSign := fmt.Sprintf("%s\n%s\n%s\n%s\n%s%s",
		method, contentMD5, contentType, date,
		canonicalized.String(), resource)

	mac := hmac.New(sha1.New, []byte(accessKeySecret))
	mac.Write([]byte(stringToSign))
	signature := base64.StdEncoding.EncodeToString(mac.Sum(nil))

	return map[string]string{
		"Authorization": fmt.Sprintf("MNS %s:%s", accessKeyID, signature),
		"Date":          date,
		"x-mns-version": "2015-06-06",
	}
}

func main() {
	headers := signRequest(
		os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"),
		os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"),
		"PUT",
		"/queues/examplequeue?metaOverride=true",
		"text/xml", "",
		map[string]string{"x-mns-version": "2015-06-06"},
	)
	for k, v := range headers {
		fmt.Printf("%s: %s\n", k, v)
	}
}

署名例

以下の例は、完全な署名済みリクエストと一般的なエラー応答を示しています。

リクエスト例

PUT /queues/$queueName?metaOverride=true HTTP/1.1
Host: $AccountId.mns.cn-hangzhou.aliyuncs.com
Date: Wed, 08 Mar 2012 12:00:00 GMT
Authorization: MNS 15B4D3461F177624****:xQE0diMbL****f3YB+FIEXAMPLE=

<?xml version="1.0" encoding="UTF-8"?>
<Queue xmlns="http://mns.aliyuncs.com/doc/v1/">
  <VisibilityTimeout>60</VisibilityTimeout>
  <MaximumMessageSize>1024</MaximumMessageSize>
  <MessageRetentionPeriod>120</MessageRetentionPeriod>
  <DelaySeconds>30</DelaySeconds>
</Queue>

エラー応答

以下の表は、一般的な認証関連のエラーを要約しています。

シナリオHTTP ステータスエラーコード
AccessKey ID が存在しないか、無効になっています403AccessIDAuthError
Date ヘッダーが見つからないか、無効です403InvalidArgument
リクエストがタイムスタンプから 15 分以上経過して到着しました408TimeExpired

例 1

403 AccessIDAuthError -- AccessKey ID が存在しないか、無効になっています。

Content-Type: text/xml
Content-Length: 314
Date: Wed, 18 Mar 2012 08:04:06 GMT
x-mns-request-id: 512B2A634403E52B1956****

<?xml version="1.0" encoding="utf-8"?>
<Error xmlns="http://mns.aliyuncs.com/doc/v1/">
  <Code>AccessIDAuthError</Code>
  <Message>
    AccessID 認証に失敗しました。AccessID を確認して再試行してください。
  </Message>
  <RequestId>512B2A634403E52B1956****</RequestId>
  <HostId>mns.cn-hangzhou.aliyuncs.com</HostId>
</Error>

例 2

403 InvalidArgument -- Date ヘッダーが見つからないか、無効です。

Content-Type: text/xml
Content-Length: 274
Date: Wed, 18 Mar 2012 08:04:06 GMT
x-mns-request-id: 512B2A634403E52B1956****

<?xml version="1.0" encoding="UTF-8"?>
<Error xmlns="http://mns.aliyuncs.com/doc/v1/">
  <Code>InvalidArgument</Code>
  <Message>Date ヘッダーが無効であるか、見つかりません。</Message>
  <RequestId>7E1A5CF258F535884403****</RequestId>
  <HostId>mns.cn-hangzhou.aliyuncs.com</HostId>
</Error>

例 3

408 TimeExpired -- リクエストがタイムスタンプから 15 分以上経過して到着しました。

Content-Type: text/xml
Content-Length: 283
Date: Wed, 11 May 2011 09:01:51 GMT
x-mns-request-id: 512B2A634403E52B1956****

<?xml version="1.0" encoding="UTF-8"?>
<Error xmlns="http://mns.aliyuncs.com/doc/v1/">
  <Code>TimeExpired</Code>
  <Message>
    送信した HTTP リクエストの有効期限が切れています。
  </Message>
  <RequestId>512B2A634403E52B1956****</RequestId>
  <HostId>mns.cn-hangzhou.aliyuncs.com</HostId>
</Error>