aliyun-rails 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +85 -0
- data/Rakefile +8 -0
- data/lib/aliyun/aliyun-rails.rb +13 -0
- data/lib/aliyun/rails/connector/roa_client.rb +168 -0
- data/lib/aliyun/rails/connector/rpc_client.rb +115 -0
- data/lib/aliyun/rails/dysms.rb +26 -0
- data/lib/aliyun/rails/dyvms.rb +26 -0
- data/lib/aliyun/rails/version.rb +9 -0
- metadata +82 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8fc1dbec7b764f807056f0f18e0f1f39bf8e2cc22292bd22d9c961d1a5946bea
|
4
|
+
data.tar.gz: 33574a813a8df2ef5bfd073fb0de6741edf2850690bce64f5941b5ed0b228adf
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 19c2df4717e7c95c83348b31ab98b8fa6225e8d0c67e44367071c778615a681284fd6aba5393e8b92630d4ca8236c957521046fa7a6011885a2104727ed55554
|
7
|
+
data.tar.gz: c387845817a3214c0576fda0b0d367d03c0fdad3b3d09eda8507a6e658ee36333f1c5623cc5b575be62f1ee305f03caec35b0613581f0f6ea6cb2e91e19630b7
|
data/README.md
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
[English](./README.md) | 简体中文
|
2
|
+
|
3
|
+
|
4
|
+
<p align="center">
|
5
|
+
<a href=" https://www.alibabacloud.com"><img src="https://aliyunsdk-pages.alicdn.com/icons/Aliyun.svg"></a>
|
6
|
+
</p>
|
7
|
+
|
8
|
+
<h1 align="center">非官方SDK套件-用于RAILS项目的</h1>
|
9
|
+
|
10
|
+
<p align="center">
|
11
|
+
<a href="https://badge.fury.io/rb/aliyunsdkcore"><img src="https://badge.fury.io/rb/aliyunsdkcore.svg" alt="Gem Version"></a>
|
12
|
+
<a href="https://travis-ci.org/aliyun/openapi-core-ruby-sdk"><img src="https://travis-ci.org/aliyun/openapi-core-ruby-sdk.svg?branch=master" alt="Build Status"></a>
|
13
|
+
<a href="https://ci.appveyor.com/project/aliyun/openapi-core-ruby-sdk/branch/master"><img src="https://ci.appveyor.com/api/projects/status/uyepkk5bjbynofvu/branch/master?svg=true" alt="Build status"></a>
|
14
|
+
<a href="https://codecov.io/gh/aliyun/openapi-core-ruby-sdk"><img src="https://codecov.io/gh/aliyun/openapi-core-ruby-sdk/branch/master/graph/badge.svg" alt="codecov"></a>
|
15
|
+
</p>
|
16
|
+
|
17
|
+
|
18
|
+
支持 Rails 轻松访问阿里云服务,例如:弹性云主机(ECS)、负载均衡(SLB)、云监控(CloudMonitor)等。
|
19
|
+
|
20
|
+
本文档介绍如何安装和使用 aliyun-rails
|
21
|
+
|
22
|
+
## 使用诊断
|
23
|
+
[Troubleshoot](https://troubleshoot.api.aliyun.com/?source=github_sdk) 提供 OpenAPI 使用诊断服务,通过 `RequestID` 或 `报错信息` ,帮助开发者快速定位,为开发者提供解决方案。
|
24
|
+
|
25
|
+
## 安装
|
26
|
+
|
27
|
+
```sh
|
28
|
+
$ gem install aliyun-rails
|
29
|
+
```
|
30
|
+
|
31
|
+
## 使用
|
32
|
+
|
33
|
+
RPC 示例;
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
require "aliyun-rails"
|
37
|
+
|
38
|
+
client = Dysms.new(
|
39
|
+
access_key_id: ENV['ACCESS_KEY_ID'],
|
40
|
+
access_key_secret: ENV['ACCESS_KEY_SECRET'],
|
41
|
+
)
|
42
|
+
|
43
|
+
response = client.send_sms("1380000000", "SMS_10010", {param1: "11"}, "SIGN_NAME")
|
44
|
+
|
45
|
+
puts response
|
46
|
+
```
|
47
|
+
|
48
|
+
|
49
|
+
ROA 示例:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
require 'aliyun-rails'
|
53
|
+
|
54
|
+
client = ROAClient.new(
|
55
|
+
endpoint: 'http://ros.aliyuncs.com',
|
56
|
+
api_version: '2015-09-01',
|
57
|
+
access_key_id: ENV['ACCESS_KEY_ID'],
|
58
|
+
access_key_secret: ENV['ACCESS_KEY_SECRET'],
|
59
|
+
)
|
60
|
+
|
61
|
+
response = client.request(
|
62
|
+
method: 'GET',
|
63
|
+
uri: '/regions',
|
64
|
+
options: {
|
65
|
+
timeout: 15000
|
66
|
+
}
|
67
|
+
)
|
68
|
+
|
69
|
+
print response.body
|
70
|
+
```
|
71
|
+
|
72
|
+
## 问题
|
73
|
+
[提交 Issue](https://github.com/ciscolive/aliyun-rails/issues/new/choose),不符合指南的问题可能会立即关闭。
|
74
|
+
|
75
|
+
|
76
|
+
## 发行说明
|
77
|
+
每个版本的详细更改记录在[发行说明](CHANGELOG.md)中。
|
78
|
+
|
79
|
+
|
80
|
+
## 贡献
|
81
|
+
提交 Pull Request 之前请阅读[贡献指南](CONTRIBUTING.md)。
|
82
|
+
|
83
|
+
|
84
|
+
## 许可证
|
85
|
+
[MIT](LICENSE.md)
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "rails/version"
|
4
|
+
|
5
|
+
require "aliyun/rails/connector/roa_client"
|
6
|
+
require "aliyun/rails/connector/rpc_client"
|
7
|
+
|
8
|
+
module Aliyun
|
9
|
+
module Rails
|
10
|
+
class Error < StandardError; end
|
11
|
+
# Your code goes here...
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
require "faraday"
|
2
|
+
require "securerandom"
|
3
|
+
require "active_support/all"
|
4
|
+
require "net/http"
|
5
|
+
|
6
|
+
module Net::HTTPHeader
|
7
|
+
def capitalize(name)
|
8
|
+
name
|
9
|
+
end
|
10
|
+
private :capitalize
|
11
|
+
end
|
12
|
+
|
13
|
+
module Aliyun
|
14
|
+
module Rails
|
15
|
+
module Connector
|
16
|
+
class ROAClient
|
17
|
+
|
18
|
+
attr_accessor :endpoint, :api_version, :access_key_id,
|
19
|
+
:access_key_secret, :security_token, :hostname, :opts
|
20
|
+
|
21
|
+
def initialize(config)
|
22
|
+
validate config
|
23
|
+
|
24
|
+
self.endpoint = config[:endpoint]
|
25
|
+
self.api_version = config[:api_version]
|
26
|
+
self.access_key_id = config[:access_key_id]
|
27
|
+
self.access_key_secret = config[:access_key_secret]
|
28
|
+
self.security_token = config[:security_token]
|
29
|
+
end
|
30
|
+
|
31
|
+
def request(method:, uri:, params: {}, body: {}, headers: {}, options: {})
|
32
|
+
# :"Content-Type" => "application/json" to "content-type" => "application/json"
|
33
|
+
headers.deep_transform_keys! { |key| key.to_s.downcase }
|
34
|
+
mix_headers = default_headers.merge(headers)
|
35
|
+
|
36
|
+
response = connection.send(method.downcase) do |request|
|
37
|
+
request.url uri, params
|
38
|
+
if body
|
39
|
+
if mix_headers["content-type"].start_with? "application/json"
|
40
|
+
request_body = body.to_json
|
41
|
+
elsif mix_headers["content-type"].start_with? "application/x-www-form-urlencoded"
|
42
|
+
request_body = URI.encode_www_form(body)
|
43
|
+
else
|
44
|
+
request_body = body
|
45
|
+
end
|
46
|
+
mix_headers["content-md5"] = Digest::MD5.base64digest request_body
|
47
|
+
mix_headers["content-length"] = request_body.length.to_s
|
48
|
+
request.body = request_body
|
49
|
+
end
|
50
|
+
string2sign = string_to_sign(method, uri, mix_headers, params)
|
51
|
+
mix_headers[:authorization] = authorization(string2sign)
|
52
|
+
mix_headers.each { |key, value| request.headers[key] = value }
|
53
|
+
end
|
54
|
+
|
55
|
+
return response if options.has_key? :raw_body
|
56
|
+
|
57
|
+
response_content_type = response.headers["Content-Type"] || ""
|
58
|
+
if response_content_type.start_with?("application/json")
|
59
|
+
if response.status >= 400
|
60
|
+
result = JSON.parse(response.body)
|
61
|
+
raise StandardError, "code: #{response.status}, #{result['Message']} requestid: #{result['RequestId']}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
if response_content_type.start_with?("text/xml")
|
66
|
+
result = Hash.from_xml(response.body)
|
67
|
+
raise ACSError, result["Error"] if result["Error"]
|
68
|
+
end
|
69
|
+
|
70
|
+
response
|
71
|
+
end
|
72
|
+
|
73
|
+
def connection(adapter = Faraday.default_adapter)
|
74
|
+
Faraday.new(url: self.endpoint) { |f| f.adapter adapter }
|
75
|
+
end
|
76
|
+
|
77
|
+
def get(uri: "", headers: {}, params: {}, options: {})
|
78
|
+
request(method: :get, uri: uri, params: params, body: {}, headers: headers, options: options)
|
79
|
+
end
|
80
|
+
|
81
|
+
def post(uri: "", headers: {}, params: {}, body: {}, options: {})
|
82
|
+
request(method: :post, uri: uri, params: params, body: body, headers: headers, options: options)
|
83
|
+
end
|
84
|
+
|
85
|
+
def put(uri: "", headers: {}, params: {}, body: {}, options: {})
|
86
|
+
request(method: :put, uri: uri, params: params, body: body, headers: headers, options: options)
|
87
|
+
end
|
88
|
+
|
89
|
+
def delete(uri: "", headers: {}, params: {}, options: {})
|
90
|
+
request(method: :delete, uri: uri, params: params, body: {}, headers: headers, options: options)
|
91
|
+
end
|
92
|
+
|
93
|
+
def default_headers
|
94
|
+
default_headers = {
|
95
|
+
"accept" => "application/json",
|
96
|
+
"date" => Time.now.httpdate,
|
97
|
+
"host" => URI(self.endpoint).host,
|
98
|
+
"x-acs-signature-nonce" => SecureRandom.hex(16),
|
99
|
+
"x-acs-signature-method" => "HMAC-SHA1",
|
100
|
+
"x-acs-signature-version" => "1.0",
|
101
|
+
"x-acs-version" => self.api_version,
|
102
|
+
"x-sdk-client" => "RUBY(#{RUBY_VERSION})", # FIXME: 如何获取Gem的名称和版本号
|
103
|
+
"user-agent" => DEFAULT_UA
|
104
|
+
}
|
105
|
+
if self.security_token
|
106
|
+
default_headers["x-acs-accesskey-id"] = self.access_key_id
|
107
|
+
default_headers["x-acs-security-token"] = self.security_token
|
108
|
+
end
|
109
|
+
default_headers
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
def string_to_sign(method, uri, headers, query = {})
|
114
|
+
header_string = [
|
115
|
+
method,
|
116
|
+
headers["accept"],
|
117
|
+
headers["content-md5"] || "",
|
118
|
+
headers["content-type"] || "",
|
119
|
+
headers["date"],
|
120
|
+
].join("\n")
|
121
|
+
"#{header_string}\n#{canonicalized_headers(headers)}#{canonicalized_resource(uri, query)}"
|
122
|
+
end
|
123
|
+
|
124
|
+
def canonicalized_headers(headers)
|
125
|
+
headers.keys.select { |key| key.to_s.start_with? "x-acs-" }
|
126
|
+
.sort.map { |key| "#{key}:#{headers[key].strip}\n" }.join
|
127
|
+
end
|
128
|
+
|
129
|
+
def canonicalized_resource(uri, query_hash = {})
|
130
|
+
query_string = query_hash.sort.map { |key, value| "#{key}=#{value}" }.join("&")
|
131
|
+
query_string.empty? ? uri : "#{uri}?#{query_string}"
|
132
|
+
end
|
133
|
+
|
134
|
+
def authorization(string_to_sign)
|
135
|
+
"acs #{self.access_key_id}:#{signature(string_to_sign)}"
|
136
|
+
end
|
137
|
+
|
138
|
+
def signature(string_to_sign)
|
139
|
+
Base64.encode64(OpenSSL::HMAC.digest("sha1", self.access_key_secret, string_to_sign)).strip
|
140
|
+
end
|
141
|
+
|
142
|
+
def validate(config)
|
143
|
+
raise ArgumentError, 'must pass "config"' unless config
|
144
|
+
raise ArgumentError, 'must pass "config[:endpoint]"' unless config[:endpoint]
|
145
|
+
unless config[:endpoint].start_with?("http://") || config[:endpoint].start_with?("https://")
|
146
|
+
raise ArgumentError, '"config.endpoint" must starts with \'https://\' or \'http://\'.'
|
147
|
+
end
|
148
|
+
raise ArgumentError, 'must pass "config[:api_version]"' unless config[:api_version]
|
149
|
+
raise ArgumentError, 'must pass "config[:access_key_id]"' unless config[:access_key_id]
|
150
|
+
raise ArgumentError, 'must pass "config[:access_key_secret]"' unless config[:access_key_secret]
|
151
|
+
end
|
152
|
+
|
153
|
+
class ACSError < StandardError
|
154
|
+
attr_accessor :code
|
155
|
+
|
156
|
+
def initialize(error)
|
157
|
+
self.code = error["Code"]
|
158
|
+
message = error["Message"]
|
159
|
+
host_id = error["HostId"]
|
160
|
+
request_id = error["RequestId"]
|
161
|
+
super("#{message} host_id: #{host_id}, request_id: #{request_id}")
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require "set"
|
2
|
+
require "openssl"
|
3
|
+
require "faraday"
|
4
|
+
require "erb"
|
5
|
+
require "active_support/all"
|
6
|
+
|
7
|
+
module Aliyun
|
8
|
+
module Rails
|
9
|
+
module Connector
|
10
|
+
class RPCClient
|
11
|
+
attr_accessor :endpoint, :api_version, :access_key_id, :access_key_secret,
|
12
|
+
:security_token, :codes, :opts, :verbose
|
13
|
+
|
14
|
+
def configure
|
15
|
+
yield self
|
16
|
+
end
|
17
|
+
|
18
|
+
# 对象初始化属性
|
19
|
+
def initialize(config = configure, verbose = false)
|
20
|
+
|
21
|
+
validate config
|
22
|
+
|
23
|
+
self.endpoint = config[:endpoint]
|
24
|
+
self.api_version = config[:api_version]
|
25
|
+
self.access_key_id = config[:access_key_id]
|
26
|
+
self.access_key_secret = config[:access_key_secret]
|
27
|
+
self.security_token = config[:security_token]
|
28
|
+
self.opts = config[:opts] || {}
|
29
|
+
self.verbose = verbose.instance_of?(TrueClass) && verbose
|
30
|
+
self.codes = Set.new [200, "200", "OK", "Success"]
|
31
|
+
self.codes.merge config[:codes] if config[:codes]
|
32
|
+
end
|
33
|
+
|
34
|
+
# 通用请求接口
|
35
|
+
def request(action:, params: {}, opts: {})
|
36
|
+
opts = self.opts.merge(opts)
|
37
|
+
action = upcase_first(action) if opts[:format_action]
|
38
|
+
params = format_params(params) unless opts[:format_params]
|
39
|
+
defaults = default_params
|
40
|
+
params = { Action: action }.merge(defaults).merge(params)
|
41
|
+
method = (opts[:method] || "GET").upcase
|
42
|
+
sign = "#{method}&#{encode('/')}&#{encode(params.to_query)}"
|
43
|
+
secret = "#{self.access_key_secret}&"
|
44
|
+
signature = Base64.encode64(OpenSSL::HMAC.digest("sha1", secret, sign)).strip
|
45
|
+
params["Signature"] = signature
|
46
|
+
|
47
|
+
# 转换为 query 样式
|
48
|
+
query_string = params.to_query
|
49
|
+
|
50
|
+
# 特殊处理 POST
|
51
|
+
uri = opts[:method] == "POST" ? "/" : "/?#{query_string}"
|
52
|
+
|
53
|
+
# 初始化会话
|
54
|
+
response = connection.send(method.downcase, uri) do |r|
|
55
|
+
if opts[:method] == "POST"
|
56
|
+
r.headers["Content-Type"] = "application/x-www-form-urlencoded"
|
57
|
+
r.body = query_string
|
58
|
+
end
|
59
|
+
r.headers["User-Agent"] = DEFAULT_UA
|
60
|
+
end
|
61
|
+
|
62
|
+
# 解析接口响应
|
63
|
+
response_body = JSON.parse(response.body)
|
64
|
+
if response_body["Code"] && !response_body["Code"].to_s.empty? && !self.codes.include?(response_body["Code"])
|
65
|
+
raise StandardError, "Code: #{response_body['Code']}, Message: #{response_body['Message']}, URL: #{uri}"
|
66
|
+
end
|
67
|
+
|
68
|
+
response_body
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
def connection(adapter = Faraday.default_adapter)
|
73
|
+
Faraday.new(url: self.endpoint) { |f| f.adapter adapter }
|
74
|
+
end
|
75
|
+
|
76
|
+
# 设置缺省参数
|
77
|
+
def default_params
|
78
|
+
params = {
|
79
|
+
Format: "JSON",
|
80
|
+
SignatureMethod: "HMAC-SHA1",
|
81
|
+
SignatureNonce: SecureRandom.hex(16),
|
82
|
+
SignatureVersion: "1.0",
|
83
|
+
Timestamp: Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
84
|
+
AccessKeyId: self.access_key_id,
|
85
|
+
Version: self.api_version,
|
86
|
+
}
|
87
|
+
params[:SecurityToken] = self.security_token if self.security_token.present?
|
88
|
+
params
|
89
|
+
end
|
90
|
+
|
91
|
+
# 消息签名需要
|
92
|
+
def encode(input)
|
93
|
+
ERB::Util.url_encode input
|
94
|
+
end
|
95
|
+
|
96
|
+
# 转换 HASH key 样式
|
97
|
+
def format_params(param_hash)
|
98
|
+
param_hash.keys.each { |key| param_hash[upcase_first(key.to_s).to_sym] = param_hash.delete key }
|
99
|
+
param_hash
|
100
|
+
end
|
101
|
+
|
102
|
+
def validate(config)
|
103
|
+
raise ArgumentError, 'must pass "config"' unless config
|
104
|
+
raise ArgumentError, 'must pass "config[:endpoint]"' unless config[:endpoint]
|
105
|
+
unless config[:endpoint].match?(/^http[s]?:/i)
|
106
|
+
raise ArgumentError, '"config.endpoint" must starts with \'https://\' or \'http://\'.'
|
107
|
+
end
|
108
|
+
raise ArgumentError, 'must pass "config[:api_version]"' unless config[:api_version]
|
109
|
+
raise ArgumentError, 'must pass "config[:access_key_id]"' unless config[:access_key_id]
|
110
|
+
raise ArgumentError, 'must pass "config[:access_key_secret]"' unless config[:access_key_secret]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Aliyun::Rails
|
2
|
+
class Dysms < Aliyun::Rails::Connector::RPCClient
|
3
|
+
|
4
|
+
# 本产品(Dysmsapi/2017-05-25)的OpenAPI采用RPC签名风格,签名细节参见签名机制说明。
|
5
|
+
# 我们已经为开发者封装了常见编程语言的SDK,开发者可通过下载SDK直接调用本产品OpenAPI而无需关心技术细节。
|
6
|
+
def initialize(config, verbose = nil)
|
7
|
+
|
8
|
+
config["endpoint"] = "http://dysmsapi.aliyuncs.com"
|
9
|
+
config["api_version"] = "2017-05-25"
|
10
|
+
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
# 发送短信,发送前要申请短信签名和短信模板,并确保签名和模板已审核通过。
|
15
|
+
def send_sms(phone_numbers, template_code, template_param, sign_name = "")
|
16
|
+
params = {
|
17
|
+
PhoneNumbers: phone_numbers,
|
18
|
+
SignName: sign_name,
|
19
|
+
TemplateCode: template_code,
|
20
|
+
TemplateParam: template_param.to_json
|
21
|
+
}
|
22
|
+
opts = { method: "POST", timeout: 15000 }
|
23
|
+
request(action: "SendSms", params: params, opts: opts)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Aliyun::Rails
|
2
|
+
class Dysms < Aliyun::Rails::Connector::RPCClient
|
3
|
+
|
4
|
+
# 本产品(Dyvmsapi/2017-05-25)的OpenAPI采用RPC签名风格,签名细节参见签名机制说明。
|
5
|
+
# 我们已经为开发者封装了常见编程语言的SDK,开发者可通过下载SDK直接调用本产品OpenAPI而无需关心技术细节。
|
6
|
+
def initialize(config, verbose = nil)
|
7
|
+
|
8
|
+
config["endpoint"] = "http://dyvmsapi.aliyuncs.com"
|
9
|
+
config["api_version"] = "2017-05-25"
|
10
|
+
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
# 调用SingleCallByTts接口向指定号码发送语音验证码和带参数变量的语音通知
|
15
|
+
def single_call_by_tts(called_show_number, called_number, tts_code, tts_param)
|
16
|
+
params = {
|
17
|
+
CalledShowNumber: called_show_number,
|
18
|
+
CalledNumber: called_number,
|
19
|
+
TtsCode: tts_code,
|
20
|
+
TtsParam: tts_param.to_json
|
21
|
+
}
|
22
|
+
opts = { method: "POST", timeout: 15000 }
|
23
|
+
request(action: "SendSms", params: params, opts: opts)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: aliyun-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- WENWU.YAN
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-03-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faraday
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.15.4
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.15.4
|
41
|
+
description: 支持 Rails 轻松访问阿里云服务,例如:弹性云主机(ECS)、负载均衡(SLB)、云监控(CloudMonitor)等
|
42
|
+
email:
|
43
|
+
- careline@foxmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- README.md
|
49
|
+
- Rakefile
|
50
|
+
- lib/aliyun/aliyun-rails.rb
|
51
|
+
- lib/aliyun/rails/connector/roa_client.rb
|
52
|
+
- lib/aliyun/rails/connector/rpc_client.rb
|
53
|
+
- lib/aliyun/rails/dysms.rb
|
54
|
+
- lib/aliyun/rails/dyvms.rb
|
55
|
+
- lib/aliyun/rails/version.rb
|
56
|
+
homepage: https://github.com/ciscolive/aliyun-rails
|
57
|
+
licenses:
|
58
|
+
- MIT
|
59
|
+
metadata:
|
60
|
+
homepage_uri: https://github.com/ciscolive/aliyun-rails
|
61
|
+
source_code_uri: https://github.com/ciscolive/aliyun-rails
|
62
|
+
changelog_uri: https://github.com/ciscolive/aliyun-rails/blob/main/README.md
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: 2.6.0
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
requirements: []
|
78
|
+
rubygems_version: 3.3.3
|
79
|
+
signing_key:
|
80
|
+
specification_version: 4
|
81
|
+
summary: 非阿里云官方SDK,本GEM主要实现RAILS项目轻松调用 ** aliyun ** 相关接口
|
82
|
+
test_files: []
|