# GAPI服务

# 服务地址

https://g.sinacloud.com

# 签名规则

将所有x-sae-开头的http header(小写)按name排序后用冒号链接name和value,放在method、uri(包含query string,不要转义)后以换行符分隔拼接为签名原文字符串,再以Secretkey为密钥用hmac sha256计算哈希值(二进制),再经base64编码,前面加上"SAEV1_HMAC_SHA256 ",得到本次请求的认证签名,即Authorization字段。

# 认证的请求头

请求头 说明
x-sae-accesskey 应用的Accesskey
x-sae-timestamp Unix时间戳
Authorization 本次请求的认证签名

# 请求头示例

GET /log/http/2015-06-05/1-access.log HTTP/1.1
Host: g.sae.sina.com.cn
Accept: text/plain
x-sae-accesskey: 0xdeadbeef
x-sae-timestamp: 1433495016
Authorization: SAEV1_HMAC_SHA256 VQdy0s/D4aEn6QXAexr0onGmz+QObDwkWcZCCKcxMws=

# Python签名示例

import time
import base64
import hmac
import hashlib

TIMESTAMP = str(int(time.time()))
URI = '/log/http/2015-05-06/1-access.log?head/0/1'
# x-sae-开头的header的name需要是小写的
msgToSign = "\n".join(["GET", URI, "\n".join([(k + ":" + v) for k, v in sorted(HEADERS) if k.startswith('x-sae-')])])
signature = "SAEV1_HMAC_SHA256 " + base64.b64encode(hmac.new(SECRETKEY, msgToSign, hashlib.sha256).digest())

# PHP签名示例

<?php
namespace sinacloud\sae;
class Gapi
{
    private $accessKey;
    private $secretKey;
    private $gapi = 'http://g.sinacloud.com';

    public function __construct($accessKey, $secretKey)
    {
        $this->accessKey = $accessKey;
        $this->secretKey = $secretKey;
    }

    /**
     * 发送一个GET请求
     * @param $uri
     * @return bool|mixed
     */
    public function get($uri)
    {
        if (!$uri) {
            return false;
        }
        return $this->_curl($uri);
    }

    public function post($uri, $post_data = array())
    {
        if (!$uri) {
            return false;
        }
        return $this->_curl($uri, $post_data, 'POST');
    }

    private function _cal_sign_and_set_header($ch, $uri, $method = 'GET')
    {
        $a = array();
        $a[] = $method;
        $a[] = $uri;
        // $timeline unix timestamp
        $timeline = time();
        $b = array('x-sae-accesskey' => $this->accessKey, 'x-sae-timestamp' => $timeline);
        ksort($b);
        foreach ($b as $key => $value) {
            $a[] = sprintf("%s:%s", $key, $value);
        }
        $str = implode("\n", $a);
        $s = hash_hmac('sha256', $str, $this->secretKey, true);
        $b64_s = base64_encode($s);
        $headers = array();
        $headers[] = sprintf('x-sae-accesskey:%s', $this->accessKey);
        $headers[] = sprintf('x-sae-timestamp:%s', $timeline);
        $headers[] = sprintf('Authorization: SAEV1_HMAC_SHA256 %s', $b64_s);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        return $headers;
    }

    private function _curl($uri, $post_data = array(), $method = 'GET')
    {
        $ch = curl_init();
        $url = sprintf('%s%s', $this->gapi, $uri);
        curl_setopt($ch, CURLOPT_URL, $url);
        $this->_cal_sign_and_set_header($ch, $uri, $method);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        if ($post_data) {
            if (is_array($post_data)) {
                curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
            } else {
                curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
            }
        }
        $txt = curl_exec($ch);
        $error = curl_errno($ch);
        curl_close($ch);
        if ($error) {
            return false;
        }
        return $txt;
    }
}

# 接口返回码说明

状态码 说明
200 OK 无错误
403 Forbidden 认证失败
404 Not Found 接口不存在等
405 Method Not Allowed 不支持的http method