vng 1.2.0 → 1.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6331c32b323783c597456c56d604a7896c3a5d1219fe2f8c9a6f1f83299075eb
4
- data.tar.gz: e90b4794467713d98f0adfc3c3edb5f0e8fae0d6264b77752d6aa71b06715b61
3
+ metadata.gz: d55841e2ab8e3e620c5bd29d8c994cbbb441a327ab3006ee262c3c44f207fda1
4
+ data.tar.gz: d4fb1cd2865d72faa464711cd03d61974a991d53e766310523ee5adc0353ba1e
5
5
  SHA512:
6
- metadata.gz: 25dd494526c573d342f30f6a1b393d2972b50ea74b60ccb56f6097b38e23c01b225576b5337fcf9c638a30e66119ec4217b1d9268b7fbf0d3c46a08e2ddbc570
7
- data.tar.gz: 64db905f1777fe5e1866d84ea9c1d7a6eb3c224c5a5ee7680fdf319803cfbe64f15ec296e26342ab4ad5da0f09248b770d182548bf0218eb8e2356ac4fe6b498
6
+ metadata.gz: f118bbfc089a69e924fdcc0948de07dbb20217d4b5556a0e80abea896734f545199f27afdf1edf7c6d1c3ffec2ee9a6a04497a7629527e1623c44ba5ea75e894
7
+ data.tar.gz: fce28eb9405e05bc3620e67a53942ae901ec0f655dca7e640755ac231c975b262329596ec5dbd6a5e0dfa6180ebd5b2edc9d95503b3e8f09db0f670c97618920
data/CHANGELOG.md CHANGED
@@ -1,4 +1,8 @@
1
- ## [Unreleased]
1
+ ## [Unreleased] -
2
+
3
+ ## [1.3] - 2024-11-21
4
+
5
+ - Adds MockRequest which can be set with VNG_MOCK=1
2
6
 
3
7
  ## [1.2] - 2024-11-20
4
8
 
data/README.md CHANGED
@@ -84,7 +84,14 @@ To run tests:
84
84
  rspec
