proxy_rb 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.env +3 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +1 -0
  5. data/.travis.yml +8 -2
  6. data/Gemfile +7 -3
  7. data/README.md +42 -8
  8. data/Rakefile +8 -23
  9. data/bin/bootstrap +10 -0
  10. data/{script → bin}/console +1 -0
  11. data/bin/test +3 -0
  12. data/cucumber.yml +2 -0
  13. data/fixtures/proxy-config/.rspec +2 -0
  14. data/fixtures/proxy-config/README.md +18 -0
  15. data/fixtures/proxy-config/Rakefile +10 -0
  16. data/fixtures/proxy-config/bin/http_server +14 -0
  17. data/fixtures/proxy-config/spec/spec_helper.rb +8 -0
  18. data/fixtures/proxy-config/spec/support/aruba.rb +2 -0
  19. data/fixtures/proxy-config/spec/support/proxy_rb.rb +2 -0
  20. data/lib/proxy_rb/basic_configuration/in_config_wrapper.rb +28 -0
  21. data/lib/proxy_rb/basic_configuration/option.rb +32 -0
  22. data/lib/proxy_rb/basic_configuration.rb +148 -0
  23. data/lib/proxy_rb/configuration.rb +42 -0
  24. data/lib/proxy_rb/credentials.rb +52 -0
  25. data/lib/proxy_rb/errors.rb +5 -0
  26. data/lib/proxy_rb/http_downloader.rb +23 -0
  27. data/lib/proxy_rb/http_proxy.rb +52 -0
  28. data/lib/proxy_rb/main.rb +8 -2
  29. data/lib/proxy_rb/no_proxy.rb +26 -0
  30. data/lib/proxy_rb/password_fetchers/basic_password_fetcher.rb +12 -0
  31. data/lib/proxy_rb/password_fetchers/environment_password_fetcher.rb +34 -0
  32. data/lib/proxy_rb/password_fetchers/vault_password_fetcher.rb +47 -0
  33. data/lib/proxy_rb/password_fetchers.rb +6 -0
  34. data/lib/proxy_rb/proxy_url.rb +73 -0
  35. data/lib/proxy_rb/proxy_url_parser.rb +56 -0
  36. data/lib/proxy_rb/request.rb +36 -0
  37. data/lib/proxy_rb/resource.rb +28 -0
  38. data/lib/proxy_rb/response.rb +20 -0
  39. data/lib/proxy_rb/rspec/helpers/http_proxy.rb +78 -0
  40. data/lib/proxy_rb/rspec/helpers/passwords.rb +29 -0
  41. data/lib/proxy_rb/rspec.rb +9 -6
  42. data/lib/proxy_rb/user_passwords/environment_user_password.rb +30 -0
  43. data/lib/proxy_rb/user_passwords/vault_user_password.rb +27 -0
  44. data/lib/proxy_rb/user_passwords.rb +7 -0
  45. data/lib/proxy_rb/version.rb +2 -1
  46. data/lib/proxy_rb.rb +2 -0
  47. data/proxy_rb.gemspec +5 -3
  48. metadata +40 -9
  49. data/Gemfile.lock +0 -263
  50. data/script/bootstrap +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 504810e2b43ff35a50377363f2cd74b22caadf70
4
- data.tar.gz: 54c59c88935fc8bd1195e26b25c0340a748c14ec
3
+ metadata.gz: db7176840c8e9a52da91b08248612198aa17f557
4
+ data.tar.gz: ca4ad19e9d3bad727954e3ed9164cad8ee0e6267
5
5
  SHA512:
