leancloud-ruby-client 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/.travis.yml +9 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +86 -0
- data/LICENSE.txt +20 -0
- data/README.md +1177 -0
- data/Rakefile +45 -0
- data/VERSION +1 -0
- data/example.rb +35 -0
- data/features.md +1111 -0
- data/fixtures/vcr_cassettes/test_acls_arent_objects.yml +274 -0
- data/fixtures/vcr_cassettes/test_array_add.yml +213 -0
- data/fixtures/vcr_cassettes/test_array_add_pointerizing.yml +380 -0
- data/fixtures/vcr_cassettes/test_array_add_unique.yml +319 -0
- data/fixtures/vcr_cassettes/test_batch_create_object.yml +107 -0
- data/fixtures/vcr_cassettes/test_batch_delete_object.yml +637 -0
- data/fixtures/vcr_cassettes/test_batch_run.yml +109 -0
- data/fixtures/vcr_cassettes/test_batch_update_nils_delete_keys.yml +435 -0
- data/fixtures/vcr_cassettes/test_batch_update_object.yml +637 -0
- data/fixtures/vcr_cassettes/test_contains_all.yml +1143 -0
- data/fixtures/vcr_cassettes/test_cql.yml +99 -0
- data/fixtures/vcr_cassettes/test_created_at.yml +109 -0
- data/fixtures/vcr_cassettes/test_decrement.yml +213 -0
- data/fixtures/vcr_cassettes/test_deep_parse.yml +321 -0
- data/fixtures/vcr_cassettes/test_destroy.yml +213 -0
- data/fixtures/vcr_cassettes/test_empty_response.yml +1026 -0
- data/fixtures/vcr_cassettes/test_eq_pointerize.yml +427 -0
- data/fixtures/vcr_cassettes/test_equality.yml +321 -0
- data/fixtures/vcr_cassettes/test_get.yml +215 -0
- data/fixtures/vcr_cassettes/test_get_installation.yml +58 -0
- data/fixtures/vcr_cassettes/test_get_missing.yml +160 -0
- data/fixtures/vcr_cassettes/test_image_file_associate_with_object.yml +2089 -0
- data/fixtures/vcr_cassettes/test_image_file_save.yml +1928 -0
- data/fixtures/vcr_cassettes/test_include.yml +321 -0
- data/fixtures/vcr_cassettes/test_new_model.yml +109 -0
- data/fixtures/vcr_cassettes/test_new_object.yml +109 -0
- data/fixtures/vcr_cassettes/test_nils_delete_keys.yml +319 -0
- data/fixtures/vcr_cassettes/test_object_id.yml +56 -0
- data/fixtures/vcr_cassettes/test_parse_delete.yml +421 -0
- data/fixtures/vcr_cassettes/test_pointer.yml +109 -0
- data/fixtures/vcr_cassettes/test_request_sms.yml +48 -0
- data/fixtures/vcr_cassettes/test_reset_password.yml +109 -0
- data/fixtures/vcr_cassettes/test_retries.yml +4173 -0
- data/fixtures/vcr_cassettes/test_retries_404.yml +1026 -0
- data/fixtures/vcr_cassettes/test_retries_404_correct.yml +1026 -0
- data/fixtures/vcr_cassettes/test_retries_json_error.yml +2265 -0
- data/fixtures/vcr_cassettes/test_retries_server_error.yml +2265 -0
- data/fixtures/vcr_cassettes/test_save_installation.yml +58 -0
- data/fixtures/vcr_cassettes/test_save_with_sub_objects.yml +484 -0
- data/fixtures/vcr_cassettes/test_saving_boolean_values.yml +215 -0
- data/fixtures/vcr_cassettes/test_saving_nested_objects.yml +62 -0
- data/fixtures/vcr_cassettes/test_server_update.yml +586 -0
- data/fixtures/vcr_cassettes/test_simple_save.yml +109 -0
- data/fixtures/vcr_cassettes/test_text_file_save.yml +109 -0
- data/fixtures/vcr_cassettes/test_update.yml +213 -0
- data/fixtures/vcr_cassettes/test_updated_at.yml +213 -0
- data/fixtures/vcr_cassettes/test_user_login.yml +276 -0
- data/fixtures/vcr_cassettes/test_user_save.yml +109 -0
- data/fixtures/vcr_cassettes/test_xget.yml +603 -0
- data/leancloud-ruby-client.gemspec +166 -0
- data/lib/faraday/better_retry.rb +94 -0
- data/lib/faraday/extended_parse_json.rb +39 -0
- data/lib/faraday/get_method_override.rb +32 -0
- data/lib/leancloud-ruby-client.rb +34 -0
- data/lib/leancloud/application.rb +7 -0
- data/lib/leancloud/batch.rb +53 -0
- data/lib/leancloud/client.rb +149 -0
- data/lib/leancloud/cloud.rb +28 -0
- data/lib/leancloud/datatypes.rb +355 -0
- data/lib/leancloud/error.rb +42 -0
- data/lib/leancloud/installation.rb +57 -0
- data/lib/leancloud/model.rb +14 -0
- data/lib/leancloud/object.rb +252 -0
- data/lib/leancloud/protocol.rb +193 -0
- data/lib/leancloud/push.rb +48 -0
- data/lib/leancloud/query.rb +194 -0
- data/lib/leancloud/user.rb +38 -0
- data/lib/leancloud/util.rb +93 -0
- data/test/cloud_functions/MyCloudCode/cloud/main.js +4 -0
- data/test/config/global.json +14 -0
- data/test/helper.rb +108 -0
- data/test/middleware/better_retry_test.rb +57 -0
- data/test/middleware/extend_parse_json_test.rb +55 -0
- data/test/parsers.jpg +0 -0
- data/test/test_batch.rb +132 -0
- data/test/test_client.rb +183 -0
- data/test/test_cloud.rb +31 -0
- data/test/test_datatypes.rb +105 -0
- data/test/test_file.rb +67 -0
- data/test/test_init.rb +23 -0
- data/test/test_init_from_cloud_code.rb +8 -0
- data/test/test_installation.rb +49 -0
- data/test/test_model.rb +22 -0
- data/test/test_object.rb +295 -0
- data/test/test_push.rb +45 -0
- data/test/test_query.rb +198 -0
- data/test/test_throttle.rb +5 -0
- data/test/test_user.rb +60 -0
- metadata +298 -0
@@ -0,0 +1,166 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "leancloud-ruby-client"
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Alan deLevie", "Adam Alpern", "Dennis Zhuang"]
|
12
|
+
s.date = "2015-04-10"
|
13
|
+
s.description = "A simple Ruby client for the leancloud.cn REST API"
|
14
|
+
s.email = "killme2008@gmail.com"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.md"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".travis.yml",
|
21
|
+
"Gemfile",
|
22
|
+
"Gemfile.lock",
|
23
|
+
"LICENSE.txt",
|
24
|
+
"README.md",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"example.rb",
|
28
|
+
"features.md",
|
29
|
+
"fixtures/vcr_cassettes/test_acls_arent_objects.yml",
|
30
|
+
"fixtures/vcr_cassettes/test_array_add.yml",
|
31
|
+
"fixtures/vcr_cassettes/test_array_add_pointerizing.yml",
|
32
|
+
"fixtures/vcr_cassettes/test_array_add_unique.yml",
|
33
|
+
"fixtures/vcr_cassettes/test_batch_create_object.yml",
|
34
|
+
"fixtures/vcr_cassettes/test_batch_delete_object.yml",
|
35
|
+
"fixtures/vcr_cassettes/test_batch_run.yml",
|
36
|
+
"fixtures/vcr_cassettes/test_batch_update_nils_delete_keys.yml",
|
37
|
+
"fixtures/vcr_cassettes/test_batch_update_object.yml",
|
38
|
+
"fixtures/vcr_cassettes/test_contains_all.yml",
|
39
|
+
"fixtures/vcr_cassettes/test_cql.yml",
|
40
|
+
"fixtures/vcr_cassettes/test_created_at.yml",
|
41
|
+
"fixtures/vcr_cassettes/test_decrement.yml",
|
42
|
+
"fixtures/vcr_cassettes/test_deep_parse.yml",
|
43
|
+
"fixtures/vcr_cassettes/test_destroy.yml",
|
44
|
+
"fixtures/vcr_cassettes/test_empty_response.yml",
|
45
|
+
"fixtures/vcr_cassettes/test_eq_pointerize.yml",
|
46
|
+
"fixtures/vcr_cassettes/test_equality.yml",
|
47
|
+
"fixtures/vcr_cassettes/test_get.yml",
|
48
|
+
"fixtures/vcr_cassettes/test_get_installation.yml",
|
49
|
+
"fixtures/vcr_cassettes/test_get_missing.yml",
|
50
|
+
"fixtures/vcr_cassettes/test_image_file_associate_with_object.yml",
|
51
|
+
"fixtures/vcr_cassettes/test_image_file_save.yml",
|
52
|
+
"fixtures/vcr_cassettes/test_include.yml",
|
53
|
+
"fixtures/vcr_cassettes/test_new_model.yml",
|
54
|
+
"fixtures/vcr_cassettes/test_new_object.yml",
|
55
|
+
"fixtures/vcr_cassettes/test_nils_delete_keys.yml",
|
56
|
+
"fixtures/vcr_cassettes/test_object_id.yml",
|
57
|
+
"fixtures/vcr_cassettes/test_parse_delete.yml",
|
58
|
+
"fixtures/vcr_cassettes/test_pointer.yml",
|
59
|
+
"fixtures/vcr_cassettes/test_request_sms.yml",
|
60
|
+
"fixtures/vcr_cassettes/test_reset_password.yml",
|
61
|
+
"fixtures/vcr_cassettes/test_retries.yml",
|
62
|
+
"fixtures/vcr_cassettes/test_retries_404.yml",
|
63
|
+
"fixtures/vcr_cassettes/test_retries_404_correct.yml",
|
64
|
+
"fixtures/vcr_cassettes/test_retries_json_error.yml",
|
65
|
+
"fixtures/vcr_cassettes/test_retries_server_error.yml",
|
66
|
+
"fixtures/vcr_cassettes/test_save_installation.yml",
|
67
|
+
"fixtures/vcr_cassettes/test_save_with_sub_objects.yml",
|
68
|
+
"fixtures/vcr_cassettes/test_saving_boolean_values.yml",
|
69
|
+
"fixtures/vcr_cassettes/test_saving_nested_objects.yml",
|
70
|
+
"fixtures/vcr_cassettes/test_server_update.yml",
|
71
|
+
"fixtures/vcr_cassettes/test_simple_save.yml",
|
72
|
+
"fixtures/vcr_cassettes/test_text_file_save.yml",
|
73
|
+
"fixtures/vcr_cassettes/test_update.yml",
|
74
|
+
"fixtures/vcr_cassettes/test_updated_at.yml",
|
75
|
+
"fixtures/vcr_cassettes/test_user_login.yml",
|
76
|
+
"fixtures/vcr_cassettes/test_user_save.yml",
|
77
|
+
"fixtures/vcr_cassettes/test_xget.yml",
|
78
|
+
"leancloud-ruby-client.gemspec",
|
79
|
+
"lib/faraday/better_retry.rb",
|
80
|
+
"lib/faraday/extended_parse_json.rb",
|
81
|
+
"lib/faraday/get_method_override.rb",
|
82
|
+
"lib/leancloud-ruby-client.rb",
|
83
|
+
"lib/leancloud/application.rb",
|
84
|
+
"lib/leancloud/batch.rb",
|
85
|
+
"lib/leancloud/client.rb",
|
86
|
+
"lib/leancloud/cloud.rb",
|
87
|
+
"lib/leancloud/datatypes.rb",
|
88
|
+
"lib/leancloud/error.rb",
|
89
|
+
"lib/leancloud/installation.rb",
|
90
|
+
"lib/leancloud/model.rb",
|
91
|
+
"lib/leancloud/object.rb",
|
92
|
+
"lib/leancloud/protocol.rb",
|
93
|
+
"lib/leancloud/push.rb",
|
94
|
+
"lib/leancloud/query.rb",
|
95
|
+
"lib/leancloud/user.rb",
|
96
|
+
"lib/leancloud/util.rb",
|
97
|
+
"test/cloud_functions/MyCloudCode/cloud/main.js",
|
98
|
+
"test/config/global.json",
|
99
|
+
"test/helper.rb",
|
100
|
+
"test/middleware/better_retry_test.rb",
|
101
|
+
"test/middleware/extend_parse_json_test.rb",
|
102
|
+
"test/parsers.jpg",
|
103
|
+
"test/test_batch.rb",
|
104
|
+
"test/test_client.rb",
|
105
|
+
"test/test_cloud.rb",
|
106
|
+
"test/test_datatypes.rb",
|
107
|
+
"test/test_file.rb",
|
108
|
+
"test/test_init.rb",
|
109
|
+
"test/test_init_from_cloud_code.rb",
|
110
|
+
"test/test_installation.rb",
|
111
|
+
"test/test_model.rb",
|
112
|
+
"test/test_object.rb",
|
113
|
+
"test/test_push.rb",
|
114
|
+
"test/test_query.rb",
|
115
|
+
"test/test_throttle.rb",
|
116
|
+
"test/test_user.rb"
|
117
|
+
]
|
118
|
+
s.homepage = "http://github.com/killme2008/leancloud-ruby-client"
|
119
|
+
s.licenses = ["MIT"]
|
120
|
+
s.require_paths = ["lib"]
|
121
|
+
s.rubygems_version = "2.0.6"
|
122
|
+
s.summary = "A simple Ruby client for the leancloud.cn REST API"
|
123
|
+
|
124
|
+
if s.respond_to? :specification_version then
|
125
|
+
s.specification_version = 4
|
126
|
+
|
127
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
128
|
+
s.add_runtime_dependency(%q<faraday>, [">= 0"])
|
129
|
+
s.add_runtime_dependency(%q<faraday_middleware>, [">= 0"])
|
130
|
+
s.add_development_dependency(%q<bundler>, [">= 0"])
|
131
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
132
|
+
s.add_development_dependency(%q<test-unit>, ["= 2.5.0"])
|
133
|
+
s.add_development_dependency(%q<mocha>, ["= 0.12.0"])
|
134
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.8.5"])
|
135
|
+
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
136
|
+
s.add_development_dependency(%q<webmock>, ["~> 1.9.0"])
|
137
|
+
s.add_development_dependency(%q<vcr>, [">= 0"])
|
138
|
+
s.add_development_dependency(%q<pry>, [">= 0"])
|
139
|
+
else
|
140
|
+
s.add_dependency(%q<faraday>, [">= 0"])
|
141
|
+
s.add_dependency(%q<faraday_middleware>, [">= 0"])
|
142
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
143
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
144
|
+
s.add_dependency(%q<test-unit>, ["= 2.5.0"])
|
145
|
+
s.add_dependency(%q<mocha>, ["= 0.12.0"])
|
146
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.5"])
|
147
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
148
|
+
s.add_dependency(%q<webmock>, ["~> 1.9.0"])
|
149
|
+
s.add_dependency(%q<vcr>, [">= 0"])
|
150
|
+
s.add_dependency(%q<pry>, [">= 0"])
|
151
|
+
end
|
152
|
+
else
|
153
|
+
s.add_dependency(%q<faraday>, [">= 0"])
|
154
|
+
s.add_dependency(%q<faraday_middleware>, [">= 0"])
|
155
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
156
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
157
|
+
s.add_dependency(%q<test-unit>, ["= 2.5.0"])
|
158
|
+
s.add_dependency(%q<mocha>, ["= 0.12.0"])
|
159
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.5"])
|
160
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
161
|
+
s.add_dependency(%q<webmock>, ["~> 1.9.0"])
|
162
|
+
s.add_dependency(%q<vcr>, [">= 0"])
|
163
|
+
s.add_dependency(%q<pry>, [">= 0"])
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'ostruct'
|
3
|
+
module Faraday
|
4
|
+
# Catches exceptions and retries each request a limited number of times.
|
5
|
+
#
|
6
|
+
# By default, it retries 2 times and handles only timeout exceptions. It can
|
7
|
+
# be configured with an arbitrary number of retries, a list of exceptions to
|
8
|
+
# handle an a retry interval.
|
9
|
+
#
|
10
|
+
# Examples
|
11
|
+
#
|
12
|
+
# Faraday.new do |conn|
|
13
|
+
# conn.request :retry, max: 2, interval: 0.05,
|
14
|
+
# exceptions: [CustomException, 'Timeout::Error']
|
15
|
+
# conn.adapter ...
|
16
|
+
# end
|
17
|
+
class BetterRetry < Faraday::Middleware
|
18
|
+
class Options < OpenStruct
|
19
|
+
|
20
|
+
def max
|
21
|
+
(self[:max] ||= 2).to_i
|
22
|
+
end
|
23
|
+
|
24
|
+
def interval
|
25
|
+
(self[:interval] ||= 0).to_f
|
26
|
+
end
|
27
|
+
|
28
|
+
def exceptions
|
29
|
+
Array(self[:exceptions] ||= [Errno::ETIMEDOUT, 'Timeout::Error', Error::TimeoutError])
|
30
|
+
end
|
31
|
+
|
32
|
+
# define for ruby less than 2.0
|
33
|
+
def [](name)
|
34
|
+
@table[name.to_sym]
|
35
|
+
end
|
36
|
+
|
37
|
+
def []=(name, value)
|
38
|
+
modifiable[new_ostruct_member(name)] = value
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
# Public: Initialize middleware
|
44
|
+
#
|
45
|
+
# Options:
|
46
|
+
# max - Maximum number of retries (default: 2).
|
47
|
+
# interval - Pause in seconds between retries (default: 0).
|
48
|
+
# exceptions - The list of exceptions to handle. Exceptions can be
|
49
|
+
# given as Class, Module, or String. (default:
|
50
|
+
# [Errno::ETIMEDOUT, Timeout::Error, Error::TimeoutError])
|
51
|
+
def initialize(app, options = {})
|
52
|
+
super(app)
|
53
|
+
@options = Options.new(options)
|
54
|
+
@errmatch = build_exception_matcher(@options.exceptions)
|
55
|
+
@logger = options[:logger]
|
56
|
+
end
|
57
|
+
|
58
|
+
def call(env)
|
59
|
+
env[:retries] = retries = @options.max
|
60
|
+
begin
|
61
|
+
@app.call(env)
|
62
|
+
rescue @errmatch => e
|
63
|
+
if retries > 0
|
64
|
+
if @logger
|
65
|
+
@logger.warn("Retrying Parse Error #{e.inspect} on request #{env[:url].to_s} #{env[:body].inspect} response #{env[:response].inspect}")
|
66
|
+
end
|
67
|
+
retries -= 1
|
68
|
+
env[:retries] = retries
|
69
|
+
sleep @options.interval if @options.interval > 0
|
70
|
+
retry
|
71
|
+
end
|
72
|
+
raise
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Private: construct an exception matcher object.
|
77
|
+
#
|
78
|
+
# An exception matcher for the rescue clause can usually be any object that
|
79
|
+
# responds to `===`, but for Ruby 1.8 it has to be a Class or Module.
|
80
|
+
def build_exception_matcher(exceptions)
|
81
|
+
matcher = Module.new
|
82
|
+
(class << matcher; self; end).class_eval do
|
83
|
+
define_method(:===) do |error|
|
84
|
+
exceptions.any? do |ex|
|
85
|
+
if ex.is_a? Module then error.is_a? ex
|
86
|
+
else error.class.to_s == ex.to_s
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
matcher
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Faraday
|
3
|
+
|
4
|
+
class ExtendedParseJson < FaradayMiddleware::ParseJson
|
5
|
+
|
6
|
+
def process_response(env)
|
7
|
+
env[:raw_body] = env[:body] if preserve_raw?(env)
|
8
|
+
|
9
|
+
|
10
|
+
if env[:status] >= 400
|
11
|
+
data = parse(env[:body]) || {} rescue {}
|
12
|
+
|
13
|
+
array_codes = [
|
14
|
+
AV::Protocol::ERROR_INTERNAL,
|
15
|
+
AV::Protocol::ERROR_TIMEOUT,
|
16
|
+
AV::Protocol::ERROR_EXCEEDED_BURST_LIMIT
|
17
|
+
]
|
18
|
+
error_hash = { "error" => "HTTP Status #{env[:status]} Body #{env[:body]}", "http_status_code" => env[:status] }.merge(data)
|
19
|
+
if data['code'] && array_codes.include?(data['code'])
|
20
|
+
sleep 60 if data['code'] == AV::Protocol::ERROR_EXCEEDED_BURST_LIMIT
|
21
|
+
raise exception(env).new(error_hash.merge(data))
|
22
|
+
elsif env[:status] >= 500
|
23
|
+
raise exception(env).new(error_hash.merge(data))
|
24
|
+
end
|
25
|
+
raise AV::AVProtocolError.new(error_hash)
|
26
|
+
else
|
27
|
+
data = parse(env[:body]) || {}
|
28
|
+
|
29
|
+
env[:body] = data
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def exception env
|
34
|
+
# decide to retry or not
|
35
|
+
(env[:retries].to_i.zero? ? AV::AVProtocolError : AV::AVProtocolRetry)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
|
5
|
+
module Faraday
|
6
|
+
# Public: Writes the original HTTP method to "X-Http-Method-Override" header
|
7
|
+
# and sends the request as POST for GET requests that are too long.
|
8
|
+
class GetMethodOverride < Faraday::Middleware
|
9
|
+
|
10
|
+
HEADER = "X-Http-Method-Override".freeze
|
11
|
+
|
12
|
+
# Public: Initialize the middleware.
|
13
|
+
#
|
14
|
+
# app - the Faraday app to wrap
|
15
|
+
def initialize(app, options = nil)
|
16
|
+
super(app)
|
17
|
+
end
|
18
|
+
|
19
|
+
def call(env)
|
20
|
+
if env[:method] == :get && env[:url].to_s.size > 2000
|
21
|
+
env[:request_headers][HEADER] = 'GET'
|
22
|
+
env[:request_headers]['Content-Type'] =
|
23
|
+
'application/x-www-form-urlencoded'
|
24
|
+
env[:body] = env[:url].query
|
25
|
+
env[:url].query = nil
|
26
|
+
env[:method] = :post
|
27
|
+
end
|
28
|
+
|
29
|
+
@app.call(env)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
## ----------------------------------------------------------------------
|
3
|
+
##
|
4
|
+
## Ruby client for parse.com
|
5
|
+
## A quick library for playing with parse.com's REST API for object storage.
|
6
|
+
## See https://parse.com/docs/rest for full documentation on the API.
|
7
|
+
##
|
8
|
+
## ----------------------------------------------------------------------
|
9
|
+
require 'rubygems'
|
10
|
+
require 'bundler/setup'
|
11
|
+
|
12
|
+
require 'faraday'
|
13
|
+
require 'faraday_middleware'
|
14
|
+
require 'faraday/better_retry'
|
15
|
+
require 'faraday/extended_parse_json'
|
16
|
+
require 'faraday/get_method_override'
|
17
|
+
require 'date'
|
18
|
+
require 'cgi'
|
19
|
+
|
20
|
+
cwd = Pathname(__FILE__).dirname
|
21
|
+
$:.unshift(cwd.to_s) unless $:.include?(cwd.to_s) || $:.include?(cwd.expand_path.to_s)
|
22
|
+
|
23
|
+
require 'leancloud/object'
|
24
|
+
require 'leancloud/query'
|
25
|
+
require 'leancloud/datatypes'
|
26
|
+
require 'leancloud/util'
|
27
|
+
require 'leancloud/protocol'
|
28
|
+
require 'leancloud/user'
|
29
|
+
require "leancloud/installation"
|
30
|
+
require 'leancloud/push'
|
31
|
+
require 'leancloud/cloud'
|
32
|
+
require 'leancloud/model'
|
33
|
+
require 'leancloud/batch'
|
34
|
+
require 'leancloud/application'
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module AV
|
3
|
+
class Batch
|
4
|
+
attr_reader :requests
|
5
|
+
attr_reader :client
|
6
|
+
|
7
|
+
def initialize(client = AV.client)
|
8
|
+
@client = client
|
9
|
+
@requests ||= []
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_request(request)
|
13
|
+
@requests << request
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_object(object)
|
17
|
+
method = "POST"
|
18
|
+
path = AV::Protocol.class_uri(object.class_name)
|
19
|
+
body = object.safe_hash
|
20
|
+
add_request({
|
21
|
+
"method" => method,
|
22
|
+
"path" => path,
|
23
|
+
"body" => body
|
24
|
+
})
|
25
|
+
end
|
26
|
+
|
27
|
+
def update_object(object)
|
28
|
+
method = "PUT"
|
29
|
+
path = AV::Protocol.class_uri(object.class_name, object.id)
|
30
|
+
body = object.safe_hash
|
31
|
+
add_request({
|
32
|
+
"method" => method,
|
33
|
+
"path" => path,
|
34
|
+
"body" => body
|
35
|
+
})
|
36
|
+
end
|
37
|
+
|
38
|
+
def delete_object(object)
|
39
|
+
add_request({
|
40
|
+
"method" => "DELETE",
|
41
|
+
"path" => AV::Protocol.class_uri(object.class_name, object.id)
|
42
|
+
})
|
43
|
+
end
|
44
|
+
|
45
|
+
def run!
|
46
|
+
uri = AV::Protocol.batch_request_uri
|
47
|
+
body = {:requests => @requests}.to_json
|
48
|
+
@client.request(uri, :post, body)
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'leancloud/protocol'
|
3
|
+
require 'leancloud/error'
|
4
|
+
require 'leancloud/util'
|
5
|
+
|
6
|
+
require 'logger'
|
7
|
+
module AV
|
8
|
+
|
9
|
+
# A class which encapsulates the HTTPS communication with the Parse
|
10
|
+
# API server.
|
11
|
+
class Client
|
12
|
+
attr_accessor :host
|
13
|
+
attr_accessor :application_id
|
14
|
+
attr_accessor :api_key
|
15
|
+
attr_accessor :master_key
|
16
|
+
attr_accessor :session_token
|
17
|
+
attr_accessor :session
|
18
|
+
attr_accessor :max_retries
|
19
|
+
attr_accessor :logger
|
20
|
+
attr_accessor :quiet
|
21
|
+
|
22
|
+
def initialize(data = {}, &blk)
|
23
|
+
@host = data[:host] || Protocol::HOST
|
24
|
+
@application_id = data[:application_id]
|
25
|
+
@api_key = data[:api_key]
|
26
|
+
@master_key = data[:master_key]
|
27
|
+
@session_token = data[:session_token]
|
28
|
+
@max_retries = data[:max_retries] || 3
|
29
|
+
@logger = data[:logger] || Logger.new(STDERR).tap{|l| l.level = Logger::INFO}
|
30
|
+
@quiet = data[:quiet] || false
|
31
|
+
|
32
|
+
options = {:request => {:timeout => 30, :open_timeout => 30}}
|
33
|
+
|
34
|
+
@session = Faraday.new("https://#{host}", options) do |c|
|
35
|
+
c.request :json
|
36
|
+
|
37
|
+
c.use Faraday::GetMethodOverride
|
38
|
+
|
39
|
+
c.use Faraday::BetterRetry,
|
40
|
+
max: @max_retries,
|
41
|
+
logger: @logger,
|
42
|
+
interval: 0.5,
|
43
|
+
exceptions: ['Faraday::Error::TimeoutError', 'Faraday::Error::ParsingError', 'AV::AVProtocolRetry']
|
44
|
+
c.use Faraday::ExtendedParseJson
|
45
|
+
|
46
|
+
c.response :logger, @logger unless @quiet
|
47
|
+
c.adapter Faraday.default_adapter
|
48
|
+
|
49
|
+
yield(c) if block_given?
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Perform an HTTP request for the given uri and method
|
54
|
+
# with common basic response handling. Will raise a
|
55
|
+
# AVProtocolError if the response has an error status code,
|
56
|
+
# and will return the parsed JSON body on success, if there is one.
|
57
|
+
def request(uri, method = :get, body = nil, query = nil, content_type = nil)
|
58
|
+
headers = {}
|
59
|
+
|
60
|
+
{
|
61
|
+
"Content-Type" => content_type || 'application/json',
|
62
|
+
"User-Agent" => 'Parse for Ruby, 0.0',
|
63
|
+
Protocol::HEADER_MASTER_KEY => @master_key,
|
64
|
+
Protocol::HEADER_APP_ID => @application_id,
|
65
|
+
Protocol::HEADER_API_KEY => @api_key,
|
66
|
+
Protocol::HEADER_SESSION_TOKEN => @session_token,
|
67
|
+
}.each do |key, value|
|
68
|
+
headers[key] = value if value
|
69
|
+
end
|
70
|
+
|
71
|
+
@session.send(method, uri, query || body || {}, headers).body
|
72
|
+
end
|
73
|
+
|
74
|
+
def get(uri)
|
75
|
+
request(uri)
|
76
|
+
end
|
77
|
+
|
78
|
+
def post(uri, body)
|
79
|
+
request(uri, :post, body)
|
80
|
+
end
|
81
|
+
|
82
|
+
def put(uri, body)
|
83
|
+
request(uri, :put, body)
|
84
|
+
end
|
85
|
+
|
86
|
+
def delete(uri)
|
87
|
+
request(uri, :delete)
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
# Module methods
|
94
|
+
# ------------------------------------------------------------
|
95
|
+
class << self
|
96
|
+
# A singleton client for use by methods in Object.
|
97
|
+
# Always use AV.client to retrieve the client object.
|
98
|
+
@client = nil
|
99
|
+
|
100
|
+
# Initialize the singleton instance of Client which is used
|
101
|
+
# by all API methods. AV.init must be called before saving
|
102
|
+
# or retrieving any objects.
|
103
|
+
def init(data = {}, &blk)
|
104
|
+
defaults = {:application_id => ENV["LC_APPLICATION_ID"], :api_key => ENV["LC_APPLICATION_KEY"]}
|
105
|
+
defaults.merge!(data)
|
106
|
+
|
107
|
+
# use less permissive key if both are specified
|
108
|
+
defaults[:master_key] = ENV["PARSE_MASTER_API_KEY"] unless data[:master_key] || defaults[:api_key]
|
109
|
+
@@client = Client.new(defaults, &blk)
|
110
|
+
end
|
111
|
+
|
112
|
+
# A convenience method for using global.json
|
113
|
+
def init_from_cloud_code(path = "../config/global.json")
|
114
|
+
# warning: toplevel constant File referenced by AV::Object::File
|
115
|
+
global = JSON.parse(Object::File.open(path).read)
|
116
|
+
application_name = global["applications"]["_default"]["link"]
|
117
|
+
application_id = global["applications"][application_name]["applicationId"]
|
118
|
+
master_key = global["applications"][application_name]["masterKey"]
|
119
|
+
self.init(:application_id => application_id, :master_key => master_key)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Used mostly for testing. Lets you delete the api key global vars.
|
123
|
+
def destroy
|
124
|
+
@@client = nil
|
125
|
+
self
|
126
|
+
end
|
127
|
+
|
128
|
+
def client
|
129
|
+
raise AVError, "API not initialized" if !@@client
|
130
|
+
@@client
|
131
|
+
end
|
132
|
+
|
133
|
+
# Perform a simple retrieval of a simple object, or all objects of a
|
134
|
+
# given class. If object_id is supplied, a single object will be
|
135
|
+
# retrieved. If object_id is not supplied, then all objects of the
|
136
|
+
# given class will be retrieved and returned in an Array.
|
137
|
+
def get(class_name, object_id = nil)
|
138
|
+
data = self.client.get( Protocol.class_uri(class_name, object_id) )
|
139
|
+
self.parse_json class_name, data
|
140
|
+
rescue AVProtocolError => e
|
141
|
+
if e.code == Protocol::ERROR_OBJECT_NOT_FOUND_FOR_GET
|
142
|
+
e.message += ": #{class_name}:#{object_id}"
|
143
|
+
end
|
144
|
+
raise
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
|