85
85
  ```
86
86
 
87
- Set `VNG_MOCK=1` to test against HTTP mocks.
87
+ By default, tests are run with real HTTP calls to Vonigo that must be
88
+ set with the environment variables specified above.
89
+
90
+ If you do not have access to Vonigo, you can still run the tests mocked:
91
+
92
+ ```bash
93
+ VNG_MOCK=1 rspec
94
+ ```
88
95
 
89
96
  How to release new versions
90
97
  ===========================
@@ -1,3 +1,4 @@
1
+ require 'date'
1
2
  require 'vng/resource'
2
3
 
3
4
  module Vng
data/lib/vng/franchise.rb CHANGED
@@ -21,7 +21,7 @@ module Vng
21
21
  zip: zip,
22
22
  }
23
23
 
24
- data = request path: Vng::Availability::PATH, body: body
24
+ data = request path: Availability::PATH, body: body
25
25
 
26
26
  franchise_id = data['Ids']['franchiseID']
27
27
  new(id: franchise_id) unless franchise_id == '0'
@@ -0,0 +1,95 @@
1
+ require 'json'
2
+ require 'net/http'
3
+
4
+ require 'vng/connection_error'
5
+ require 'vng/error'
6
+
7
+ module Vng
8
+ # A wrapper around +Net::HTTP+ to send HTTP requests to the Vonigo API and
9
+ # return their result or raise an error if the result is unexpected.
10
+ # The basic way to use HTTPRequest is by calling +run+ on an instance.
11
+ # @example List the species of all breeds.
12
+ # host = ''subdomain.vonigo.com'
13
+ # path = '/api/v1/resources/breeds/'
14
+ # body = {securityToken: security_token}
15
+ # response = Vng::HTTPRequest.new(path: path, body: body).run
16
+ # response['Breeds'].map{|breed| breed['species']}
17
+ # @api private
18
+ class Request
19
+ # Initializes an HTTPRequest object.
20
+ # @param [Hash] options the options for the request.
21
+ # @option options [String] :host The host of the request URI.
22
+ # @option options [String] :path The path of the request URI.
23
+ # @option options [Hash] :query ({}) The params to use as the query
24
+ # component of the request URI, for instance the Hash +{a: 1, b: 2}+
25
+ # corresponds to the query parameters +"a=1&b=2"+.
26
+ # @option options [Hash] :body The body of the request.
27
+ def initialize(options = {})
28
+ @host = options[:host]
29
+ @path = options[:path]
30
+ @body = options[:body]
31
+ @query = options.fetch :query, {}
32
+ end
33
+
34
+ # Sends the request and returns the body parsed from the JSON response.
35
+ # @return [Hash] the body parsed from the JSON response.
36
+ # @raise [Vng::ConnectionError] if the request fails.
37
+ # @raise [Vng::Error] if parsed body includes errors.
38
+ def run
39
+ return {} if response.body.empty?
40
+ JSON(response.body).tap do |data|
41
+ raise Error, "#{data['errMsg']} #{data['Errors']}" unless data['errNo'].zero?
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ # Run the request and memoize the response or the server error received.
48
+ def response
49
+ @response ||= Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
50
+ http.request http_request
51
+ end
52
+ rescue *server_errors => e
53
+ raise ConnectionError, e.message
54
+ end
55
+
56
+ # @return [URI::HTTPS] the (memoized) URI of the request.
57
+ def uri
58
+ attributes = { host: @host, path: @path, query: URI.encode_www_form(@query) }
59
+ @uri ||= URI::HTTPS.build attributes
60
+ end
61
+
62
+ # @return [Net::HTTPRequest] the full HTTP request object,
63
+ # inclusive of headers of request body.
64
+ def http_request
65
+ http_class = @query.any? ? Net::HTTP::Get : Net::HTTP::Post
66
+
67
+ @http_request ||= http_class.new(uri.request_uri).tap do |request|
68
+ set_request_body! request
69
+ set_request_headers! request
70
+ end
71
+ end
72
+
73
+ # Adds the request headers to the request in the appropriate format.
74
+ # The User-Agent header is also set to recognize the request.
75
+ def set_request_headers!(request)
76
+ request.initialize_http_header 'Content-Type' => 'application/json'
77
+ request.add_field 'User-Agent', 'Vng::HTTPRequest'
78
+ end
79
+
80
+ # Adds the request body to the request in the appropriate format.
81
+ def set_request_body!(request)
82
+ request.body = @body.to_json if @body
83
+ end
84
+
85
+ # Returns the list of server errors worth retrying the request once.
86
+ def server_errors
87
+ [
88
+ Errno::ECONNRESET, Errno::EHOSTUNREACH, Errno::ENETUNREACH,
89
+ Errno::ETIMEDOUT, Errno::ECONNREFUSED, Net::HTTPServerError,
90
+ OpenSSL::SSL::SSLError, OpenSSL::SSL::SSLErrorWaitReadable,
91
+ Net::OpenTimeout, SocketError,
92
+ ]
93
+ end
94
+ end
95
+ end
data/lib/vng/lock.rb CHANGED
@@ -22,7 +22,7 @@ module Vng
22
22
  startTime: minutes,
23
23
  }
24
24
 
25
- data = request path: Vng::Availability::PATH, body: body
25
+ data = request path: Availability::PATH, body: body
26
26
 
27
27
  new id: data['Ids']['lockID']
28
28
  end
@@ -0,0 +1,130 @@
1
+ module Vng
2
+ # A mock version of HTTPRequest which returns pre-built responses.
3
+ # @example List the species of all breeds.
4
+ # host = ''subdomain.vonigo.com'
5
+ # path = '/api/v1/resources/breeds/'
6
+ # body = {securityToken: security_token}
7
+ # response = Vng::Request.new(path: path, body: body).run
8
+ # response['Breeds'].map{|breed| breed['species']}
9
+ # @api private
10
+ class Request
11
+ # Initializes an MockRequest object.
12
+ # @param [Hash] options the options for the request.
13
+ # @option options [String] :host The host of the request URI.
14
+ # @option options [String] :path The path of the request URI.
15
+ # @option options [Hash] :query ({}) The params to use as the query
16
+ # component of the request URI, for instance the Hash +{a: 1, b: 2}+
17
+ # corresponds to the query parameters +"a=1&b=2"+.
18
+ # @option options [Hash] :body The body of the request.
19
+ def initialize(options = {})
20
+ @host = options[:host]
21
+ @path = options[:path]
22
+ @body = options[:body]
23
+ @query = options.fetch :query, {}
24
+ end
25
+
26
+ ROUTE_ID = 1630
27
+ @@logged_out = false
28
+
29
+ # Sends the request and returns the body parsed from the JSON response.
30
+ # @return [Hash] the body parsed from the JSON response.
31
+ # @raise [Vng::ConnectionError] if the request fails.
32
+ # @raise [Vng::Error] if parsed body includes errors.
33
+ def run
34
+ case @path
35
+ when '/api/v1/security/session/'
36
+ raise Error.new 'Same franchise ID supplied.'
37
+ when '/api/v1/security/login/'
38
+ if @host == 'invalid-host'
39
+ raise ConnectionError.new 'Failed to open connection'
40
+ else
41
+ { "securityToken"=>"1234567" }
42
+ end
43
+ when '/api/v1/security/logout/'
44
+ if @@logged_out
45
+ raise Error.new 'Session expired. '
46
+ else
47
+ @@logged_out = true
48
+ {}
49
+ end
50
+ when '/api/v1/resources/zips/'
51
+ { "Zips"=>[{ "zip"=>"21765", "zoneName"=>"Brentwood", "state"=>"MD" }] }
52
+ when '/api/v1/resources/franchises/'
53
+ if @body.key?(:objectID)
54
+ { "Franchise"=>{ "objectID"=>"2201007" }, "Fields"=>[
55
+ { "fieldID"=>9, "fieldValue"=>"vng@example.com" },
56
+ ] }
57
+ else
58
+ { "Franchises"=>[
59
+ { "franchiseID"=>106, "franchiseName"=>"Mississauga", "gmtOffsetFranchise"=>-300, "isActive"=>false },
60
+ { "franchiseID"=>107, "franchiseName"=>"Boise", "gmtOffsetFranchise"=>-420, "isActive"=>true },
61
+ ] }
62
+ end
63
+ when '/api/v1/resources/availability/'
64
+ if @body.key?(:zip)
65
+ { "Ids"=>{ "franchiseID"=>"172" } }
66
+ elsif @body[:method] == '2'
67
+ { "Ids"=>{ "lockID"=>"1406328" } }
68
+ else
69
+ { "Availability"=> [
70
+ { "dayID"=>"20281119", "routeID"=>"#{ROUTE_ID}", "startTime"=>"1080" },
71
+ { "dayID"=>"20281119", "routeID"=>"#{ROUTE_ID}", "startTime"=>"1110" },
72
+ ] }
73
+ end
74
+ when '/api/v1/resources/breeds/'
75
+ { "Breeds"=>[{ "breedID"=>2, "breed"=>"Bulldog", "species"=>"Dog", "optionID"=>303, "breedLowWeight"=>30, "breedHighWeight"=>50 }] }
76
+ when '/api/v1/data/Leads/'
77
+ { "Client"=>{ "objectID"=>"916347" }, "Fields"=> [
78
+ { "fieldID"=>126, "fieldValue"=>"Vng Example" },
79
+ { "fieldID"=>238, "fieldValue"=>"vng@example.com" },
80
+ { "fieldID"=>1024, "fieldValue"=>"8648648640" },
81
+ ] }
82
+ when '/api/v1/data/Contacts/'
83
+ { "Contact"=>{ "objectID"=>"2201007" }, "Fields"=>[
84
+ { "fieldID"=>127, "fieldValue"=>"Vng" },
85
+ { "fieldID"=>128, "fieldValue"=>"Example" },
86
+ { "fieldID"=>97, "fieldValue"=>"vng@example.com" },
87
+ { "fieldID"=>96, "fieldValue"=>"8648648640" },
88
+ ] }
89
+ when '/api/v1/data/Locations/'
90
+ { "Location"=>{ "objectID"=>"995681" } }
91
+ when '/api/v1/data/Assets/'
92
+ if @body[:method].eql? '3'
93
+ { "Asset"=>{ "objectID"=>"2201008" } }
94
+ elsif @body[:method].eql? '4'
95
+ {}
96
+ end
97
+ when '/api/v1/data/priceLists/'
98
+ { "PriceItems"=>[
99
+ { "priceItemID"=>275111, "priceItem"=>"15 Step SPA Grooming", "value"=>85.0, "taxID"=>256, "durationPerUnit"=>45.0, "serviceBadge"=>"Required", "serviceCategory"=>"15 Step Spa", "isOnline"=>true, "isActive"=>true },
100
+ { "priceItemID"=>275300, "priceItem"=>"De-Matting - Light", "value"=>10.0, "taxID"=>256, "durationPerUnit"=>15.0, "serviceBadge"=>nil, "serviceCategory"=>"De-Shed", "isOnline"=>true, "isActive"=>true },
101
+ { "priceItemID"=>275301, "priceItem"=>"De-Shedding Treatment", "value"=>20.0, "taxID"=>256, "durationPerUnit"=>15.0, "serviceBadge"=>nil, "serviceCategory"=>"De-Shed", "isOnline"=>true, "isActive"=>false },
102
+ ] }
103
+ when '/api/v1/resources/serviceTypes/'
104
+ if @body.key?(:zip)
105
+ {"ServiceTypes" => [
106
+ {"serviceTypeID" => 14, "serviceType" => "Pet Grooming (name)", "duration" => 45,"isActive" => true},
107
+ {"serviceTypeID" => 16, "serviceType" => "Pet Grooming (name)", "duration" => 45,"isActive" => false},
108
+ ]}
109
+ else
110
+ { "ServiceTypes"=>[
111
+ { "serviceTypeID"=>14, "serviceType"=>"Pet Grooming", "duration"=>90, "isActive"=>true },
112
+ ] }
113
+ end
114
+ when '/api/v1/resources/Routes/'
115
+ {"Routes" => [
116
+ {"routeID" => ROUTE_ID, "routeName" => "Route 1", "isActive" => true},
117
+ {"routeID" => 2, "routeName" => "Inactive", "isActive" => false},
118
+ ]}
119
+ when '/api/v1/data/WorkOrders/'
120
+ { "WorkOrder"=>{ "objectID"=>"4138030" } }
121
+ when '/api/v1/data/Cases/'
122
+ if @body[:method].eql? '3'
123
+ {"Case" => {"objectID" => "28503"}}
124
+ elsif @body[:method].eql? '4'
125
+ {}
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
data/lib/vng/resource.rb CHANGED
@@ -1,42 +1,18 @@
1
- require 'vng/connection_error'
2
- require 'vng/error'
1
+ require ENV['VNG_MOCK'] ? 'vng/mock_request' : 'vng/http_request'
3
2
 
4
3
  module Vng
5
4
  # Provides an abstract class for every Vonigo resource.
6
5
  class Resource
7
6
  private
8
- def self.request(path:, body: {}, query: {}, include_security_token: true)
9
- uri = URI::HTTPS.build host: host, path: path
10
- uri.query = URI.encode_www_form(query) if query.any?
11
-
12
- method = query.any? ? Net::HTTP::Get : Net::HTTP::Post
13
- request = method.new uri.request_uri
14
- request.initialize_http_header 'Content-Type' => 'application/json'
15
-
16
- if query.none?
17
- body = body.merge(securityToken: security_token) if include_security_token
18
- request.body = body.to_json
19
- end
20
7
 
21
- response = instrument do |data|
22
- data[:response] = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
23
- http.request request
24
- end
8
+ def self.request(path:, body: {}, query: {}, include_security_token: true)
9
+ if query.none? && include_security_token
10
+ body = body.merge securityToken: Vng.configuration.security_token
25
11
  end
26
12
 
27
- JSON(response.body).tap do |data|
28
- raise Vng::Error, "#{data['errMsg']} #{data['Errors']}" unless data['errNo'].zero?
13
+ instrument do |data|
14
+ Request.new(host: host, path: path, query: query, body: body).run
29
15
  end
30
- rescue Errno::ECONNREFUSED, SocketError => e
31
- raise Vng::ConnectionError, e.message
32
- end
33
-
34
- def self.host
35
- Vng.configuration.host
36
- end
37
-
38
- def self.security_token
39
- Vng.configuration.security_token
40
16
  end
41
17
 
42
18
  def self.value_for_field(data, field_id)
@@ -44,12 +20,18 @@ module Vng
44
20
  field['fieldValue'] if field
45
21
  end
46
22
 
23
+ # @return [String] the Vonigo API host.
24
+ def self.host
25
+ Vng.configuration.host
26
+ end
27
+
28
+ # Provides instrumentation to ActiveSupport listeners
47
29
  def self.instrument(&block)
48
- data = {class_name: name} # TODO: Add path, query, ...
30
+ data = { class_name: name }
49
31
  if defined?(ActiveSupport::Notifications)
50
32
  ActiveSupport::Notifications.instrument 'Vng.request', data, &block
51
33
  else
52
- block.call(data)
34
+ block.call data
53
35
  end
54
36
  end
55
37
  end
@@ -1,3 +1,4 @@
1
+ require 'digest/md5'
1
2
  require 'vng/resource'
2
3
 
3
4
  module Vng
@@ -32,14 +33,14 @@ module Vng
32
33
  }
33
34
 
34
35
  self.class.request path: '/api/v1/security/session/', body: body, include_security_token: false
35
- rescue Vng::Error => e
36
+ rescue Error => e
36
37
  raise unless e.message.include? 'Same franchise ID supplied'
37
38
  end
38
39
 
39
40
  def destroy
40
41
  query = { securityToken: @token }
41
42
  self.class.request path: '/api/v1/security/logout/', query: query
42
- rescue Vng::Error => e
43
+ rescue Error => e
43
44
  raise unless e.message.include?('Session expired') || e.message.include?('Session does not exist')
44
45
  end
45
46
  end
data/lib/vng/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Vng
2
- VERSION = '1.2.0'
2
+ VERSION = '1.3.0'
3
3
  end
data/lib/vng.rb CHANGED
@@ -1,14 +1,13 @@
1
- require 'date'
2
- require 'digest/md5'
3
- require 'json'
4
- require 'net/http'
1
+ # Used by multiple resources
5
2
  require 'uri'
3
+ require_relative 'vng/error'
4
+ require_relative 'vng/config'
6
5
 
6
+ # Individual resources
7
7
  require_relative 'vng/asset'
8
8
  require_relative 'vng/availability'
9
9
  require_relative 'vng/breed'
10
10
  require_relative 'vng/case'
11
- require_relative 'vng/config'
12
11
  require_relative 'vng/connection_error'
13
12
  require_relative 'vng/contact'
14
13
  require_relative 'vng/franchise'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vng
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - claudiob
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-11-21 00:00:00.000000000 Z
11
+ date: 2024-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: simplecov
@@ -76,10 +76,11 @@ files:
76
76
  - lib/vng/contact.rb
77
77
  - lib/vng/error.rb
78
78
  - lib/vng/franchise.rb
79
+ - lib/vng/http_request.rb
79
80
  - lib/vng/lead.rb
80
81
  - lib/vng/location.rb
81
82
  - lib/vng/lock.rb
82
- - lib/vng/mock_resource.rb
83
+ - lib/vng/mock_request.rb
83
84
  - lib/vng/price_item.rb
84
85
  - lib/vng/resource.rb
85
86
  - lib/vng/route.rb
@@ -1,107 +0,0 @@
1
- require 'vng/connection_error'
2
- require 'vng/error'
3
-
4
- module Vng
5
- # Provides an abstract class for every Vonigo resource.
6
- class Resource
7
- private
8
- def self.request(path:, body: {}, query: {}, include_security_token: true)
9
- if Vng.configuration.mock
10
- mock_request(path:, body:, query:)
11
- else
12
- http_request(path:, body:, query:, include_security_token:)
13
- end
14
- end
15
-
16
- def self.mock_request(path:, body:, query:)
17
- case path
18
- when '/api/v1/security/login/'
19
- { "securityToken"=>"1234567" }
20
- when '/api/v1/resources/zips/'
21
- { "Zips"=>[{ "zip"=>"21765", "zoneName"=>"Brentwood", "state"=>"MD" }] }
22
- when '/api/v1/resources/franchises/'
23
- { "Franchises"=>[
24
- { "franchiseID"=>106, "franchiseName"=>"Mississauga", "gmtOffsetFranchise"=>-300, "isActive"=>false },
25
- { "franchiseID"=>107, "franchiseName"=>"Boise", "gmtOffsetFranchise"=>-420, "isActive"=>true },
26
- ] }
27
- when '/api/v1/resources/availability/'
28
- if body.key?(:zip)
29
- { "Ids"=>{ "franchiseID"=>"172" } }
30
- elsif body[:method] == '2'
31
- { "Ids"=>{ "lockID"=>"1406328" } }
32
- else
33
- { "Availability"=> [
34
- { "dayID"=>"20241119", "routeID"=>"8949", "startTime"=>"1080" },
35
- { "dayID"=>"20241119", "routeID"=>"8949", "startTime"=>"1110" },
36
- ] }
37
- end
38
- when '/api/v1/resources/breeds/'
39
- { "Breeds"=>[{ "breedID"=>2, "breed"=>"Bulldog", "species"=>"Dog", "optionID"=>303, "breedLowWeight"=>30, "breedHighWeight"=>50 }] }
40
- when '/api/v1/data/Leads/'
41
- { "Client"=>{ "objectID"=>"916347" }, "Fields"=> [
42
- { "fieldID"=>126, "fieldValue"=>"Vng Example" },
43
- { "fieldID"=>238, "fieldValue"=>"vng@example.com" },
44
- { "fieldID"=>1024, "fieldValue"=>"8648648640" },
45
- ] }
46
- when '/api/v1/data/Contacts/'
47
- { "Contact"=>{ "objectID"=>"2201007" }, "Fields"=>[
48
- { "fieldID"=>127, "fieldValue"=>"Vng" },
49
- { "fieldID"=>128, "fieldValue"=>"Example" },
50
- { "fieldID"=>97, "fieldValue"=>"vng@example.com" },
51
- { "fieldID"=>96, "fieldValue"=>"8648648640" },
52
- ] }
53
- when '/api/v1/data/Locations/'
54
- { "Location"=>{ "objectID"=>"995681" } }
55
- when '/api/v1/data/Assets/'
56
- { "Asset"=>{ "objectID"=>"2201008" } }
57
- when '/api/v1/data/priceLists/'
58
- { "PriceItems"=>[
59
- { "priceItemID"=>275111, "priceItem"=>"15 Step SPA Grooming", "value"=>85.0, "taxID"=>256, "durationPerUnit"=>45.0, "serviceBadge"=>"Required", "serviceCategory"=>"15 Step Spa", "isOnline"=>true, "isActive"=>true },
60
- { "priceItemID"=>275300, "priceItem"=>"De-Shedding Treatment", "value"=>20.0, "taxID"=>256, "durationPerUnit"=>15.0, "serviceBadge"=>nil, "serviceCategory"=>"De-Shed", "isOnline"=>true, "isActive"=>false },
61
- ] }
62
- when '/api/v1/resources/serviceTypes/'
63
- { "ServiceTypes"=>[
64
- { "serviceTypeID"=>14, "serviceType"=>"Pet Grooming", "duration"=>90, "isActive"=>true },
65
- ] }
66
- when '/api/v1/data/WorkOrders/'
67
- { "WorkOrder"=>{ "objectID"=>"4138030" } }
68
- when '/api/v1/data/Cases/'
69
- { "Case"=>{ "objectID"=>"28460" } }
70
- else
71
- {}
72
- end
73
- end
74
-
75
- def self.http_request(path:, body:, query:, include_security_token: true)
76
- uri = URI::HTTPS.build host: host, path: path
77
- uri.query = URI.encode_www_form(query) if query.any?
78
-
79
- method = query.any? ? Net::HTTP::Get : Net::HTTP::Post
80
- request = method.new uri.request_uri
81
- request.initialize_http_header 'Content-Type' => 'application/json'
82
-
83
- if query.none?
84
- body = body.merge(securityToken: security_token) if include_security_token
85
- request.body = body.to_json
86
- end
87
-
88
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
89
- http.request request
90
- end
91
-
92
- JSON(response.body).tap do |data|
93
- raise Vng::Error, "#{data['errMsg']} #{data['Errors']}" unless data['errNo'].zero?
94
- end
95
- rescue Errno::ECONNREFUSED, SocketError => e
96
- raise Vng::ConnectionError, e.message
97
- end
98
-
99
- def self.host
100
- Vng.configuration.host
101
- end
102
-
103
- def self.security_token
104
- Vng.configuration.security_token
105
- end
106
- end
107
- end