6
- metadata.gz: 634c2663282ea5804be8dacb98be87ffe0292390db532b537b41373919dea5327b33ec13fc5b08e21061bb9ca966040ea2034af7d6ebaade2ec511d2c6b21b35
7
- data.tar.gz: 582664775a075dfd4ca583e645568a879b46f5436519dde04110460b6138e44191368da6785d927064c7abb0bdc78d499dc9d7e98dddc03dc39e42aa70b5cf0b
6
+ metadata.gz: 53f73d13a40222916a1783e2c4ba19bf1ac749ea866f6d81e571baed37a567e29f245a98fc0654dd2817b114faa5bc6e49cacca4a53cdd0baf3a8dcc796b27e1
7
+ data.tar.gz: c75ebce750ca3f20a8000a498a54208c4f6c5c24b79ceb30427c4a1cd769ee569c8ee39e27c13f6646a77876fe56267824b4d1d501cfa3a4f2d3490feb5d071a
data/.env ADDED
@@ -0,0 +1,3 @@
1
+ VAULT_ADDR="http://localhost:8200"
2
+ # VAULT_TOKEN="*Test123"
3
+ # VAULT_SSL_VERIFY=0
data/.gitignore CHANGED
@@ -3,3 +3,4 @@
3
3
  pkg/*
4
4
  coverage
5
5
  tmp/
6
+ Gemfile.lock
data/.rubocop.yml CHANGED
@@ -2,6 +2,7 @@ AllCops:
2
2
  Exclude:
3
3
  - 'tmp/**/*'
4
4
  DisplayCopNames: true
5
+ TargetRubyVersion: 2.3
5
6
 
6
7
  Metrics/AbcSize:
7
8
  Max: 38
data/.travis.yml CHANGED
@@ -1,8 +1,14 @@
1
+ sudo: false
1
2
  env:
2
3
  - CI=1
3
4
  language: ruby
4
5
  bundler_args: --without development debug profile
5
6
  rvm:
6
7
  - 2.1.5
7
- - 2.2.1
8
- script: script/ci
8
+ - 2.2.3
9
+ - 2.3.0
10
+ script: script/test
11
+ before_install:
12
+ - curl -o /tmp/vault.zip https://releases.hashicorp.com/vault/0.5.1/vault_0.5.1_linux_amd64.zip
13
+ - unzip /tmp/vault.zip
14
+ - install -D -m 0755 /tmp/vault ./bin/vault
data/Gemfile CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  source 'https://rubygems.org'
2
3
 
3
4
  # Specify your gem's dependencies in local_pac.gemspec
@@ -13,7 +14,12 @@ group :debug do
13
14
  end
14
15
 
15
16
  group :development, :test do
16
- gem 'activesupport', '~> 4.2.0', require: false
17
+ # Password store
18
+ gem 'vault'
19
+
20
+ # Set env during development/test
21
+ gem 'dotenv'
22
+
17
23
  gem 'aruba', require: false
18
24
  gem 'awesome_print', require: 'ap'
19
25
  gem 'bundler', '~> 1.3', require: false
@@ -21,7 +27,6 @@ group :development, :test do
21
27
  gem 'coveralls', require: false
22
28
  gem 'cucumber', require: false
23
29
  gem 'erubis'
24
- gem 'fedux_org-stdlib', '~>0.7.25', require: false
25
30
  gem 'filegen'
26
31
  gem 'foreman', require: false
27
32
  gem 'fuubar', require: false
@@ -31,7 +36,6 @@ group :development, :test do
31
36
  gem 'license_finder'
32
37
  gem 'rack'
33
38
  gem 'rake', require: false
34
- gem 'redcarpet', require: false
35
39
  gem 'rubocop', require: false
36
40
  gem 'simplecov', require: false
37
41
  gem 'sinatra', require: 'sinatra/base'
data/README.md CHANGED
@@ -1,8 +1,6 @@
1
1
  # ProxyRb
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/proxy_rb`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ `proxy_rb` makes it easier for you to test your proxy infrastructre.
6
4
 
7
5
  ## Installation
8
6
 
@@ -22,8 +20,12 @@ Or install it yourself as:
22
20
 
23
21
  ## Usage
24
22
 
23
+ ### Rspec-Integration
24
+
25
25
  ```ruby
