Class: Parse::Client
- Inherits:
- Object
- Object
- Parse::Client
- Includes:
- API::Aggregate, API::Analytics, API::Batch, API::CloudFunctions, API::Config, API::Files, API::Hooks, API::Objects, API::Push, API::Schema, API::Server, API::Sessions, API::Users
- Defined in:
- lib/parse/client.rb
Overview
This class is the core and low level API for the Parse SDK REST interface that is used by the other components. It can manage multiple sessions, which means you can have multiple client instances pointing to different Parse Applications at the same time. It handles sending raw requests as well as providing Request/Response objects for all API handlers. The connection engine is Faraday, which means it is open to add any additional middleware for features you'd like to implement.
Defined Under Namespace
Modules: Connectable Classes: ResponseError
Constant Summary collapse
- USER_AGENT_HEADER =
The user agent header key.
"User-Agent".freeze
- USER_AGENT_VERSION =
The value for the User-Agent header.
"Parse-Stack v#{Parse::Stack::VERSION}".freeze
- DEFAULT_RETRIES =
The default retry count
2
- RETRY_DELAY =
The wait time in seconds between retries
1.5
Constants included from API::Hooks
Class Attribute Summary collapse
- .clients ⇒ Object readonly
Returns the value of attribute clients.
Instance Attribute Summary collapse
- #api_key ⇒ String readonly
The Parse API key to be sent in every API request.
- #application_id ⇒ String (also: #app_id) readonly
The Parse application identifier to be sent in every API request.
- #cache ⇒ Moneta::Transformer, Moneta::Expires
The underlying cache store for caching API requests.
- #master_key ⇒ String readonly
The Parse master key for this application, which when set, will be sent in every API request.
- #retry_limit ⇒ Integer
If set, returns the current retry count for this instance.
- #server_url ⇒ String readonly
The Parse server url that will be receiving these API requests.
Attributes included from API::Server
Attributes included from API::Config
Class Method Summary collapse
- .client(conn = :default) ⇒ Parse::Client
Returns or create a new Parse::Client connection for the given connection name.
- .client?(conn = :default) ⇒ Boolean
True if a Parse::Client has been configured.
- .setup(opts = {}) { ... } ⇒ Client
Setup the a new client with the appropriate Parse app keys, middleware and options.
Instance Method Summary collapse
- #clear_cache! ⇒ Object
Clear the client cache.
- #delete(uri, body = nil, headers = {}) ⇒ Parse::Response
Send a DELETE request.
- #get(uri, query = nil, headers = {}) ⇒ Parse::Response
Send a GET request.
- #initialize(opts = {}) ⇒ Client constructor
Create a new client connected to the Parse Server REST API endpoint.
- #post(uri, body = nil, headers = {}) ⇒ Parse::Response
Send a POST request.
- #put(uri, body = nil, headers = {}) ⇒ Parse::Response
Send a PUT request.
- #request(method, uri = nil, body: nil, query: nil, headers: nil, opts: {}) ⇒ Parse::Response
Send a REST API request to the server.
- #send_request(req) ⇒ Parse::Response
Send a Request object.
- #url_prefix ⇒ String
The url prefix of the Parse Server url.
Methods included from API::Users
#create_user, #current_user, #delete_user, #fetch_user, #find_users, #login, #logout, #request_password_reset, #set_service_auth_data, #signup, #update_user
Methods included from API::Sessions
Methods included from API::Server
#server_health, #server_info!, #server_version
Methods included from API::Schema
#create_schema, #schema, #schemas, #update_schema
Methods included from API::Push
Methods included from API::Objects
#create_object, #delete_object, #fetch_object, #find_objects, #update_object, #uri_path
Methods included from API::Hooks
#create_function, #create_trigger, #delete_function, #delete_trigger, #fetch_function, #fetch_trigger, #functions, #triggers, #update_function, #update_trigger
Methods included from API::Files
Methods included from API::Config
Methods included from API::CloudFunctions
Methods included from API::Batch
Methods included from API::Aggregate
#aggregate_objects, #aggregate_uri_path
Methods included from API::Analytics
Constructor Details
#initialize(opts = {}) ⇒ Client
Create a new client connected to the Parse Server REST API endpoint.
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 | # File 'lib/parse/client.rb', line 250 def initialize(opts = {}) @server_url = opts[:server_url] || ENV["PARSE_SERVER_URL"] || Parse::Protocol::SERVER_URL @application_id = opts[:application_id] || opts[:app_id] || ENV["PARSE_SERVER_APPLICATION_ID"] || ENV["PARSE_APP_ID"] @api_key = opts[:api_key] || opts[:rest_api_key] || ENV["PARSE_SERVER_REST_API_KEY"] || ENV["PARSE_API_KEY"] @master_key = opts[:master_key] || ENV["PARSE_SERVER_MASTER_KEY"] || ENV["PARSE_MASTER_KEY"] opts[:adapter] ||= Faraday.default_adapter opts[:expires] ||= 3 if @server_url.nil? || @application_id.nil? || (@api_key.nil? && @master_key.nil?) raise Parse::Error::ConnectionError, "Please call Parse.setup(server_url:, application_id:, api_key:) to setup a client" end @server_url += "/" unless @server_url.ends_with?("/") #Configure Faraday opts[:faraday] ||= {} opts[:faraday].merge!(:url => @server_url) @conn = Faraday.new(opts[:faraday]) do |conn| #conn.request :json conn.response :logger if opts[:logging] # This middleware handles sending the proper authentication headers to Parse # on each request. # this is the required authentication middleware. Should be the first thing # so that other middlewares have access to the env that is being set by # this middleware. First added is first to brocess. conn.use Parse::Middleware::Authentication, application_id: @application_id, master_key: @master_key, api_key: @api_key # This middleware turns the result from Parse into a Parse::Response object # and making sure request that are going out, follow the proper MIME format. # We place it after the Authentication middleware in case we need to use then # authentication information when building request and responses. conn.use Parse::Middleware::BodyBuilder if opts[:logging].present? && opts[:logging] == :debug Parse::Middleware::BodyBuilder.logging = true end if opts[:cache].present? && opts[:expires].to_i > 0 # advanced: provide a REDIS url, we'll configure a Moneta Redis store. if opts[:cache].is_a?(String) && opts[:cache].starts_with?("redis://") begin opts[:cache] = Moneta.new(:Redis, url: opts[:cache]) rescue LoadError puts "[Parse::Middleware::Caching] Did you forget to load the redis gem (Gemfile)?" raise end end unless [:key?, :[], :delete, :store].all? { |method| opts[:cache].respond_to?(method) } raise ArgumentError, "Parse::Client option :cache needs to be a type of Moneta store" end self.cache = opts[:cache] conn.use Parse::Middleware::Caching, self.cache, { expires: opts[:expires].to_i } end yield(conn) if block_given? conn.adapter opts[:adapter] end Parse::Client.clients[:default] ||= self end |
Class Attribute Details
.clients ⇒ Object (readonly)
Returns the value of attribute clients.
174 175 176 | # File 'lib/parse/client.rb', line 174 def clients @clients end |
Instance Attribute Details
#api_key ⇒ String (readonly)
The Parse API key to be sent in every API request.
163 | # File 'lib/parse/client.rb', line 163 attr_accessor :cache, :retry_limit |
#application_id ⇒ String (readonly) Also known as: app_id
The Parse application identifier to be sent in every API request.
163 | # File 'lib/parse/client.rb', line 163 attr_accessor :cache, :retry_limit |
#cache ⇒ Moneta::Transformer, Moneta::Expires
The underlying cache store for caching API requests.
163 164 165 | # File 'lib/parse/client.rb', line 163 def cache @cache end |
#master_key ⇒ String (readonly)
The Parse master key for this application, which when set, will be sent in every API request. (There is a way to prevent this on a per request basis.)
163 | # File 'lib/parse/client.rb', line 163 attr_accessor :cache, :retry_limit |
#retry_limit ⇒ Integer
If set, returns the current retry count for this instance. Otherwise, returns DEFAULT_RETRIES. Set to 0 to disable retry mechanism.
163 | # File 'lib/parse/client.rb', line 163 attr_accessor :cache, :retry_limit |
#server_url ⇒ String (readonly)
The Parse server url that will be receiving these API requests. By default this will be Protocol::SERVER_URL.
163 | # File 'lib/parse/client.rb', line 163 attr_accessor :cache, :retry_limit |
Class Method Details
.client(conn = :default) ⇒ Parse::Client
Returns or create a new Parse::Client connection for the given connection name.
186 187 188 | # File 'lib/parse/client.rb', line 186 def client(conn = :default) @clients[conn] ||= self.new end |
.client?(conn = :default) ⇒ Boolean
Returns true if a Parse::Client has been configured.
178 179 180 | # File 'lib/parse/client.rb', line 178 def client?(conn = :default) @clients[conn].present? end |
.setup(opts = {}) { ... } ⇒ Client
Setup the a new client with the appropriate Parse app keys, middleware and options.
205 206 207 | # File 'lib/parse/client.rb', line 205 def setup(opts = {}) @clients[:default] = self.new(opts, &Proc.new) end |
Instance Method Details
#clear_cache! ⇒ Object
Clear the client cache
327 328 329 | # File 'lib/parse/client.rb', line 327 def clear_cache! self.cache.clear if self.cache.present? end |
#delete(uri, body = nil, headers = {}) ⇒ Parse::Response
Send a DELETE request.
528 529 530 | # File 'lib/parse/client.rb', line 528 def delete(uri, body = nil, headers = {}) request :delete, uri, body: body, headers: headers end |
#get(uri, query = nil, headers = {}) ⇒ Parse::Response
Send a GET request.
501 502 503 | # File 'lib/parse/client.rb', line 501 def get(uri, query = nil, headers = {}) request :get, uri, query: query, headers: headers end |
#post(uri, body = nil, headers = {}) ⇒ Parse::Response
Send a POST request.
510 511 512 | # File 'lib/parse/client.rb', line 510 def post(uri, body = nil, headers = {}) request :post, uri, body: body, headers: headers end |
#put(uri, body = nil, headers = {}) ⇒ Parse::Response
Send a PUT request.
519 520 521 | # File 'lib/parse/client.rb', line 519 def put(uri, body = nil, headers = {}) request :put, uri, body: body, headers: headers end |
#request(method, uri = nil, body: nil, query: nil, headers: nil, opts: {}) ⇒ Parse::Response
Send a REST API request to the server. This is the low-level API used for all requests to the Parse server with the provided options. Every request sent to Parse through the client goes through the configured set of middleware that can be modified by applying different headers or specific options. This method supports retrying requests a few times when a ServiceUnavailableError is raised.
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 | # File 'lib/parse/client.rb', line 378 def request(method, uri = nil, body: nil, query: nil, headers: nil, opts: {}) _retry_count ||= self.retry_limit if opts[:retry] == false _retry_count = 0 elsif opts[:retry].to_i > 0 _retry_count = opts[:retry] end headers ||= {} # if the first argument is a Parse::Request object, then construct it _request = nil if method.is_a?(Request) _request = method method = _request.method uri ||= _request.path query ||= _request.query body ||= _request.body headers.merge! _request.headers else _request = Parse::Request.new(method, uri, body: body, headers: headers, opts: opts) end # http method method = method.downcase.to_sym # set the User-Agent headers[USER_AGENT_HEADER] = USER_AGENT_VERSION if opts[:cache] == false headers[Parse::Middleware::Caching::CACHE_CONTROL] = "no-cache" elsif opts[:cache].is_a?(Numeric) # specify the cache duration of this request headers[Parse::Middleware::Caching::CACHE_EXPIRES_DURATION] = opts[:cache].to_s end if opts[:use_master_key] == false headers[Parse::Middleware::Authentication::DISABLE_MASTER_KEY] = "true" end token = opts[:session_token] if token.present? token = token.session_token if token.respond_to?(:session_token) headers[Parse::Middleware::Authentication::DISABLE_MASTER_KEY] = "true" headers[Parse::Protocol::SESSION_TOKEN] = token end #if it is a :get request, then use query params, otherwise body. params = (method == :get ? query : body) || {} # if the path does not start with the '/1/' prefix, then add it to be nice. # actually send the request and return the body response_env = @conn.send(method, uri, params, headers) response = response_env.body response.request = _request case response.http_status when 401, 403 warn "[Parse:AuthenticationError] #{response}" raise Parse::Error::AuthenticationError, response when 400, 408 if response.code == Parse::Response::ERROR_TIMEOUT || response.code == 143 #"net/http: timeout awaiting response headers" warn "[Parse:TimeoutError] #{response}" raise Parse::Error::TimeoutError, response end when 404 unless response.object_not_found? warn "[Parse:ConnectionError] #{response}" raise Parse::Error::ConnectionError, response end when 405, 406 warn "[Parse:ProtocolError] #{response}" raise Parse::Error::ProtocolError, response when 429 # Request over the throttle limit warn "[Parse:RequestLimitExceededError] #{response}" raise Parse::Error::RequestLimitExceededError, response when 500, 503 warn "[Parse:ServiceUnavailableError] #{response}" raise Parse::Error::ServiceUnavailableError, response end if response.error? if response.code <= Parse::Response::ERROR_SERVICE_UNAVAILABLE warn "[Parse:ServiceUnavailableError] #{response}" raise Parse::Error::ServiceUnavailableError, response elsif response.code <= 100 warn "[Parse:ServerError] #{response}" raise Parse::Error::ServerError, response elsif response.code == Parse::Response::ERROR_EXCEEDED_BURST_LIMIT warn "[Parse:RequestLimitExceededError] #{response}" raise Parse::Error::RequestLimitExceededError, response elsif response.code == 209 # Error 209: invalid session token warn "[Parse:InvalidSessionTokenError] #{response}" raise Parse::Error::InvalidSessionTokenError, response end end response rescue Parse::Error::RequestLimitExceededError, Parse::Error::ServiceUnavailableError => e if _retry_count > 0 warn "[Parse:Retry] Retries remaining #{_retry_count} : #{response.request}" _retry_count -= 1 backoff_delay = RETRY_DELAY * (self.retry_limit - _retry_count) _retry_delay = [0, RETRY_DELAY, backoff_delay].sample sleep _retry_delay if _retry_delay > 0 retry end raise rescue Faraday::Error::ClientError, Net::OpenTimeout => e if _retry_count > 0 warn "[Parse:Retry] Retries remaining #{_retry_count} : #{_request}" _retry_count -= 1 backoff_delay = RETRY_DELAY * (self.retry_limit - _retry_count) _retry_delay = [0, RETRY_DELAY, backoff_delay].sample sleep _retry_delay if _retry_delay > 0 retry end raise Parse::Error::ConnectionError, "#{_request} : #{e.class} - #{e.}" end |
#send_request(req) ⇒ Parse::Response
Send a Request object.
536 537 538 539 | # File 'lib/parse/client.rb', line 536 def send_request(req) #Parse::Request object raise ArgumentError, "Object not of Parse::Request type." unless req.is_a?(Parse::Request) request req.method, req.path, req.body, req.headers end |
#url_prefix ⇒ String
Returns the url prefix of the Parse Server url.
322 323 324 | # File 'lib/parse/client.rb', line 322 def url_prefix @conn.url_prefix end |