d2l-valence 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +22 -0
  3. data/.gitignore +17 -0
  4. data/.rubocop.yml +13 -0
  5. data/Gemfile +4 -0
  6. data/Gemfile.lock +71 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +266 -0
  9. data/Rakefile +6 -0
  10. data/d2l-valence.gemspec +30 -0
  11. data/lib/d2l/valence.rb +15 -0
  12. data/lib/d2l/valence/app_context.rb +49 -0
  13. data/lib/d2l/valence/auth_tokens.rb +60 -0
  14. data/lib/d2l/valence/encrypt.rb +34 -0
  15. data/lib/d2l/valence/host.rb +43 -0
  16. data/lib/d2l/valence/request.rb +104 -0
  17. data/lib/d2l/valence/response.rb +66 -0
  18. data/lib/d2l/valence/timestamp_error.rb +42 -0
  19. data/lib/d2l/valence/user_context.rb +58 -0
  20. data/lib/d2l/valence/version.rb +5 -0
  21. data/spec/d2l/valence/app_context_spec.rb +14 -0
  22. data/spec/d2l/valence/auth_tokens_spec.rb +30 -0
  23. data/spec/d2l/valence/host_spec.rb +64 -0
  24. data/spec/d2l/valence/request/authenticated_uri_spec.rb +75 -0
  25. data/spec/d2l/valence/request/execute/invalid_time_stamp_spec.rb +40 -0
  26. data/spec/d2l/valence/request/execute/lti_links/create_spec.rb +66 -0
  27. data/spec/d2l/valence/request/execute/lti_links/delete_spec.rb +39 -0
  28. data/spec/d2l/valence/request/execute/lti_links/list_spec.rb +41 -0
  29. data/spec/d2l/valence/request/execute/lti_links/update_spec.rb +73 -0
  30. data/spec/d2l/valence/request/execute/lti_links/view_spec.rb +41 -0
  31. data/spec/d2l/valence/request/execute/version_spec.rb +41 -0
  32. data/spec/d2l/valence/request/execute/whoami_spec.rb +40 -0
  33. data/spec/d2l/valence/response/code_spec.rb +34 -0
  34. data/spec/d2l/valence/response/server_skew_spec.rb +33 -0
  35. data/spec/d2l/valence/timestamp_error_spec.rb +21 -0
  36. data/spec/d2l/valence/user_context_spec.rb +6 -0
  37. data/spec/fixtures/vcr_cassettes/request/execute/create_lti_link.yml +71 -0
  38. data/spec/fixtures/vcr_cassettes/request/execute/delete_lti_link.yml +48 -0
  39. data/spec/fixtures/vcr_cassettes/request/execute/get_a_lti_link.yml +66 -0
  40. data/spec/fixtures/vcr_cassettes/request/execute/get_lti_links.yml +70 -0
  41. data/spec/fixtures/vcr_cassettes/request/execute/get_version.yml +66 -0
  42. data/spec/fixtures/vcr_cassettes/request/execute/get_whoami.yml +61 -0
  43. data/spec/fixtures/vcr_cassettes/request/execute/invalid_timestamp.yml +112 -0
  44. data/spec/fixtures/vcr_cassettes/request/execute/put_lti_link.yml +139 -0
  45. data/spec/spec_helper.rb +20 -0
  46. data/spec/support/common_context.rb +37 -0
  47. metadata +228 -0
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe D2L::Valence::Request, type: :service do
4
+ include_context :common_context
5
+
6
+ subject do
7
+ described_class.new(
8
+ user_context: user_context,
9
+ http_method: http_method,
10
+ route: route,
11
+ route_params: route_params,
12
+ query_params: query_params
13
+ )
14
+ end
15
+
16
+ context '.execute' do
17
+ let(:user_id) { ENV['D2L_USER_ID'] }
18
+ let(:user_key) { ENV['D2L_USER_KEY'] }
19
+
20
+ context 'for GET a lti link', vcr: {cassette_name: 'request/execute/get_a_lti_link'} do
21
+ let(:http_method) { 'GET' }
22
+ let(:route) { '/d2l/api/le/:version/lti/link/:orgUnitId/:ltiLinkId' }
23
+ let(:route_params) { {orgUnitId: 8041, ltiLinkId: 12335} }
24
+ let(:query_params) { {} }
25
+ let(:api_version) { '1.15' }
26
+ let(:response) { subject.execute }
27
+
28
+ before do
29
+ Timecop.freeze Time.at(1491961181)
30
+ end
31
+
32
+ after { Timecop.return }
33
+
34
+ it 'will return the specified lti link for the associated unit' do
35
+ expect(response.code).to eq :HTTP_200
36
+ expect(response.to_hash['LtiLinkId']).to eq route_params[:ltiLinkId]
37
+ expect(response.to_hash['OrgUnitId']).to eq route_params[:orgUnitId]
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe D2L::Valence::Request, type: :service do
4
+ include_context :common_context
5
+
6
+ subject do
7
+ described_class.new(
8
+ user_context: user_context,
9
+ http_method: http_method,
10
+ route: route,
11
+ route_params: route_params,
12
+ query_params: query_params
13
+ )
14
+ end
15
+
16
+ context '.execute' do
17
+ let(:user_id) { ENV['D2L_USER_ID'] }
18
+ let(:user_key) { ENV['D2L_USER_KEY'] }
19
+
20
+ context 'for GET version', vcr: {cassette_name: 'request/execute/get_version'} do
21
+ let(:http_method) { 'GET' }
22
+ let(:route) { '/d2l/api/versions/' }
23
+ let(:route_params) { {} }
24
+ let(:query_params) { {} }
25
+ let(:api_version) { '1.15' }
26
+ let(:response) { subject.execute }
27
+
28
+ before do
29
+ Timecop.freeze Time.at(1491960243)
30
+ end
31
+
32
+ after { Timecop.return }
33
+
34
+ its(:execute) { is_expected.to be_a D2L::Valence::Response }
35
+ it 'will return the version information' do
36
+ response = subject.execute
37
+ expect(response.code).to eq :HTTP_200
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe D2L::Valence::Request, type: :service do
4
+ include_context :common_context
5
+
6
+ subject do
7
+ described_class.new(
8
+ user_context: user_context,
9
+ http_method: http_method,
10
+ route: route,
11
+ route_params: route_params,
12
+ query_params: query_params
13
+ )
14
+ end
15
+
16
+ context '.execute' do
17
+ let(:user_id) { ENV['D2L_USER_ID'] }
18
+ let(:user_key) { ENV['D2L_USER_KEY'] }
19
+
20
+ context 'for whoami', vcr: {cassette_name: 'request/execute/get_whoami'} do
21
+ let(:http_method) { 'GET' }
22
+ let(:route) { '/d2l/api/lp/:version/users/whoami' }
23
+ let(:route_params) { {} }
24
+ let(:query_params) { {} }
25
+ let(:response) { subject.execute }
26
+
27
+ before do
28
+ Timecop.freeze Time.at(1491960098)
29
+ end
30
+
31
+ after { Timecop.return }
32
+
33
+ its(:execute) { is_expected.to be_a D2L::Valence::Response }
34
+ it 'will return the version information' do
35
+ expect(response.to_hash['ProfileIdentifier']).to_not be_nil
36
+ expect(response.code).to eq :HTTP_200
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe D2L::Valence::Response, type: :service do
4
+ Struct.new('DummyHttpResponse', :code, :body)
5
+
6
+ context '.code' do
7
+ subject { described_class.new(http_response) }
8
+ let(:http_response) { Struct::DummyHttpResponse.new(code, body) }
9
+
10
+ context 'with bad timestamp' do
11
+ let(:code) { 403 }
12
+ let(:server_time_in_seconds) { (Time.now.to_f).to_i + time_skew }
13
+ let(:time_skew) { 60 * 60 }
14
+ let(:body) { "Timestamp out of range #{server_time_in_seconds}" }
15
+
16
+ its(:code) { is_expected.to eq :INVALID_TIMESTAMP }
17
+ its(:server_skew) { is_expected.to_not eq 0 }
18
+ end
19
+
20
+ context 'with invalid token' do
21
+ let(:code) { 403 }
22
+ let(:body) { 'invalid token'}
23
+
24
+ its(:code) { is_expected.to eq :INVALID_TOKEN }
25
+ end
26
+
27
+ context 'with a successful request' do
28
+ let(:code) { 200 }
29
+ let(:body) { 'success'}
30
+
31
+ its(:code) { is_expected.to eq :HTTP_200 }
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe D2L::Valence::Response, type: :service do
4
+ Struct.new('DummyHttpResponse', :code, :body)
5
+
6
+ context '.server_skew' do
7
+ subject { described_class.new(http_response) }
8
+ let(:http_response) { Struct::DummyHttpResponse.new(code, body) }
9
+
10
+ context 'with bad timestamp' do
11
+ let(:code) { 403 }
12
+ let(:server_time_in_seconds) { (Time.now.to_f).to_i + time_skew }
13
+ let(:time_skew) { 60 * 60 }
14
+ let(:body) { "Timestamp out of range #{server_time_in_seconds}" }
15
+
16
+ its(:server_skew) { is_expected.to_not eq 0 }
17
+ end
18
+
19
+ context 'with invalid token' do
20
+ let(:code) { 403 }
21
+ let(:body) { 'invalid token'}
22
+
23
+ its(:server_skew) { is_expected.to eq 0 }
24
+ end
25
+
26
+ context 'with a successful request' do
27
+ let(:code) { 200 }
28
+ let(:body) { 'success'}
29
+
30
+ its(:server_skew) { is_expected.to eq 0 }
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe D2L::Valence::TimestampError do
4
+ subject { described_class.new(error_message) }
5
+
6
+ context 'when there is an error message' do
7
+ let(:server_time_in_seconds) { (Time.now.to_f).to_i + time_skew }
8
+ let(:time_skew) { 60 * 60 }
9
+ let(:error_message) { "Timestamp out of range #{server_time_in_seconds}" }
10
+
11
+ its(:timestamp_out_of_range?) { is_expected.to be_truthy }
12
+ its(:server_skew) { is_expected.to_not eq 0 }
13
+ end
14
+
15
+ context 'when there is no error message' do
16
+ let(:error_message) { 'This is not a timestamp error message' }
17
+
18
+ its(:timestamp_out_of_range?) { is_expected.to be_falsey }
19
+ its(:server_skew) { is_expected.to eq 0 }
20
+ end
21
+ end
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+
3
+ describe D2L::Valence::UserContext, type: :service do
4
+ include_context :common_context
5
+
6
+ end
@@ -0,0 +1,71 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://partners.brightspace.com/d2l/api/le/1.15/lti/link/8041?x_a=api_id&x_b=user_id&x_c=sKj4auxOs9ytAueL8bo8_Efju72WweaW95sUJnamHsw&x_d=6N_bgR4f91ZOFhejxEYESy1oexgtChOxFsGiIRcNUaQ&x_t=1491960645
6
+ body:
7
+ encoding: UTF-8
8
+ string: '{"Title":"LTI Link","Url":"http://myapplication.com/tool/launch","Description":"Link
9
+ for external tool","Key":"2015141297208","PlainSecret":"a30be7c3550149b7a7daac3065f0e5e5","IsVisible":false,"SignMessage":true,"SignWithTc":true,"SendTcInfo":true,"SendContextInfo":true,"SendUserId":true,"SendUserName":true,"SendUserEmail":true,"SendLinkTitle":true,"SendLinkDescription":true,"SendD2LUserName":true,"SendD2LOrgDefinedId":true,"SendD2LOrgRoleId":true,"UseToolProviderSecuritySettings":false,"CustomParameters":null}'
10
+ headers:
11
+ Accept:
12
+ - "*/*"
13
+ Accept-Encoding:
14
+ - gzip, deflate
15
+ User-Agent:
16
+ - rest-client/2.0.1 (darwin16.1.0 x86_64) ruby/2.3.3p222
17
+ Content-Type:
18
+ - application/json
19
+ Content-Length:
20
+ - '516'
21
+ Host:
22
+ - partners.brightspace.com
23
+ response:
24
+ status:
25
+ code: 200
26
+ message: OK
27
+ headers:
28
+ Cache-Control:
29
+ - no-cache, no-store
30
+ Pragma:
31
+ - no-cache
32
+ Content-Type:
33
+ - application/json; charset=UTF-8
34
+ Content-Encoding:
35
+ - gzip
36
+ Expires:
37
+ - "-1"
38
+ Vary:
39
+ - Accept-Encoding
40
+ Server:
41
+ - Microsoft-IIS/7.5
42
+ Access-Control-Allow-Origin:
43
+ - "*"
44
+ Access-Control-Allow-Credentials:
45
+ - 'false'
46
+ Access-Control-Expose-Headers:
47
+ - Content-Disposition,Content-Length,Content-Type,Accept-Ranges,Content-Range,Date
48
+ X-Powered-By:
49
+ - ASP.NET
50
+ X-Xss-Protection:
51
+ - '0'
52
+ Date:
53
+ - Wed, 12 Apr 2017 01:30:46 GMT
54
+ Content-Length:
55
+ - '410'
56
+ body:
57
+ encoding: ASCII-8BIT
58
+ string: !binary |-
59
+ H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvVK1+B0oQiAYBMk2JBAEOzBiM3m
60
+ kuwdaUcjKasqgcplVmVdZhZAzO2dvPfee++999577733ujudTif33/8/XGZk
61
+ AWz2zkrayZ4hgKrIHz9+fB8/In7xR181+ZuqKl/W1WUxy+vX+XRdF+3167xt
62
+ i+VF89Gj86xs8tFHz9viebF8ezb76NHu/v7De7ujj76sL75aFi0+OtjZpw/e
63
+ FG2Zf/Too+dvzlI0/mj00Vd1SR/M23b16O7dxXW2WpXFNGuLajmeVou7LXV9
64
+ t8zWy+mcGj/Nm2ldrPAtvQQI6XlVp/m7Nq+XWZmiNTX7vfJr+npvZ/f+7v7u
65
+ 3sMHezsH9OlZ85NFU0yAgKL8urhYfpE3TXZBn7X1Wj/6btHO30ztJ/ly9mZ6
66
+ tjyv/E9OqmVL3XY/JmLVGG74yYts4TrQz04XWUEjdx9iNEqf8MNg0O6rp3vP
67
+ AacLmz4msj/Nz4tlPgtRka9eVWXuPj9ZN221eJnVBIaISNP5ve//kv8HjSKB
68
+ i/UBAAA=
69
+ http_version:
70
+ recorded_at: Wed, 12 Apr 2017 01:30:46 GMT
71
+ recorded_with: VCR 3.0.3
@@ -0,0 +1,48 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: delete
5
+ uri: https://partners.brightspace.com/d2l/api/le/1.15/lti/link/144931?x_a=api_id&x_b=user_id&x_c=U_8slZfjQ2jg9KcIskFn67j1TR-KS4n2WE4shz6ZG5M&x_d=zrApqElhuD12RmYSi72DMyJ5rfUH1kVIgV_lWuJUw5I&x_t=1491960880
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - "*/*"
12
+ Accept-Encoding:
13
+ - gzip, deflate
14
+ User-Agent:
15
+ - rest-client/2.0.1 (darwin16.1.0 x86_64) ruby/2.3.3p222
16
+ Content-Type:
17
+ - application/json
18
+ Host:
19
+ - partners.brightspace.com
20
+ response:
21
+ status:
22
+ code: 200
23
+ message: OK
24
+ headers:
25
+ Cache-Control:
26
+ - private
27
+ Content-Length:
28
+ - '0'
29
+ Server:
30
+ - Microsoft-IIS/7.5
31
+ Access-Control-Allow-Origin:
32
+ - "*"
33
+ Access-Control-Allow-Credentials:
34
+ - 'false'
35
+ Access-Control-Expose-Headers:
36
+ - Content-Disposition,Content-Length,Content-Type,Accept-Ranges,Content-Range,Date
37
+ X-Powered-By:
38
+ - ASP.NET
39
+ X-Xss-Protection:
40
+ - '0'
41
+ Date:
42
+ - Wed, 12 Apr 2017 01:34:40 GMT
43
+ body:
44
+ encoding: UTF-8
45
+ string: ''
46
+ http_version:
47
+ recorded_at: Wed, 12 Apr 2017 01:34:41 GMT
48
+ recorded_with: VCR 3.0.3
@@ -0,0 +1,66 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://partners.brightspace.com/d2l/api/le/1.15/lti/link/8041/12335?x_a=api_id&x_b=user_id&x_c=hGIVnIiIpVdkKK2y2jtK-afH5hQoRPYnjstjCBrs67A&x_d=eEpvKLjj8rlktq0YRjYoicTa2zlW6wxkXL_GfWmN5Us&x_t=1491961181
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - "*/*"
12
+ Accept-Encoding:
13
+ - gzip, deflate
14
+ User-Agent:
15
+ - rest-client/2.0.1 (darwin16.1.0 x86_64) ruby/2.3.3p222
16
+ Host:
17
+ - partners.brightspace.com
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Cache-Control:
24
+ - no-cache, no-store
25
+ Pragma:
26
+ - no-cache
27
+ Content-Type:
28
+ - application/json; charset=UTF-8
29
+ Content-Encoding:
30
+ - gzip
31
+ Expires:
32
+ - "-1"
33
+ Vary:
34
+ - Accept-Encoding
35
+ Server:
36
+ - Microsoft-IIS/7.5
37
+ Access-Control-Allow-Origin:
38
+ - "*"
39
+ Access-Control-Allow-Credentials:
40
+ - 'false'
41
+ Access-Control-Expose-Headers:
42
+ - Content-Disposition,Content-Length,Content-Type,Accept-Ranges,Content-Range,Date
43
+ X-Powered-By:
44
+ - ASP.NET
45
+ X-Xss-Protection:
46
+ - '0'
47
+ Date:
48
+ - Wed, 12 Apr 2017 01:39:42 GMT
49
+ Content-Length:
50
+ - '420'
51
+ body:
52
+ encoding: ASCII-8BIT
53
+ string: !binary |-
54
+ H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvVK1+B0oQiAYBMk2JBAEOzBiM3m
55
+ kuwdaUcjKasqgcplVmVdZhZAzO2dvPfee++999577733ujudTif33/8/XGZk
56
+ AWz2zkrayZ4hgKrIHz9+fB8/In7xR181+ZuqKl/W1WUxy+vX+XRdF+3167xt
57
+ i+VF89Gj86xs8tFHz9viebF8ezb76NHu3r1790cffVlffLUsWnxysLO/O/ro
58
+ TdGW+UePPspf5U1eX+bpqzybMZDRR1/VJX0zb9tV8+ju3Xw9zmtpNJ5Wi3G2
59
+ vputVneLZZtf1FlbVMu7ZVv8/i0hdrfM1svpnEA8zZtpXazwLYGiD36v/Jp+
60
+ 2dvZvb+7v7v38MHe7kP69Kz5yaIpJsCkrdeE+eviYvlF3jTZRfDRd4t2/mZq
61
+ x/c6X87eTM+W55VtRJ+cVITSu7b7MRGtxrjDT15kC9eDfna6yAoaufsQRFRC
62
+ hR8Gw3NfPd17Djhd2PQx0f9pfl4s81mIinz1qipz9/nJummrxcusJjBtXtO0
63
+ fu/7v+T/Acj3k0P9AQAA
64
+ http_version:
65
+ recorded_at: Wed, 12 Apr 2017 01:39:42 GMT
66
+ recorded_with: VCR 3.0.3
@@ -0,0 +1,70 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://partners.brightspace.com/d2l/api/le/1.15/lti/link/8041/?x_a=api_id&x_b=user_id&x_c=DjRNAX2xPjotbQb6qN7YfsvNj2CWVteuzytONhagySo&x_d=6eMmv4xCSEhh516zXMM8ulZKgi6T1ph3Okfmcg2DJRg&x_t=1491960964
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - "*/*"
12
+ Accept-Encoding:
13
+ - gzip, deflate
14
+ User-Agent:
15
+ - rest-client/2.0.1 (darwin16.1.0 x86_64) ruby/2.3.3p222
16
+ Host:
17
+ - partners.brightspace.com
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Cache-Control:
24
+ - no-cache, no-store
25
+ Pragma:
26
+ - no-cache
27
+ Content-Type:
28
+ - application/json; charset=UTF-8
29
+ Content-Encoding:
30
+ - gzip
31
+ Expires:
32
+ - "-1"
33
+ Vary:
34
+ - Accept-Encoding
35
+ Server:
36
+ - Microsoft-IIS/7.5
37
+ Access-Control-Allow-Origin:
38
+ - "*"
39
+ Access-Control-Allow-Credentials:
40
+ - 'false'
41
+ Access-Control-Expose-Headers:
42
+ - Content-Disposition,Content-Length,Content-Type,Accept-Ranges,Content-Range,Date
43
+ X-Powered-By:
44
+ - ASP.NET
45
+ X-Xss-Protection:
46
+ - '0'
47
+ Date:
48
+ - Wed, 12 Apr 2017 01:36:05 GMT
49
+ Content-Length:
50
+ - '612'
51
+ body:
52
+ encoding: ASCII-8BIT
53
+ string: !binary |-
54
+ H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvVK1+B0oQiAYBMk2JBAEOzBiM3m
55
+ kuwdaUcjKasqgcplVmVdZhZAzO2dvPfee++999577733ujudTif33/8/XGZk
56
+ AWz2zkrayZ4hgKrIHz9+fB8/Ir73iz/6qsnfVFX5sq4ui1lev86n67por1/n
57
+ bVssL5qPHp1nZZOPPnreFs+L5duz2UePdvfu3bs/+ujL+uKrZdHik4Od/d3R
58
+ R2+Ktsw/evRR/ipv8voyT1/l2YyBjD76qi7pm3nbrppHd+/m63FeS6PxtFqM
59
+ s/XdbLW6Wyzb/KLO2qJa3i3b4vdvCbG7ZbZeTucE4mneTOtihW8JFH3we+XX
60
+ 9Mvezu793f3dvYcP9nYf0qdnzU8WTTEBJm29JsxfFxfLL/KmyS6Cj75btPM3
61
+ Uzu+1/ly9mZ6tjyvbCP65KQilN613Y+JaDXGHX7yIlu4HvSz00VW0MjdhyCi
62
+ Eir8MBie++rp3nPA6cKmj4n+T/PzYpnPQlTkq1dVmbvPT9ZNWy1eZjWBafOa
63
+ pvV73/8lo683+/v7uw9otqmP+PTT7Ffreprjhdd5mU8xpDd509LkODYgLphW
64
+ de74oMyWUSag7xnc718SvCFueLw6Qg+pfJ1W58R78loKNNLnb870u7xOt8pq
65
+ mpV3Ht9dHRGgn39c5OFKn9M8emzU++5nk4/2Dh7cko9+ssivMME0Mz/rLERt
66
+ 0vOqTi+pT0IezJSF7DRKV1nT4LvOF+nZ0x9xFX9Os/pBXPWLPxKoHwVz9/sX
67
+ M6LiT2blGl/tfvRLvv9Lvv//ADDINGzEBgAA
68
+ http_version:
69
+ recorded_at: Wed, 12 Apr 2017 01:36:06 GMT
70
+ recorded_with: VCR 3.0.3