lhc 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +36 -0
  3. data/Gemfile +11 -0
  4. data/README.md +116 -0
  5. data/Rakefile +25 -0
  6. data/docs/configuration.md +57 -0
  7. data/docs/exceptions.md +68 -0
  8. data/docs/interceptors.md +90 -0
  9. data/docs/request.md +24 -0
  10. data/docs/response.md +19 -0
  11. data/lhc.gemspec +30 -0
  12. data/lib/lhc.rb +16 -0
  13. data/lib/lhc/concerns/lhc/basic_methods.rb +42 -0
  14. data/lib/lhc/config.rb +45 -0
  15. data/lib/lhc/endpoint.rb +53 -0
  16. data/lib/lhc/error.rb +63 -0
  17. data/lib/lhc/errors/client_error.rb +73 -0
  18. data/lib/lhc/errors/server_error.rb +28 -0
  19. data/lib/lhc/errors/timeout.rb +4 -0
  20. data/lib/lhc/errors/unknown_error.rb +4 -0
  21. data/lib/lhc/interceptor.rb +9 -0
  22. data/lib/lhc/interceptor_processor.rb +24 -0
  23. data/lib/lhc/request.rb +91 -0
  24. data/lib/lhc/response.rb +52 -0
  25. data/lib/lhc/version.rb +3 -0
  26. data/script/ci/build.sh +19 -0
  27. data/spec/basic_methods/delete_spec.rb +34 -0
  28. data/spec/basic_methods/get_spec.rb +37 -0
  29. data/spec/basic_methods/post_spec.rb +42 -0
  30. data/spec/basic_methods/put_spec.rb +48 -0
  31. data/spec/basic_methods/request_spec.rb +19 -0
  32. data/spec/config/endpoints_spec.rb +49 -0
  33. data/spec/config/placeholders_spec.rb +32 -0
  34. data/spec/dummy/README.rdoc +28 -0
  35. data/spec/dummy/Rakefile +6 -0
  36. data/spec/dummy/app/assets/images/.keep +0 -0
  37. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  38. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  39. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  40. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  41. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  42. data/spec/dummy/app/mailers/.keep +0 -0
  43. data/spec/dummy/app/models/.keep +0 -0
  44. data/spec/dummy/app/models/concerns/.keep +0 -0
  45. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  46. data/spec/dummy/bin/bundle +3 -0
  47. data/spec/dummy/bin/rails +4 -0
  48. data/spec/dummy/bin/rake +4 -0
  49. data/spec/dummy/config.ru +4 -0
  50. data/spec/dummy/config/application.rb +14 -0
  51. data/spec/dummy/config/boot.rb +5 -0
  52. data/spec/dummy/config/environment.rb +5 -0
  53. data/spec/dummy/config/environments/development.rb +34 -0
  54. data/spec/dummy/config/environments/production.rb +75 -0
  55. data/spec/dummy/config/environments/test.rb +39 -0
  56. data/spec/dummy/config/initializers/assets.rb +8 -0
  57. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  58. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  59. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  60. data/spec/dummy/config/initializers/inflections.rb +16 -0
  61. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  62. data/spec/dummy/config/initializers/session_store.rb +3 -0
  63. data/spec/dummy/config/initializers/wrap_parameters.rb +9 -0
  64. data/spec/dummy/config/locales/en.yml +23 -0
  65. data/spec/dummy/config/routes.rb +56 -0
  66. data/spec/dummy/config/secrets.yml +22 -0
  67. data/spec/dummy/lib/assets/.keep +0 -0
  68. data/spec/dummy/log/.keep +0 -0
  69. data/spec/dummy/public/404.html +67 -0
  70. data/spec/dummy/public/422.html +67 -0
  71. data/spec/dummy/public/500.html +66 -0
  72. data/spec/dummy/public/favicon.ico +0 -0
  73. data/spec/endpoint/compile_spec.rb +25 -0
  74. data/spec/endpoint/placeholders_spec.rb +14 -0
  75. data/spec/endpoint/remove_interpolated_params_spec.rb +16 -0
  76. data/spec/error/find_spec.rb +56 -0
  77. data/spec/error/response_spec.rb +17 -0
  78. data/spec/error/timeout_spec.rb +14 -0
  79. data/spec/interceptors/after_request_spec.rb +21 -0
  80. data/spec/interceptors/after_response_spec.rb +42 -0
  81. data/spec/interceptors/before_request_spec.rb +21 -0
  82. data/spec/interceptors/before_response_spec.rb +21 -0
  83. data/spec/interceptors/default_interceptors_spec.rb +15 -0
  84. data/spec/interceptors/define_spec.rb +29 -0
  85. data/spec/interceptors/response_competition_spec.rb +40 -0
  86. data/spec/interceptors/return_response_spec.rb +39 -0
  87. data/spec/rails_helper.rb +4 -0
  88. data/spec/request/error_handling_spec.rb +52 -0
  89. data/spec/request/headers_spec.rb +11 -0
  90. data/spec/request/option_dup_spec.rb +12 -0
  91. data/spec/request/parallel_requests_spec.rb +15 -0
  92. data/spec/request/url_patterns_spec.rb +19 -0
  93. data/spec/response/body_spec.rb +16 -0
  94. data/spec/response/code_spec.rb +16 -0
  95. data/spec/response/data_spec.rb +18 -0
  96. data/spec/response/headers_spec.rb +18 -0
  97. data/spec/response/success_spec.rb +12 -0
  98. data/spec/response/time_spec.rb +16 -0
  99. data/spec/spec_helper.rb +4 -0
  100. data/spec/support/fixtures/json/feedback.json +11 -0
  101. data/spec/support/fixtures/json/feedbacks.json +164 -0
  102. data/spec/support/fixtures/json/localina_content_ad.json +23 -0
  103. data/spec/support/load_json.rb +3 -0
  104. data/spec/support/reset_config.rb +7 -0
  105. data/spec/timeouts/no_signal_spec.rb +13 -0
  106. data/spec/timeouts/timings_spec.rb +59 -0
  107. metadata +313 -0
