appnexusapi 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +71 -39
- data/appnexusapi.gemspec +1 -2
- data/lib/appnexusapi.rb +21 -10
- data/lib/appnexusapi/configuration.rb +12 -0
- data/lib/appnexusapi/connection.rb +83 -90
- data/lib/appnexusapi/error.rb +3 -0
- data/lib/appnexusapi/faraday/raise_http_error.rb +15 -1
- data/lib/appnexusapi/read_only_service.rb +8 -0
- data/lib/appnexusapi/resource.rb +19 -15
- data/lib/appnexusapi/service.rb +35 -48
- data/lib/appnexusapi/services/ad_server_service.rb +9 -0
- data/lib/appnexusapi/{advertiser_service.rb → services/advertiser_service.rb} +0 -0
- data/lib/appnexusapi/{bidder_instance_service.rb → services/bidder_instance_service.rb} +0 -6
- data/lib/appnexusapi/{bidder_profile_service.rb → services/bidder_profile_service.rb} +0 -6
- data/lib/appnexusapi/{bidder_service.rb → services/bidder_service.rb} +0 -0
- data/lib/appnexusapi/services/brand_service.rb +2 -0
- data/lib/appnexusapi/services/browser_service.rb +2 -0
- data/lib/appnexusapi/{campaign_service.rb → services/campaign_service.rb} +0 -0
- data/lib/appnexusapi/services/category_service.rb +5 -0
- data/lib/appnexusapi/{content_category_service.rb → services/content_category_service.rb} +0 -1
- data/lib/appnexusapi/{creative_service.rb → services/creative_service.rb} +0 -0
- data/lib/appnexusapi/{creative_template_service.rb → services/creative_template_service.rb} +1 -6
- data/lib/appnexusapi/services/device_model_service.rb +2 -0
- data/lib/appnexusapi/{domain_list_service.rb → services/domain_list_service.rb} +0 -0
- data/lib/appnexusapi/services/inventory_attribute_service.rb +2 -0
- data/lib/appnexusapi/{inventory_source_service.rb → services/inventory_source_service.rb} +0 -0
- data/lib/appnexusapi/services/language_service.rb +2 -0
- data/lib/appnexusapi/{line_item_service.rb → services/line_item_service.rb} +0 -0
- data/lib/appnexusapi/services/log_level_data_download_service.rb +13 -0
- data/lib/appnexusapi/services/log_level_data_service.rb +105 -0
- data/lib/appnexusapi/services/media_type_service.rb +2 -0
- data/lib/appnexusapi/{member_service.rb → services/member_service.rb} +0 -0
- data/lib/appnexusapi/{object_limit_service.rb → services/object_limit_service.rb} +0 -0
- data/lib/appnexusapi/{operating_system_extended_service.rb → services/operating_system_extended_service.rb} +1 -6
- data/lib/appnexusapi/services/operating_system_service.rb +2 -0
- data/lib/appnexusapi/{payment_rule_service.rb → services/payment_rule_service.rb} +0 -0
- data/lib/appnexusapi/{placement_service.rb → services/placement_service.rb} +0 -0
- data/lib/appnexusapi/services/platform_member_service.rb +2 -0
- data/lib/appnexusapi/{profile_service.rb → services/profile_service.rb} +0 -0
- data/lib/appnexusapi/{publisher_service.rb → services/publisher_service.rb} +0 -0
- data/lib/appnexusapi/{segment_service.rb → services/segment_service.rb} +0 -2
- data/lib/appnexusapi/{site_service.rb → services/site_service.rb} +0 -0
- data/lib/appnexusapi/services/technical_attribute_service.rb +2 -0
- data/lib/appnexusapi/{tiny_tag_service.rb → services/tiny_tag_service.rb} +0 -6
- data/lib/appnexusapi/{user_service.rb → services/user_service.rb} +0 -0
- data/lib/appnexusapi/version.rb +1 -1
- data/spec/connection_spec.rb +46 -10
- data/spec/fixtures/vcr/content_category_crud.yml +188 -69
- data/spec/fixtures/vcr/log_level_data_service_download.yml +213 -0
- data/spec/integration/content_category_spec.rb +4 -0
- data/spec/{creative_service_spec.rb → integration/creative_service_spec.rb} +0 -0
- data/spec/integration/log_level_data_service_spec.rb +13 -0
- data/spec/{object_limit_service_spec.rb → integration/object_limit_service_spec.rb} +0 -0
- data/spec/integration/placement_spec.rb +0 -1
- data/spec/spec_helper.rb +2 -3
- metadata +52 -94
- data/lib/appnexusapi/ad_server_resource.rb +0 -2
- data/lib/appnexusapi/ad_server_service.rb +0 -20
- data/lib/appnexusapi/advertiser_resource.rb +0 -2
- data/lib/appnexusapi/bidder_instance_resource.rb +0 -2
- data/lib/appnexusapi/bidder_profile_resource.rb +0 -2
- data/lib/appnexusapi/bidder_resource.rb +0 -2
- data/lib/appnexusapi/brand_resource.rb +0 -2
- data/lib/appnexusapi/brand_service.rb +0 -8
- data/lib/appnexusapi/browser_resource.rb +0 -2
- data/lib/appnexusapi/browser_service.rb +0 -8
- data/lib/appnexusapi/campaign_resource.rb +0 -2
- data/lib/appnexusapi/category_resource.rb +0 -2
- data/lib/appnexusapi/category_service.rb +0 -12
- data/lib/appnexusapi/content_category_resource.rb +0 -2
- data/lib/appnexusapi/creative_resource.rb +0 -2
- data/lib/appnexusapi/creative_template_resource.rb +0 -2
- data/lib/appnexusapi/device_model_resource.rb +0 -2
- data/lib/appnexusapi/device_model_service.rb +0 -6
- data/lib/appnexusapi/domain_list_resource.rb +0 -2
- data/lib/appnexusapi/inventory_attribute_resource.rb +0 -2
- data/lib/appnexusapi/inventory_attribute_service.rb +0 -8
- data/lib/appnexusapi/inventory_source_resource.rb +0 -2
- data/lib/appnexusapi/language_resource.rb +0 -2
- data/lib/appnexusapi/language_service.rb +0 -8
- data/lib/appnexusapi/line_item_resource.rb +0 -2
- data/lib/appnexusapi/log_level_data_download_service.rb +0 -68
- data/lib/appnexusapi/log_level_data_resource.rb +0 -19
- data/lib/appnexusapi/log_level_data_service.rb +0 -26
- data/lib/appnexusapi/media_type_resource.rb +0 -2
- data/lib/appnexusapi/media_type_service.rb +0 -8
- data/lib/appnexusapi/member_resource.rb +0 -2
- data/lib/appnexusapi/object_limit_resource.rb +0 -2
- data/lib/appnexusapi/operating_system_extended_resource.rb +0 -2
- data/lib/appnexusapi/operating_system_resource.rb +0 -2
- data/lib/appnexusapi/operating_system_service.rb +0 -8
- data/lib/appnexusapi/payment_rule_resource.rb +0 -2
- data/lib/appnexusapi/placement_resource.rb +0 -2
- data/lib/appnexusapi/platform_member_resource.rb +0 -2
- data/lib/appnexusapi/platform_member_service.rb +0 -8
- data/lib/appnexusapi/profile_resource.rb +0 -2
- data/lib/appnexusapi/publisher_resource.rb +0 -2
- data/lib/appnexusapi/segment_resource.rb +0 -2
- data/lib/appnexusapi/site_resource.rb +0 -2
- data/lib/appnexusapi/technical_attribute_resource.rb +0 -2
- data/lib/appnexusapi/technical_attribute_service.rb +0 -8
- data/lib/appnexusapi/tiny_tag_resource.rb +0 -2
- data/lib/appnexusapi/user_resource.rb +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 06455610db5b16548020d670d175ef13fd7451f5
|
4
|
+
data.tar.gz: 07544e12f14bb6e8fe351a53798fcbf5e2eaef94
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f96356e6bb6566aff2903b3964ccb01dbb0f2ad89aaa9c2372708fa9049569c3c37c95b8c15a28370af856dfe0352409775eba90c04aaa9b0eaef03a055bb476
|
7
|
+
data.tar.gz: 640ca6320f0c33ab849038014a8f7971cbaf09a02d729252c33b819609e50384f9fe5c1566c347991181dfa19a9e374c402c160f9554a32f9e79cbc3e2f4bb44
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
## 1.1.0
|
2
|
+
- Add `Resource#save` method to allow saving resources that have been modified with `update`
|
3
|
+
- Replace `Pester` gem with `Retriable`
|
4
|
+
- Remove `NullLogger` dependency; log to STDOUT by default
|
5
|
+
- Delete unnecessary `_resource.rb` files
|
6
|
+
|
7
|
+
## 1.0.0
|
8
|
+
|
9
|
+
- Initial 1.0 release; lots of new services and resources.
|
data/README.md
CHANGED
@@ -18,58 +18,83 @@ Or install it yourself as:
|
|
18
18
|
|
19
19
|
## Usage
|
20
20
|
|
21
|
-
|
21
|
+
#### Configure defaults
|
22
|
+
```ruby
|
23
|
+
AppnexusApi.configure do |config|
|
24
|
+
config.logger = Logger.new('/path/to/log.log')
|
25
|
+
end
|
26
|
+
```
|
27
|
+
|
28
|
+
#### Establish a connection:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
connection = AppnexusApi::Connection.new(
|
32
|
+
'username' => 'username',
|
33
|
+
'password' => 'password',
|
34
|
+
'logger' => Logger.new(STDOUT) # defaults to STDOUT
|
35
|
+
|
36
|
+
# Defaults to connecting to https://api.appnexus.com/ but you can optionally pass a uri to
|
37
|
+
# connect to another endpoint, e.g. the staging site could be
|
38
|
+
# "uri" => 'http://api-test.appnexus.com',
|
39
|
+
)
|
40
|
+
```
|
22
41
|
|
23
|
-
|
24
|
-
'username' => 'username',
|
25
|
-
'password' => 'password',
|
26
|
-
'logger' => Logger.new(STDOUT) # defaults to a null logger if no value passed in.
|
42
|
+
#### Use a Service:
|
27
43
|
|
28
|
-
|
29
|
-
|
30
|
-
|
44
|
+
```ruby
|
45
|
+
member_service = AppnexusApi::MemberService.new(connection)
|
46
|
+
# get always returns an array of results
|
47
|
+
# and defaults "num_elements" to 100 and "start_element" to 0
|
48
|
+
# and returns an AppnexusApi::Resource object which is a wrapper around the JSON
|
49
|
+
member = member_service.get.first
|
31
50
|
|
51
|
+
line_item_service = AppnexusApi::LineItemService.new(connection)
|
52
|
+
line_item = line_item_service.get.first
|
53
|
+
line_item = line_item_service.get({advertiser_id: 12345}).first
|
32
54
|
|
33
|
-
|
55
|
+
# create a new object
|
56
|
+
url_params = { advertiser_id: 12345 }
|
57
|
+
body_params = { name: "some line item", code: "line item code"}
|
34
58
|
|
35
|
-
|
59
|
+
line_item = line_item_service.create(url_params, body_params)
|
60
|
+
line_item.state
|
36
61
|
|
37
|
-
member_service = AppnexusApi::MemberService.new(connection)
|
38
|
-
# get always returns an array of results
|
39
|
-
# and defaults "num_elements" to 100 and "start_element" to 0
|
40
|
-
# and returns an AppnexusApi::Resource object which is a wrapper around the JSON
|
41
|
-
member = member_service.get.first
|
42
62
|
|
43
|
-
|
44
|
-
|
45
|
-
|
63
|
+
# update an object
|
64
|
+
update_params = { state: "inactive" }
|
65
|
+
json_result = line_item.update(url_params, update_params)
|
46
66
|
|
47
|
-
|
48
|
-
|
49
|
-
body_params = { name: "some line item", code: "line item code"}
|
67
|
+
# delete an object
|
68
|
+
line_item.delete(url_params)
|
50
69
|
|
51
|
-
|
52
|
-
|
70
|
+
# save an object that you modified locally
|
71
|
+
line_item.raw_json[:state] = 'active'
|
72
|
+
line_item.save
|
53
73
|
|
74
|
+
# this raises an AppnexusApi::UnprocessableEntity, not a 404 as it should
|
75
|
+
line_item_service.get(line_item.id)
|
54
76
|
|
55
|
-
|
56
|
-
|
57
|
-
|
77
|
+
new_creative = {
|
78
|
+
"content" => "<iframe src='helloword.html'></iframe>",
|
79
|
+
"width" => "300",
|
80
|
+
"height" => "250",
|
81
|
+
"template" =>{ "id" => 7 }
|
82
|
+
}
|
83
|
+
creative = creative_service.create(new_creative)
|
84
|
+
creative.update("campaign" => "Testing")
|
85
|
+
```
|
58
86
|
|
59
|
-
|
60
|
-
line_item.delete(url_params)
|
87
|
+
#### Downloading Log Level Data:
|
61
88
|
|
62
|
-
|
63
|
-
|
89
|
+
```ruby
|
90
|
+
download_service = AppnexusApi::LogLevelDataService.new(
|
91
|
+
connection,
|
92
|
+
downloaded_files_path: '/example/local/path',
|
93
|
+
siphon_name: 'standard_feed'
|
94
|
+
)
|
64
95
|
|
65
|
-
|
66
|
-
|
67
|
-
"width" => "300",
|
68
|
-
"height" => "250",
|
69
|
-
"template" =>{ "id" => 7 }
|
70
|
-
}
|
71
|
-
creative = creative_service.create(new_creative)
|
72
|
-
creative.update("campaign" => "Testing")
|
96
|
+
downloaded_files = data_service.download_new_files_since('2016-02-01'.to_time)
|
97
|
+
```
|
73
98
|
|
74
99
|
## Testing
|
75
100
|
|
@@ -81,8 +106,15 @@ bundle exec rspec
|
|
81
106
|
### Writing New Specs or Updating Old Ones
|
82
107
|
This library uses [VCR](https://github.com/vcr/vcr) and Webmock to record API call HTTP data and play it back when you run the specs. To write new specs or update old ones, however, you will need to actually provide a valid login/password in a `.env` file (see [`env_example`](env_example) for an example) before launching the specs.
|
83
108
|
|
84
|
-
To update a spec, simply remove the relevant file from [spec/fixtures/vcr](spec/fixtures/vcr) (and setup the username/password) before launching `rspec`; the changes will be recorded automatically by VCR.
|
109
|
+
To update a spec, simply remove the relevant file from [spec/fixtures/vcr](spec/fixtures/vcr) (and setup the username/password as above) before launching `rspec`; the changes will be recorded automatically by VCR.
|
110
|
+
|
111
|
+
## Debugging
|
85
112
|
|
113
|
+
To trigger full Faraday request/respone logging, set the `APPNEXUS_API_DEBUG` environment variable before launching
|
114
|
+
your application
|
115
|
+
```
|
116
|
+
export APPNEXUS_API_DEBUG=true
|
117
|
+
```
|
86
118
|
|
87
119
|
## Contributing
|
88
120
|
|
data/appnexusapi.gemspec
CHANGED
@@ -18,8 +18,7 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.add_dependency 'faraday', '~> 0.9'
|
19
19
|
gem.add_dependency 'faraday_middleware'
|
20
20
|
gem.add_dependency 'multi_json'
|
21
|
-
gem.add_dependency '
|
22
|
-
gem.add_dependency 'null_logger'
|
21
|
+
gem.add_dependency 'retriable', '>= 2.0'
|
23
22
|
|
24
23
|
gem.add_development_dependency 'bundler', '>= 1.2.0'
|
25
24
|
gem.add_development_dependency 'rspec'
|
data/lib/appnexusapi.rb
CHANGED
@@ -1,15 +1,26 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday_middleware'
|
3
|
+
require 'logger'
|
4
|
+
require 'retriable'
|
4
5
|
|
5
|
-
|
6
|
-
|
6
|
+
require 'appnexusapi/configuration'
|
7
|
+
require 'appnexusapi/version'
|
8
|
+
require 'appnexusapi/error'
|
9
|
+
require 'appnexusapi/resource'
|
10
|
+
require 'appnexusapi/service'
|
11
|
+
require 'appnexusapi/read_only_service'
|
12
|
+
require 'appnexusapi/connection'
|
13
|
+
|
14
|
+
Dir.glob("#{File.join(File.dirname(__FILE__), 'appnexusapi', 'services')}/*.rb").each do |service_file|
|
15
|
+
require service_file
|
16
|
+
end
|
7
17
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
sym = file.capitalize.gsub(/(_(.))/) { |c| $2.upcase }.to_sym
|
12
|
-
autoload sym, "appnexusapi/#{file}"
|
18
|
+
module AppnexusApi
|
19
|
+
def self.config
|
20
|
+
@configuration ||= Configuration.new
|
13
21
|
end
|
14
22
|
|
23
|
+
def self.configure
|
24
|
+
yield(config)
|
25
|
+
end
|
15
26
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module AppnexusApi
|
2
|
+
class Configuration
|
3
|
+
attr_accessor :api_debug, :logger
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@api_debug = ENV['APPNEXUS_API_DEBUG'].to_s =~ /^(true|t|yes|y|1)$/i
|
7
|
+
@logger = Logger.new(STDOUT).tap do |logger|
|
8
|
+
@api_debug ? logger.level = Logger::DEBUG : logger.level = Logger::INFO
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -1,108 +1,101 @@
|
|
1
|
-
require 'faraday_middleware'
|
2
1
|
require 'appnexusapi/faraday/raise_http_error'
|
3
|
-
|
4
|
-
|
5
|
-
class
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
conn.request :json
|
18
|
-
conn.response :json, :content_type => /\bjson$/
|
19
|
-
conn.use AppnexusApi::Faraday::Response::RaiseHttpError
|
20
|
-
conn.adapter Faraday.default_adapter
|
2
|
+
|
3
|
+
module AppnexusApi
|
4
|
+
class Connection
|
5
|
+
RATE_EXCEEDED_DEFAULT_TIMEOUT = 15
|
6
|
+
|
7
|
+
RATE_LIMIT_WAITER = Proc.new do |exception, try, elapsed_time, next_interval|
|
8
|
+
if (match = /Retry after (\d+)s/.match(exception.message))
|
9
|
+
seconds = match[1].to_i
|
10
|
+
else
|
11
|
+
seconds = RATE_EXCEEDED_DEFAULT_TIMEOUT
|
12
|
+
end
|
13
|
+
seconds += RATE_EXCEEDED_DEFAULT_TIMEOUT # Just to be sure we waited long enough
|
14
|
+
AppnexusApi.config.logger.warn("WARN: Rate limit exceeded; retrying after #{seconds}s...")
|
15
|
+
sleep(seconds)
|
21
16
|
end
|
22
|
-
end
|
23
17
|
|
24
|
-
|
25
|
-
!@token.nil?
|
26
|
-
end
|
18
|
+
attr_reader :connection, :logger
|
27
19
|
|
28
|
-
|
29
|
-
|
30
|
-
|
20
|
+
def initialize(config)
|
21
|
+
@config = config
|
22
|
+
@config['uri'] ||= 'https://api.appnexus.com/'
|
23
|
+
@logger = @config['logger'] || AppnexusApi.config.logger
|
24
|
+
@connection = ::Faraday.new(@config['uri']) do |conn|
|
25
|
+
conn.response :logger, @logger, bodies: true if AppnexusApi.config.api_debug
|
26
|
+
conn.request :json
|
27
|
+
conn.response :json, :content_type => /\bjson$/
|
28
|
+
conn.use AppnexusApi::Faraday::Response::RaiseHttpError
|
29
|
+
conn.adapter ::Faraday.default_adapter
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def login
|
34
|
+
response = @connection.run_request(
|
35
|
+
:post,
|
36
|
+
'auth',
|
37
|
+
{ 'auth' => { 'username' => @config['username'], 'password' => @config['password'] } },
|
38
|
+
{}
|
39
|
+
)
|
40
|
+
|
41
|
+
if response.body['response']['error_code']
|
42
|
+
fail "#{response.body['response']['error_code']}/#{response.body['response']['error_description']}"
|
43
|
+
end
|
31
44
|
|
32
|
-
|
33
|
-
response = @connection.run_request(:post, 'auth', { 'auth' => { 'username' => @config['username'], 'password' => @config['password'] } }, {})
|
34
|
-
log.debug(response.body)
|
35
|
-
if response.body['response']['error_code']
|
36
|
-
fail "#{response.body['response']['error_code']}/#{response.body['response']['error_description']}"
|
45
|
+
@token = response.body['response']['token']
|
37
46
|
end
|
38
|
-
@token = response.body['response']['token']
|
39
|
-
end
|
40
47
|
|
41
|
-
|
42
|
-
|
43
|
-
|
48
|
+
def get(route, params={}, headers={})
|
49
|
+
params = params.delete_if { |_, v| v.nil? }
|
50
|
+
run_request(:get, build_url(route, params), nil, headers)
|
51
|
+
end
|
44
52
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
end
|
53
|
+
def build_url(route, params)
|
54
|
+
@connection.build_url(route, params)
|
55
|
+
end
|
49
56
|
|
50
|
-
|
51
|
-
|
52
|
-
|
57
|
+
def post(route, body=nil, headers={})
|
58
|
+
run_request(:post, route, body, headers)
|
59
|
+
end
|
53
60
|
|
54
|
-
|
55
|
-
|
56
|
-
|
61
|
+
def put(route, body=nil, headers={})
|
62
|
+
run_request(:put, route, body, headers)
|
63
|
+
end
|
57
64
|
|
58
|
-
|
59
|
-
|
60
|
-
|
65
|
+
def delete(route, body=nil, headers={})
|
66
|
+
run_request(:delete, route, body, headers)
|
67
|
+
end
|
61
68
|
|
62
|
-
|
63
|
-
run_request(:delete, route, body, headers)
|
64
|
-
end
|
69
|
+
private
|
65
70
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
rescue AppnexusApi::Unauthorized => e
|
84
|
-
if @retry == true
|
85
|
-
raise AppnexusApi::Unauthorized, e
|
86
|
-
else
|
87
|
-
@retry = true
|
88
|
-
logout
|
89
|
-
response = run_request(method, route, body, headers)
|
71
|
+
def run_request(method, route, body, headers)
|
72
|
+
login unless is_authorized?
|
73
|
+
response = {}
|
74
|
+
|
75
|
+
Retriable.retriable(on: Unauthorized, on_retry: Proc.new { logout }) do
|
76
|
+
Retriable.retriable(on: RateLimitExceeded, on_retry: RATE_LIMIT_WAITER) do
|
77
|
+
begin
|
78
|
+
response = @connection.run_request(
|
79
|
+
method,
|
80
|
+
route,
|
81
|
+
body,
|
82
|
+
{ 'Authorization' => @token }.merge(headers)
|
83
|
+
)
|
84
|
+
rescue ::Faraday::Error::TimeoutError => e
|
85
|
+
raise Timeout, e.message, e.message, e.backtrace
|
86
|
+
end
|
87
|
+
end
|
90
88
|
end
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
89
|
+
|
90
|
+
response
|
91
|
+
end
|
92
|
+
|
93
|
+
def is_authorized?
|
94
|
+
!@token.nil?
|
95
95
|
end
|
96
|
-
log.debug(response.body)
|
97
|
-
response
|
98
|
-
end
|
99
96
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
route,
|
104
|
-
body,
|
105
|
-
{ 'Authorization' => @token }.merge(headers)
|
106
|
-
)
|
97
|
+
def logout
|
98
|
+
@token = nil
|
99
|
+
end
|
107
100
|
end
|
108
101
|
end
|
data/lib/appnexusapi/error.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
module AppnexusApi
|
2
2
|
class Error < StandardError; end
|
3
|
+
|
4
|
+
class BadChecksumException < Error; end
|
3
5
|
class BadRequest < Error; end
|
4
6
|
class Unauthorized < Error; end
|
5
7
|
class Forbidden < Error; end
|
@@ -12,4 +14,5 @@ module AppnexusApi
|
|
12
14
|
class ServiceUnavailable < Error; end
|
13
15
|
class InvalidJson < Error; end
|
14
16
|
class Timeout < Error; end
|
17
|
+
class RateLimitExceeded < Error; end
|
15
18
|
end
|
@@ -2,6 +2,10 @@ module AppnexusApi
|
|
2
2
|
module Faraday
|
3
3
|
module Response
|
4
4
|
class RaiseHttpError < ::Faraday::Response::Middleware
|
5
|
+
# Inexplicably, sandbox uses the correct code of 429, while production uses 405? so
|
6
|
+
# we just rely on the error message
|
7
|
+
RATE_EXCEEDED_ERROR = 'RATE_EXCEEDED'.freeze
|
8
|
+
|
5
9
|
def on_complete(response)
|
6
10
|
case response[:status].to_i
|
7
11
|
when 400
|
@@ -25,11 +29,21 @@ module AppnexusApi
|
|
25
29
|
when 503
|
26
30
|
raise AppnexusApi::ServiceUnavailable, error_message(response)
|
27
31
|
end
|
32
|
+
|
33
|
+
return if response.body.empty?
|
34
|
+
body = JSON.parse(response.body).fetch('response', {})
|
35
|
+
|
36
|
+
if body['error_code'] == RATE_EXCEEDED_ERROR
|
37
|
+
raise AppnexusApi::RateLimitExceeded, "Retry after #{response.response_headers['retry-after']}s"
|
38
|
+
elsif body['error_id'] && !body['error_id'].empty?
|
39
|
+
# TODO: this should raise an error, but a lot of the specs currently have error responses
|
40
|
+
# raise AppnexusApi::Error, "#{body['error_id']}: #{body['error']} - #{body['error_description']}"
|
41
|
+
end
|
28
42
|
end
|
29
43
|
|
30
44
|
def error_message(response)
|
31
45
|
msg = "#{response[:method].to_s.upcase} #{response[:url].to_s}: #{response[:status]}"
|
32
|
-
if errors = response[:body] && response[:body][
|
46
|
+
if (errors = response[:body]) && response[:body]['errors']
|
33
47
|
msg << "\n"
|
34
48
|
msg << errors.join("\n")
|
35
49
|
end
|