-
Notifications
You must be signed in to change notification settings - Fork 132
Expand file tree
/
Copy pathclient.rb
More file actions
208 lines (171 loc) · 6.1 KB
/
client.rb
File metadata and controls
208 lines (171 loc) · 6.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# encoding: utf-8
require 'parse/protocol'
require 'parse/error'
require 'parse/util'
require 'logger'
# This module contains all the code
module Parse
# The client that communicates with the Parse server via REST
class Client
RETRIED_EXCEPTIONS = [
'Faraday::TimeoutError',
'Faraday::ParsingError',
'Faraday::ConnectionFailed',
'Parse::ParseProtocolRetry'
]
attr_accessor :host
attr_accessor :path
attr_accessor :application_id
attr_accessor :api_key
attr_accessor :master_key
attr_accessor :session_token
attr_accessor :session
attr_accessor :max_retries
attr_accessor :logger
attr_accessor :quiet
attr_accessor :timeout
attr_accessor :interval
attr_accessor :backoff_factor
attr_accessor :retried_exceptions
attr_reader :get_method_override
def initialize(data = {}, &_blk)
@host = data[:host]
@path = data[:path] || Protocol::PATH
@application_id = data[:application_id]
@master_key = data[:master_key]
@api_key = data[:api_key]
@session_token = data[:session_token]
@max_retries = data[:max_retries] || 3
@logger = data[:logger] || Logger
.new(STDERR).tap { |l| l.level = Logger::INFO }
@quiet = data[:quiet] || false
@timeout = data[:timeout] || 30
# Additional parameters for Faraday Request::Retry
@interval = data[:interval] || 0.5
@backoff_factor = data[:backoff_factor] || 2
@retried_exceptions = RETRIED_EXCEPTIONS
@retried_exceptions += data[:retried_exceptions] if data[
:retried_exceptions]
@get_method_override = data[:get_method_override]
options = { request: { timeout: @timeout, open_timeout: @timeout } }
@session = Faraday.new(host, options) do |c|
c.request :json
c.use Faraday::GetMethodOverride if @get_method_override
c.use Faraday::BetterRetry,
max: @max_retries,
logger: @logger,
interval: @interval,
backoff_factor: @backoff_factor,
exceptions: @retried_exceptions
c.use Faraday::ExtendedParseJson
c.response :logger, @logger unless @quiet
c.adapter Faraday.default_adapter
yield(c) if block_given?
end
end
# Perform an HTTP request for the given uri and method
# with common basic response handling. Will raise a
# ParseProtocolError if the response has an error status code,
# and will return the parsed JSON body on success, if there is one.
def request(uri, method = :get, body = nil, query = nil, content_type = nil)
headers = {}
{
'Content-Type' => content_type || 'application/json',
'User-Agent' => "Parse for Ruby, #{VERSION}",
Protocol::HEADER_MASTER_KEY => @master_key,
Protocol::HEADER_APP_ID => @application_id,
Protocol::HEADER_API_KEY => @api_key,
Protocol::HEADER_SESSION_TOKEN => @session_token
}.each do |key, value|
headers[key] = value if value
end
uri = ::File.join(path, uri)
response = @session.send(method, uri, query || body || {}, headers)
response.body
# NOTE: Don't leak our internal libraries to our clients.
# Extend this list of exceptions as needed.
rescue Faraday::ClientError, Faraday::ConnectionFailed => e
raise Parse::ConnectionError, e.message
end
def get(uri)
request(uri)
end
def post(uri, body)
request(uri, :post, body)
end
def put(uri, body)
request(uri, :put, body)
end
def delete(uri)
request(uri, :delete)
end
def application_config
Parse::Application.config(self)
end
def batch
Parse::Batch.new(self)
end
def cloud_function(function_name)
Parse::Cloud::Function.new(function_name, self)
end
def file(data)
Parse::File.new(data, self)
end
def object(class_name, data = nil)
Parse::Object.new(class_name, data, self)
end
def push(data, channel = '')
Parse::Push.new(data, channel, self)
end
def installation(object_id = nil)
Parse::Installation.new(object_id, self)
end
def query(class_name)
Parse::Query.new(class_name, self)
end
def user(data)
Parse::User.new(data, self)
end
end
# Module methods
# ------------------------------------------------------------
class << self
# Factory to create instances of Client.
def create(data = {}, &blk)
options = defaults = {
application_id: ENV['PARSE_APPLICATION_ID'],
master_key: ENV['PARSE_MASTER_API_KEY'],
api_key: ENV['PARSE_REST_API_KEY'],
get_method_override: true
}.merge(data)
Client.new(options, &blk)
end
alias :init :create
# A convenience method for using global.json
def init_from_cloud_code(path = '../config/global.json', app_name = nil)
global = JSON.parse(::File.open(path).read)
applications = global['applications']
app_name = applications['_default']['link'] if app_name.nil?
application_id = applications[app_name]['applicationId']
master_key = applications[app_name]['masterKey']
create(application_id: application_id, master_key: master_key)
end
# Perform a simple retrieval of a simple object, or all objects of a
# given class. If object_id is supplied, a single object will be
# retrieved. If object_id is not supplied, then all objects of the
# given class will be retrieved and returned in an Array.
# Accepts an explicit client object to avoid using the legacy singleton.
def get(class_name, object_id = nil, parse_client = nil)
c = parse_client || client
data = c.get(Protocol.class_uri(class_name, object_id))
object = Parse.parse_json(class_name, data)
object = Parse.copy_client(c, object)
object
rescue ParseProtocolError => e
if e.code == Protocol::ERROR_OBJECT_NOT_FOUND_FOR_GET
e.message += ": #{class_name}:#{object_id}"
end
raise
end
end
end