@@ -0,0 +1,40 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC do
4
+
5
+ context 'interceptor response competition' do
6
+
7
+ before(:each) do
8
+
9
+ class LocalCacheInterceptor < LHC::Interceptor
10
+ @@cached = false
11
+ cattr_accessor :cached
12
+
13
+ def before_request(request)
14
+ if @@cached
15
+ return LHC::Response.new(Typhoeus::Response.new(response_body: 'Im served from local cache'), nil)
16
+ end
17
+ end
18
+ end
19
+
20
+ class RemoteCacheInterceptor < LHC::Interceptor
21
+
22
+ def before_request(request)
23
+ if request.response.nil?
24
+ return LHC::Response.new(Typhoeus::Response.new(response_body: 'Im served from remote cache'), nil)
25
+ end
26
+ end
27
+ end
28
+
29
+ LHC.configure { |c| c.interceptors = [LocalCacheInterceptor, RemoteCacheInterceptor] }
30
+ end
31
+
32
+ it 'can handle multiple interceptors that compete for returning the response' do
33
+ response = LHC.get('http://local.ch')
34
+ expect(response.body).to eq 'Im served from remote cache'
35
+ LocalCacheInterceptor.cached = true
36
+ response = LHC.get('http://local.ch')
37
+ expect(response.body).to eq 'Im served from local cache'
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,39 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC do
4
+
5
+ context 'interceptor' do
6
+
7
+ before(:each) do
8
+ class CacheInterceptor < LHC::Interceptor
9
+
10
+ def before_request(request)
11
+ return LHC::Response.new(Typhoeus::Response.new(response_body: 'Im served from cache'), nil)
12
+ end
13
+ end
14
+ LHC.configure { |c| c.interceptors = [CacheInterceptor] }
15
+ end
16
+
17
+ it 'can return a response rather then doing a real request' do
18
+ response = LHC.get('http://local.ch')
19
+ expect(response.body).to eq 'Im served from cache'
20
+ end
21
+
22
+ context 'misusage' do
23
+
24
+ before(:each) do
25
+ class AnotherInterceptor < LHC::Interceptor
26
+ def before_request(request)
27
+ return LHC::Response.new(Typhoeus::Response.new({}), nil)
28
+ end
29
+ end
30
+ end
31
+
32
+ it 'raises an exception when two interceptors try to return a response' do
33
+ expect(->{
34
+ LHC.get('http://local.ch', interceptors: [CacheInterceptor, AnotherInterceptor])
35
+ }).to raise_error 'Response already set from another interceptor'
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+ require File.expand_path("../dummy/config/environment", __FILE__)
3
+
4
+ ENV["RAILS_ENV"] ||= 'test'
@@ -0,0 +1,52 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC::Request do
4
+
5
+ context 'error handling' do
6
+
7
+ def to_fail_with(error)
8
+ raise_error(error)
9
+ end
10
+
11
+ def expect_status_code(status_code)
12
+ stub_request(:get, "http://something/#{status_code}").to_return(status: status_code)
13
+ expect(
14
+ -> { LHC::Request.new(url: "http://something/#{status_code}") }
15
+ ).to yield
16
+ end
17
+
18
+ it 'raises errors for anything but 2XX response codes' do
19
+ expect_status_code(400) { to_fail_with(LHC::BadRequest) }
20
+ expect_status_code(401) { to_fail_with(LHC::Unauthorized) }
21
+ expect_status_code(402) { to_fail_with(LHC::PaymentRequired) }
22
+ expect_status_code(403) { to_fail_with(LHC::Forbidden) }
23
+ expect_status_code(403) { to_fail_with(LHC::Forbidden) }
24
+ expect_status_code(404) { to_fail_with(LHC::NotFound) }
25
+ expect_status_code(405) { to_fail_with(LHC::MethodNotAllowed) }
26
+ expect_status_code(406) { to_fail_with(LHC::NotAcceptable) }
27
+ expect_status_code(407) { to_fail_with(LHC::ProxyAuthenticationRequired) }
28
+ expect_status_code(408) { to_fail_with(LHC::RequestTimeout) }
29
+ expect_status_code(409) { to_fail_with(LHC::Conflict) }
30
+ expect_status_code(410) { to_fail_with(LHC::Gone) }
31
+ expect_status_code(411) { to_fail_with(LHC::LengthRequired) }
32
+ expect_status_code(412) { to_fail_with(LHC::PreconditionFailed) }
33
+ expect_status_code(413) { to_fail_with(LHC::RequestEntityTooLarge) }
34
+ expect_status_code(414) { to_fail_with(LHC::RequestUriToLong) }
35
+ expect_status_code(415) { to_fail_with(LHC::UnsupportedMediaType) }
36
+ expect_status_code(416) { to_fail_with(LHC::RequestedRangeNotSatisfiable) }
37
+ expect_status_code(417) { to_fail_with(LHC::ExpectationFailed) }
38
+ expect_status_code(422) { to_fail_with(LHC::UnprocessableEntity) }
39
+ expect_status_code(423) { to_fail_with(LHC::Locked) }
40
+ expect_status_code(424) { to_fail_with(LHC::FailedDependency) }
41
+ expect_status_code(426) { to_fail_with(LHC::UpgradeRequired) }
42
+ expect_status_code(500) { to_fail_with(LHC::InternalServerError) }
43
+ expect_status_code(501) { to_fail_with(LHC::NotImplemented) }
44
+ expect_status_code(502) { to_fail_with(LHC::BadGateway) }
45
+ expect_status_code(503) { to_fail_with(LHC::ServiceUnavailable) }
46
+ expect_status_code(504) { to_fail_with(LHC::GatewayTimeout) }
47
+ expect_status_code(505) { to_fail_with(LHC::HttpVersionNotSupported) }
48
+ expect_status_code(507) { to_fail_with(LHC::InsufficientStorage) }
49
+ expect_status_code(510) { to_fail_with(LHC::NotExtended) }
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,11 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC::Request do
4
+
5
+ it 'provides request headers' do
6
+ stub_request(:get, 'http://local.ch')
7
+ response = LHC.get('http://local.ch')
8
+ request = response.request
9
+ expect(request.headers).to eq({"User-Agent"=>"Typhoeus - https://github.com/typhoeus/typhoeus"})
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC::Request do
4
+
5
+ it 'does not alter the options that where passed' do
6
+ LHC.configure { |c| c.endpoint(:kpi_tracker, 'http://analytics.lb-service/track/:entity_id/w', { params: { env: 'PROD' } }) }
7
+ options = { params: { entity_id: '123' } }
8
+ stub_request(:get, "http://analytics.lb-service/track/123/w?env=PROD")
9
+ LHC.get(:kpi_tracker, options)
10
+ expect(options).to eq({ params: { entity_id: '123' } })
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC::Request do
4
+
5
+ it 'does parallel requests if you provide an array of requests' do
6
+ requests = []
7
+ requests << { url: 'http://www.local.ch/restaurants' }
8
+ requests << { url: 'http://www.local.ch' }
9
+ stub_request(:get, "http://www.local.ch/restaurants").to_return(status: 200, body: '1')
10
+ stub_request(:get, "http://www.local.ch").to_return(status: 200, body: '2')
11
+ responses = LHC.request(requests)
12
+ expect(responses[0].body).to eq '1'
13
+ expect(responses[1].body).to eq '2'
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC::Request do
4
+
5
+ it 'compiles url in case of configured endpoints' do
6
+ options = { params: {
7
+ has_reviews: true
8
+ }}
9
+ url = 'http://datastore-stg.lb-service/v2/campaign/:campaign_id/feedbacks'
10
+ LHC.configure { |c| c.endpoint(:feedbacks, url, options) }
11
+ stub_request(:get, 'http://datastore-stg.lb-service/v2/campaign/123/feedbacks?has_reviews=true')
12
+ LHC.get(:feedbacks, params:{campaign_id: 123})
13
+ end
14
+
15
+ it 'compiles url when doing a request' do
16
+ stub_request(:get, 'http://datastore-stg.lb-service:8080/v2/feedbacks/123')
17
+ LHC.get('http://datastore-stg.lb-service:8080/v2/feedbacks/:id', params:{id: 123})
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC::Response do
4
+
5
+ context 'body' do
6
+
7
+ let(:body) { 'this is a body' }
8
+
9
+ let(:raw_response) { OpenStruct.new({ body: body }) }
10
+
11
+ it 'provides response body' do
12
+ response = LHC::Response.new(raw_response, nil)
13
+ expect(response.body).to eq body
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC::Response do
4
+
5
+ context 'code' do
6
+
7
+ let(:code) { 200 }
8
+
9
+ let(:raw_response) { OpenStruct.new({ code: code }) }
10
+
11
+ it 'provides response code' do
12
+ response = LHC::Response.new(raw_response, nil)
13
+ expect(response.code).to eq code
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC::Response do
4
+
5
+ context 'data' do
6
+
7
+ let(:value) { 'some_value' }
8
+
9
+ let(:body) {{ some_key: {nested: value} }}
10
+
11
+ let(:raw_response) { OpenStruct.new({ body: body.to_json }) }
12
+
13
+ it 'makes data from response body available' do
14
+ response = LHC::Response.new(raw_response, nil)
15
+ expect(response.data.some_key.nested).to eq value
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC::Response do
4
+
5
+ context 'headers' do
6
+
7
+ let(:headers) do
8
+ { 'Content-Encoding' => 'UTF-8' }
9
+ end
10
+
11
+ let(:raw_response) { OpenStruct.new({ headers: headers }) }
12
+
13
+ it 'provides headers' do
14
+ response = LHC::Response.new(raw_response, nil)
15
+ expect(response.headers).to eq headers
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC::Response do
4
+
5
+ context 'success?' do
6
+ let(:response_success) { LHC::Response.new(Typhoeus::Response.new(response_code: 200, mock: true), nil) }
7
+ let(:response_error) { LHC::Response.new(Typhoeus::Response.new(response_code: 404, mock: true), nil) }
8
+
9
+ it { expect(response_success.success?).to be_truthy }
10
+ it { expect(response_error.success?).to be_falsy }
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC::Response do
4
+
5
+ context 'time' do
6
+
7
+ let(:time) { 1.3 }
8
+
9
+ let(:raw_response) { OpenStruct.new({time: time}) }
10
+
11
+ it 'provides response time in milliseconds' do
12
+ response = LHC::Response.new(raw_response, nil)
13
+ expect(response.time).to eq time*1000
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,4 @@
1
+ require 'pry'
2
+ require 'webmock/rspec'
3
+
4
+ Dir[File.join(__dir__, "support/**/*.rb")].each {|f| require f}
@@ -0,0 +1,11 @@
1
+ {
2
+ "href": "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/feedbacks/-Sc4_pYNpqfsudzhtivfkA",
3
+ "campaign": {
4
+ "href": "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/content-ads/51dfc5690cf271c375c5a12d"
5
+ },
6
+ "source_id": "aaa",
7
+ "recommended": true,
8
+ "modified": "2014-09-19T14:03:35.599+02:00",
9
+ "created_date": "2014-09-19T14:03:35.597+02:00",
10
+ "comments": []
11
+ }
@@ -0,0 +1,164 @@
1
+ {
2
+ "href" : "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/feedbacks/?exclude_hidden=false&offset=0&limit=10",
3
+ "items" : [ {
4
+ "href" : "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/feedbacks/0sdaetZ-OWVg4oBiBJ-7IQ",
5
+ "campaign" : {
6
+ "href" : "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/content-ads/51dfc5690cf271c375c5a12d"
7
+ },
8
+ "source_id" : "aaa",
9
+ "recommended" : true,
10
+ "ratings" : {
11
+ "ambiente" : 4,
12
+ "service" : 2,
13
+ "food" : 3
14
+ },
15
+ "modified" : "2014-09-18T16:13:32.987+02:00",
16
+ "created_date" : "2014-09-18T16:13:31.496+02:00",
17
+ "average_rating" : 3.0,
18
+ "comments" : [ ]
19
+ }, {
20
+ "href" : "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/feedbacks/QsUOQWNJoB-GFUNsX7z0jg",
21
+ "campaign" : {
22
+ "href" : "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/content-ads/51dfc5690cf271c375c5a11f"
23
+ },
24
+ "source_id" : "abcdefghs12345",
25
+ "name" : "Steve",
26
+ "recommended" : true,
27
+ "ratings" : {
28
+ "ambiente" : 3,
29
+ "service" : 5,
30
+ "food" : 2
31
+ },
32
+ "modified" : "2014-09-18T15:43:12.134+02:00",
33
+ "created_date" : "2014-09-18T15:42:57.892+02:00",
34
+ "review_title" : "GUMMYBEARS GUMMYBEARS GUMMYBEARS",
35
+ "review" : "GUMMYBEARS! ... WOAH, STEVE! No, we both know how you get when you eat gummybears!",
36
+ "average_rating" : 3.3333333333333335,
37
+ "comments" : [ ]
38
+ }, {
39
+ "href" : "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/feedbacks/QynNtmpXlsEGvUJ0ekDKVw",
40
+ "campaign" : {
41
+ "href" : "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/content-ads/51dfc56b0cf271c375c5a14d"
42
+ },
43
+ "source_id" : "abcdefghs12345",
44
+ "name" : "Steve",
45
+ "recommended" : true,
46
+ "ratings" : {
47
+ "ambiente" : 3,
48
+ "service" : 5,
49
+ "food" : 2
50
+ },
51
+ "modified" : "2014-09-17T11:17:39.660+02:00",
52
+ "created_date" : "2014-09-17T11:17:34.234+02:00",
53
+ "review_title" : "GUMMYBEARS GUMMYBEARS GUMMYBEARS",
54
+ "review" : "GUMMYBEARS! ... WOAH, STEVE! No, we both know how you get when you eat gummybears!",
55
+ "average_rating" : 3.3333333333333335,
56
+ "comments" : [ ]
57
+ }, {
58
+ "href" : "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/feedbacks/INmminYWNZwW_qNFx5peJQ",
59
+ "campaign" : {
60
+ "href" : "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/content-ads/51dfc56b0cf271c375c5a153"
61
+ },
62
+ "source_id" : "abcdefghs12345",
63
+ "name" : "Steve",
64
+ "recommended" : true,
65
+ "ratings" : {
66
+ "ambiente" : 3,
67
+ "service" : 5,
68
+ "food" : 2
69
+ },
70
+ "modified" : "2014-09-16T11:20:32.600+02:00",
71
+ "created_date" : "2014-09-16T11:20:30.194+02:00",
72
+ "review_title" : "GUMMYBEARS GUMMYBEARS GUMMYBEARS",
73
+ "review" : "GUMMYBEARS! ... WOAH, STEVE! No, we both know how you get when you eat gummybears!",
74
+ "average_rating" : 3.3333333333333335,
75
+ "comments" : [ ]
76
+ }, {
77
+ "href" : "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/feedbacks/ltgfr0VRYDN2nxyC119wTg",
78
+ "campaign" : {
79
+ "href" : "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/content-ads/51dfc56b0cf271c375c5a14c"
80
+ },
81
+ "source_id" : "aaa",
82
+ "recommended" : false,
83
+ "ratings" : {
84
+ "ambiente" : 2,
85
+ "service" : 1,
86
+ "food" : 1
87
+ },
88
+ "modified" : "2014-09-15T16:23:54.898+02:00",
89
+ "created_date" : "2014-09-15T16:23:40.355+02:00",
90
+ "average_rating" : 1.3333333333333333,
91
+ "comments" : [ ]
92
+ }, {
93
+ "href" : "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/feedbacks/5dUdQP-kZ6sulN8NtpGXTw",
94
+ "campaign" : {
95
+ "href" : "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/content-ads/51dfc56b0cf271c375c5a14c"
96
+ },
97
+ "source_id" : "abcdefghs12345",
98
+ "name" : "Steve",
99
+ "recommended" : true,
100
+ "ratings" : {
101
+ "ambiente" : 3,
102
+ "service" : 5,
103
+ "food" : 2
104
+ },
105
+ "modified" : "2014-09-12T13:10:51.220+02:00",
106
+ "created_date" : "2014-09-12T13:10:48.813+02:00",
107
+ "review_title" : "GUMMYBEARS GUMMYBEARS GUMMYBEARS",
108
+ "review" : "GUMMYBEARS! ... WOAH, STEVE! No, we both know how you get when you eat gummybears!",
109
+ "average_rating" : 3.3333333333333335,
110
+ "comments" : [ ]
111
+ }, {
112
+ "href" : "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/feedbacks/Z3KfWzIEQ3ZVCUj2IdrSNQ",
113
+ "campaign" : {
114
+ "href" : "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/content-ads/51dfc5690cf271c375c5a12e"
115
+ },
116
+ "source_id" : "abcdefghs",
117
+ "recommended" : true,
118
+ "modified" : "2014-09-10T16:57:36.255+02:00",
119
+ "created_date" : "2014-09-10T16:57:36.254+02:00",
120
+ "comments" : [ ]
121
+ }, {
122
+ "href" : "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/feedbacks/ZUUUeiw-Stw5Zb1baHDUzQ",
123
+ "campaign" : {
124
+ "href" : "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/content-ads/51dfc5690cf271c375c5a12d"
125
+ },
126
+ "source_id" : "abcdefghs",
127
+ "recommended" : true,
128
+ "modified" : "2014-09-10T16:57:32.792+02:00",
129
+ "created_date" : "2014-09-10T16:57:32.791+02:00",
130
+ "comments" : [ ]
131
+ }, {
132
+ "href" : "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/feedbacks/GyeWvhEtU4cYN_5T2FX2UA",
133
+ "campaign" : {
134
+ "href" : "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/content-ads/539266ec0cf2cd754583cfa0"
135
+ },
136
+ "source_id" : "abcdefghs",
137
+ "name" : "aa",
138
+ "recommended" : true,
139
+ "ratings" : {
140
+ "ambiente" : 2,
141
+ "service" : 4,
142
+ "food" : 3
143
+ },
144
+ "modified" : "2014-09-11T09:48:19.096+02:00",
145
+ "created_date" : "2014-09-10T16:35:39.201+02:00",
146
+ "review_title" : "bbb",
147
+ "review" : "fff",
148
+ "average_rating" : 3.0,
149
+ "comments" : [ ]
150
+ }, {
151
+ "href" : "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/feedbacks/o-qTRqQGFS3Z_RPJm1f8SA",
152
+ "campaign" : {
153
+ "href" : "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/content-ads/51dfc56c0cf271c375c5a160"
154
+ },
155
+ "source_id" : "abcdefghs12345",
156
+ "recommended" : true,
157
+ "modified" : "2014-09-10T16:31:52.493+02:00",
158
+ "created_date" : "2014-09-10T16:31:52.492+02:00",
159
+ "comments" : [ ]
160
+ } ],
161
+ "total" : 98,
162
+ "offset" : 0,
163
+ "limit" : 10
164
+ }