26
- RSpec.describe 'Intfrastructure A' do
26
+ require 'proxy_rb/rspec'
27
+
28
+ RSpec.describe 'Infrastructure A' do
27
29
  describe 'proxy1' do
28
30
  subject { 'proxy1.example.com' }
29
31
 
@@ -95,14 +97,46 @@ RSpec.describe 'Intfrastructure A' do
95
97
  end
96
98
  ```
97
99
 
100
+ ### Authentication
101
+
102
+ Maybe your proxy servers require authentication and you would like to test this
103
+ as well. You've got several possibilies to use proxy passwords with `proxy_rb`.
104
+ Please have a look at
105
+ ["features/authentication.feature"](features/authentication.feature) for
106
+ detailed information.
107
+
108
+
98
109
  ## Development
99
110
 
100
- After checking out the repo, run `bin/setup` to install dependencies. Then, run
101
- `bin/console` for an interactive prompt that will allow you to experiment.
111
+ ### Requirements
112
+
113
+ Go to [the download site](https://www.vaultproject.io/downloads.html) of the
114
+ "Vault Project" and download the latest `vault` binary. Make sure you place it
115
+ into a path which is part of the "PATH"-environment variable - even on Windows.
116
+
117
+ *Example for a Linux Distribution*
118
+
119
+ ~~~bash
120
+ curl -o /tmp/vault.zip https://releases.hashicorp.com/vault/0.5.1/vault_0.5.1_linux_amd64.zip
121
+ unzip /tmp/vault.zip
122
+ install -D /tmp/vault -m 0755 ~/bin/vault
123
+ ~~~
124
+
125
+ Maybe you want to add the path `~/bin` to `PATH` via `.bashrc` or `.zshrc`.
126
+
127
+ ~~~bash
128
+ export PATH=~/bin:$PATH
129
+ ~~~
130
+
131
+ ### Scripts
132
+
133
+ After checking out the repo, run `script/bootstrap` to install dependencies.
134
+ Then, run `script/console` for an interactive prompt that will allow you to
135
+ experiment.
102
136
 
103
- To install this gem onto your local machine, run `bundle exec rake install`. To
137
+ To install this gem onto your local machine, run `bundle exec rake gem:install`. To
104
138
  release a new version, update the version number in `version.rb`, and then run
105
- `bundle exec rake release` to create a git tag for the version, push git
139
+ `bundle exec rake gem:release` to create a git tag for the version, push git
106
140
  commits and tags, and push the `.gem` file to
107
141
  [rubygems.org](https://rubygems.org).
108
142
 
data/Rakefile CHANGED
@@ -1,25 +1,20 @@
1
1
  #!/usr/bin/env rake
2
+ # frozen_string_literal: true
3
+
4
+ namespace :gems do
5
+ require 'bundler/gem_tasks'
6
+ end
2
7
 
3
8
  # require 'bundler'
4
9
  # Bundler.require :default, :test, :development
5
10
 
6
- require 'filegen'
7
- require 'fedux_org_stdlib/rake_tasks'
8
-
9
11
  require 'coveralls/rake/task'
10
12
  Coveralls::RakeTask.new
11
13
 
14
+ task default: :test
15
+
12
16
  desc 'Run test suite'
13
- task :test do
14
- Rake::Task['test:before'].execute
15
-
16
- begin
17
- #%w(test:rubocop test:rspec test:cucumber test:after).each { |t| Rake::Task[t].execute }
18
- %w(test:rubocop test:rspec test:after).each { |t| Rake::Task[t].execute }
19
- ensure
20
- Rake::Task['test:after'].execute
21
- end
22
- end
17
+ task test: %w(test:rubocop test:rspec test:cucumber)
23
18
 
24
19
  namespace :test do
25
20
  desc 'Test with coveralls'
@@ -37,14 +32,4 @@ namespace :test do
37
32
  task :cucumber do
38
33
  sh 'bundle exec cucumber -p all'
39
34
  end
40
-
41
- desc 'Setup test environment'
42
- task :before do
43
- @web_server = Process.spawn 'rackup -p 65535 script/config.ru'
44
- end
45
-
46
- desc 'Teardown test environment'
47
- task :after do
48
- sh "kill -9 #{@web_server}"
49
- end
50
35
  end
data/bin/bootstrap ADDED
@@ -0,0 +1,10 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ which ruby 2>/dev/null >&2 || {
6
+ echo 'Bitte "ruby" installieren'
7
+ exit 2
8
+ }
9
+
10
+ gem install bundler && bundle install
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'bundler/setup'
4
5
  require 'proxy_rb'
data/bin/test ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+
3
+ bundle exec rake test
data/cucumber.yml ADDED
@@ -0,0 +1,2 @@
1
+ default: -t @wip:3 -t ~@broken-external -t ~@future -t ~@broken
2
+ all: -t ~@wip -t ~@broken-external -t ~@future -t ~@broken
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,18 @@
1
+ # Simple proxy configuration project
2
+
3
+ This is a simple proxy configuration project
4
+
5
+ ## Boostrap
6
+
7
+ Execute:
8
+
9
+ $ bundle
10
+
11
+ ## Usage
12
+
13
+ Place files in `spec/` and run `rspec`.
14
+
15
+ ### Fixture
16
+
17
+ This fixture includes files for `rspec`-integration.
18
+
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+ namespace :gem do
3
+ require 'bundler/gem_tasks'
4
+ end
5
+
6
+ task default: :test
7
+
8
+ task :test do
9
+ sh 'rspec'
10
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'webrick'
5
+
6
+ server = WEBrick::HTTPServer.new(
7
+ Port: 8000
8
+ )
9
+
10
+ server.mount_proc '/' do |_req, res|
11
+ res.body = 'Example Domain'
12
+ end
13
+
14
+ server.start
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
3
+
4
+ if RUBY_VERSION < '1.9.3'
5
+ ::Dir.glob(::File.expand_path('../support/**/*.rb', __FILE__)).each { |f| require File.join(File.dirname(f), File.basename(f, '.rb')) }
6
+ else
7
+ ::Dir.glob(::File.expand_path('../support/**/*.rb', __FILE__)).each { |f| require_relative f }
8
+ end
@@ -0,0 +1,2 @@
1
+ # frozen_string_literal: true
2
+ require 'aruba/rspec'
@@ -0,0 +1,2 @@
1
+ # frozen_string_literal: true
2
+ require 'proxy_rb/rspec'
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ # ProxyRb
3
+ module ProxyRb
4
+ # Basic Configuration
5
+ class BasicConfiguration
6
+ # In config wrapper
7
+ #
8
+ # Used to make the configuration read only if one needs to access an
9
+ # configuration option from with `ProxyRb::Config`.
10
+ #
11
+ # @private
12
+ class InConfigWrapper
13
+ attr_reader :config
14
+ private :config
15
+
16
+ def initialize(config)
17
+ @config = config.dup
18
+ end
19
+
20
+ def method_missing(name, *args)
21
+ raise ArgumentError, 'Options take no argument' if args.count > 0
22
+ raise UnknownOptionError, %(Option "#{name}" is unknown. Please use only earlier defined options) unless config.key? name
23
+
24
+ config[name]
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+ # ProxyRb
3
+ module ProxyRb
4
+ # Basic Configuration
5
+ class BasicConfiguration
6
+ # A configuration option
7
+ #
8
+ # @private
9
+ class Option
10
+ attr_accessor :name, :value
11
+ attr_reader :default_value
12
+
13
+ # Create option
14
+ def initialize(opts = {})
15
+ name = opts[:name]
16
+ value = opts[:value]
17
+
18
+ raise ArgumentError, '"name" is required' unless opts.key? :name
19
+ raise ArgumentError, '"value" is required' unless opts.key? :value
20
+
21
+ @name = name
22
+ @value = value
23
+ @default_value = value
24
+ end
25
+
26
+ # Compare option
27
+ def ==(other)
28
+ name == other.name && value == other.value
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+ require 'contracts'
3
+ require 'proxy_rb/basic_configuration/option'
4
+ require 'proxy_rb/basic_configuration/in_config_wrapper'
5
+
6
+ # ProxyRb
7
+ module ProxyRb
8
+ # Basic configuration
9
+ class BasicConfiguration
10
+ include Contracts
11
+
12
+ class << self
13
+ def known_options
14
+ @known_options ||= {}
15
+ end
16
+
17
+ # Define an option reader
18
+ #
19
+ # @param [Symbol] name
20
+ # The name of the reader
21
+ #
22
+ # @param [Hash] opts
23
+ # Options
24
+ #
25
+ # @option [Class, Module] contract
26
+ # The contract for the option
27
+ #
28
+ # @option [Object] default
29
+ # The default value
30
+ def option_reader(name, opts = {})
31
+ contract = opts[:contract]
32
+ default = opts[:default]
33
+
34
+ raise ArgumentError, 'Either use block or default value' if block_given? && default
35
+ raise ArgumentError, 'contract-options is required' if contract.nil?
36
+
37
+ Contract contract
38
+ add_option(name, block_given? ? yield(InConfigWrapper.new(known_options)) : default)
39
+
40
+ define_method(name) { find_option(name).value }
41
+
42
+ self
43
+ end
44
+
45
+ # Define an option reader and writer
46
+ #
47
+ # @param [Symbol] name
48
+ # The name of the reader
49
+ #
50
+ # @param [Hash] opts
51
+ # Options
52
+ #
53
+ # @option [Class, Module] contract
54
+ # The contract for the option
55
+ #
56
+ # @option [Object] default
57
+ # The default value
58
+ def option_accessor(name, opts = {})
59
+ contract = opts[:contract]
60
+ default = opts[:default]
61
+
62
+ raise ArgumentError, 'Either use block or default value' if block_given? && default
63
+ # fail ArgumentError, 'Either use block or default value' if !block_given? && default.nil? && default.to_s.empty?
64
+ raise ArgumentError, 'contract-options is required' if contract.nil?
65
+
66
+ # Add writer
67
+ add_option(name, block_given? ? yield(InConfigWrapper.new(known_options)) : default)
68
+
69
+ Contract contract
70
+ define_method("#{name}=") { |v| find_option(name).value = v }
71
+
72
+ # Add reader
73
+ option_reader name, contract: { None => contract.values.first }
74
+ end
75
+
76
+ private
77
+
78
+ def add_option(name, value = nil)
79
+ return if known_options.key?(name)
80
+
81
+ known_options[name] = Option.new(name: name, value: value)
82
+
83
+ self
84
+ end
85
+ end
86
+
87
+ protected
88
+
89
+ attr_accessor :local_options
90
+
91
+ public
92
+
93
+ # Create configuration
94
+ def initialize
95
+ initialize_configuration
96
+ end
97
+
98
+ # @yield [Configuration]
99
+ #
100
+ # Yields self
101
+ def configure
102
+ yield self if block_given?
103
+ end
104
+
105
+ # Reset configuration
106
+ def reset
107
+ initialize_configuration
108
+ end
109
+
110
+ # Make deep dup copy of configuration
111
+ def make_copy
112
+ obj = dup
113
+ obj.local_options = Marshal.load(Marshal.dump(local_options))
114
+
115
+ obj
116
+ end
117
+
118
+ # Check if <name> is option
119
+ #
120
+ # @param [String, Symbol] name
121
+ # The name of the option
122
+ def option?(name)
123
+ local_options.any? { |_, v| v.name == name.to_sym }
124
+ end
125
+
126
+ def ==(other)
127
+ local_options.values.map(&:value) == other.local_options.values.map(&:value)
128
+ end
129
+
130
+ # Set if name is option
131
+ def set_if_option(name, *args)
132
+ send("#{name}=".to_sym, *args) if option? name
133
+ public_send("#{name}=".to_sym, *args) if option? name
134
+ end
135
+
136
+ private
137
+
138
+ def initialize_configuration
139
+ @local_options = Marshal.load(Marshal.dump(self.class.known_options))
140
+ end
141
+
142
+ def find_option(name)
143
+ raise NotImplementedError, %(Unknown option "#{name}") unless option? name
144
+
145
+ local_options[name]
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+ require 'contracts'
3
+
4
+ require 'proxy_rb/version'
5
+ require 'proxy_rb/basic_configuration'
6
+ require 'proxy_rb/basic_configuration/in_config_wrapper'
7
+
8
+ require 'proxy_rb/password_fetchers/basic_password_fetcher'
9
+ require 'proxy_rb/password_fetchers/environment_password_fetcher'
10
+
11
+ # ProxyRb
12
+ module ProxyRb
13
+ # ProxyRb Configuration
14
+ #
15
+ # This defines the configuration options of proxy_rb
16
+ class Configuration < BasicConfiguration
17
+ option_accessor :password_fetcher, contract: { PasswordFetchers::BasicPasswordFetcher => PasswordFetchers::BasicPasswordFetcher }, default: ProxyRb::PasswordFetchers::EnvironmentPasswordFetcher.new(prefix: 'SECRET')
18
+ end
19
+ end
20
+
21
+ # ProxyRb
22
+ module ProxyRb
23
+ @config = Configuration.new
24
+
25
+ class << self
26
+ attr_reader :config
27
+
28
+ # Configure proxy_rb
29
+ #
30
+ # @example How to configure proxy_rb
31
+ #
32
+ # ProxyRb.configure do |config|
33
+ # config.<option> = <value>
34
+ # end
35
+ #
36
+ def configure(&block)
37
+ @config.configure(&block)
38
+
39
+ self
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+ require 'shellwords'
3
+
4
+ # ProxyRb
5
+ module ProxyRb
6
+ # Hold proxy credentials
7
+ class Credentials
8
+ protected
9
+
10
+ attr_reader :password
11
+
12
+ public
13
+
14
+ attr_reader :user_name
15
+
16
+ # @param [String] user_name
17
+ # The user name to use for authentication against proxy
18
+ #
19
+ # @param [String] password
20
+ # The password to use for authentication against proxy
21
+ def initialize(user_name, password)
22
+ @user_name = user_name
23
+ @password = password
24
+ end
25
+
26
+ # Convert to string
27
+ #
28
+ # @return [String]
29
+ # A formatted string <user>:<password>
30
+ def to_s
31
+ Shellwords.escape(format('%s:%s', user_name, password))
32
+ end
33
+
34
+ # Is credentials empty
35
+ #
36
+ # @return [TrueClass, FalseClass]
37
+ # Empty if any user_name or password is empty
38
+ def empty?
39
+ !(user_name? && password?)
40
+ end
41
+
42
+ private
43
+
44
+ def user_name?
45
+ !(user_name.nil? || user_name.empty?)
46
+ end
47
+
48
+ def password?
49
+ !(password.nil? || password.empty?)
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+ module ProxyRb
3
+ # Raised if time out occured while fetch resource
4
+ class UrlTimeoutError < StandardError; end
5
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+ require 'excon'
3
+
4
+ # ProxyRb
5
+ module ProxyRb
6
+ # Download Content via proxy
7
+ class HttpDownloader
8
+ private
9
+
10
+ attr_reader :downloader, :proxy
11
+
12
+ public
13
+
14
+ def initialize(proxy)
15
+ @downloader = Excon
16
+ @proxy = proxy
17
+ end
18
+
19
+ def process(resource)
20
+ resource.content = downloader.get(resource.to_uri, proxy: proxy.to_uri)
21
+ end
22
+ end
23
+ end