pacproxy 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: eda757cf693b406eb8f4502a3e85b2b0e326b95d
4
- data.tar.gz: d8ed42f024dfebcccf979f4e05e5c2df8eb0d8ea
3
+ metadata.gz: b4024d37226f9d4c70c55a9279e6a0ffa89b33ab
4
+ data.tar.gz: 6d13403957afc8ca4e5d467f43885430cd7c5ef2
5
5
  SHA512:
6
- metadata.gz: fb5e9a2dcfdbea5c337df0142e049081a9f718bdefe59ef3c62979aca90cf38c19ff9dd1c944858eb193c52a53818043046de28be0e8fa740297b2d13818e979
7
- data.tar.gz: 706eb4bebce43f55c59572d1afb6f55c6292305adbafe3a3660bdee0cfe11546040805188c90ae25ce6784be925bbe0c72f52a2eff2c9b1f95b1a204e67ed14a
6
+ metadata.gz: a8dd7e83efc77dcc421ae35318e0eaf755c4cf5eb8f28688509c8b0d94676c2b1472c4a2f3a17f5e789d59d381bd2db848ca970f70abb015f170dc7438a21714
7
+ data.tar.gz: 4e38c95852f2dd9e534412272d443de7a3912f47299021cf9688081c167b3437371a2c93491abdc716629a7824cd47a32861df76784bc9fb2fcd97d5302be937
data/README.md CHANGED
@@ -7,16 +7,35 @@ Pacproxy provides http/https proxy routed by proxy.pac.
7
7
  [![Code Climate](https://codeclimate.com/github/otahi/pacproxy.png)](https://codeclimate.com/github/otahi/pacproxy)
8
8
  [![Gem Version](https://badge.fury.io/rb/pacproxy.png)](http://badge.fury.io/rb/pacproxy)
9
9
 
10
- **:warning: Now Pacproxy is early stage, so it might have big change.**
11
-
12
10
  ## Usage
13
11
 
12
+ $ bundle exec pacproxy
13
+
14
+ or
15
+
16
+ $ bundle exec pacproxy -c pacproxy.yml
17
+
18
+ or
19
+
14
20
  $ bundle exec pacproxy -P proxy.pac -p 3128
15
21
 
16
22
  or
17
23
 
18
24
  $ bundle exec pacproxy -P http://sample.org/proxy.pac -p 3128
19
25
 
26
+ ## Configuration
27
+
28
+ You can configure pacproxy by a file which you specified with `-c` option.
29
+ The default configuration file is `pacproxy.yml`([sample](./pacproxy.yml))
30
+ in the current working directory.
31
+
32
+ Configurable items:
33
+ - daemonize
34
+ - port
35
+ - pac file
36
+ - general log
37
+ - access log
38
+
20
39
  ## Installation
21
40
 
22
41
  Add this line to your application's Gemfile, for example:
data/bin/pacproxy CHANGED
@@ -4,32 +4,46 @@ require 'pacproxy'
4
4
  require 'optparse'
5
5
  require 'logger'
6
6
 
7
- port = 3128
8
- proxy_pac = nil
9
- daemonize = false
10
- log_file = 'pacproxy.log'
7
+ config_file = nil
8
+ config = Pacproxy::Config.instance.config
11
9
 
12
10
  OptionParser.new do |o|
13
- o.on('-d', 'daemonize') { daemonize = true }
14
- o.on('-l LOGFILE', String, "specify log file. default: #{log_file}") { |l| log_file = l }
15
- o.on('-p PORT', Integer,"specify listening port. default: #{port}") { |p| port = p }
16
- o.on('-P PROXYPAC', String, 'specify proxy.pac location') { |pac| proxy_pac = pac }
17
- o.on('-h', 'show this help') { puts o; exit }
11
+ o.on('-c CONFIGFILE', String,
12
+ "specify config file. default: #{config_file}") do |f|
13
+ config_file = f
14
+ config = Pacproxy::Config.instance.update(config_file).config
15
+ end
16
+ o.on('-d', 'daemonize') { config.merge!('daemonize' => true) }
17
+ o.on('-l LOGFILE', String,
18
+ "specify log file. default: #{config['log_file']}") do |l|
19
+ config.merge!('log_file' => l)
20
+ end
21
+ o.on('-p PORT', Integer,
22
+ "specify listening port. default: #{config['port']}") do |p|
23
+ config.merge!('port' => p)
24
+ end
25
+ o.on('-P PROXYPAC', String, 'specify proxy.pac location') do |pac|
26
+ config.merge!('pac_file' => { 'location' => pac })
27
+ end
28
+ o.on('-h', 'show this help') do
29
+ puts o
30
+ exit
31
+ end
18
32
  o.parse!
19
33
  end
20
34
 
21
- logger = Logger.new(log_file, 'weekly')
22
- logger.level = Logger::DEBUG
23
-
24
- s = Pacproxy::Pacproxy.new(Port: port,
25
- Proxypac: proxy_pac,
26
- Logger: logger)
35
+ s = Pacproxy::Pacproxy.new(config)
27
36
 
28
37
  Signal.trap('INT') do
29
38
  s.shutdown
30
39
  end
31
40
 
32
- if daemonize
41
+ if config['daemonize']
42
+ # To use executed directory as the current directory
43
+ # The current directory is changed when daemonized to '/'
44
+ Pacproxy::GeneralLogger.instance
45
+ Pacproxy::AccessLogger.instance
46
+
33
47
  WEBrick::Daemon.start { s.start }
34
48
  else
35
49
  s.start
@@ -10,14 +10,23 @@ module Pacproxy
10
10
  attr_accessor :logger
11
11
 
12
12
  def initialize
13
- @logger = Logger.new('proxy_access.log', 7, 10 * 1024 * 1024)
13
+ c = Config.instance.config['access_log']
14
14
  @format = WEBrick::AccessLog::COMMON_LOG_FORMAT
15
+ return @logger = nil unless c
16
+
17
+ @format = c['format'] if c['format']
18
+
19
+ location = c['location'] ? c['location'] : STDOUT
20
+ shift_age = c['shift_age'] ? c['shift_age'] : 0
21
+ shift_size = c['shift_size'] ? c['shift_size'] : 1_048_576
22
+ @logger = Logger.new(location, shift_age, shift_size)
15
23
  end
16
24
 
17
25
  def accesslog(req, res)
18
26
  params = setup_params(req, res)
19
- logger << WEBrick::AccessLog.format(@format, params)
20
- logger << "\n"
27
+ return unless @logger
28
+ @logger << WEBrick::AccessLog.format(@format, params)
29
+ @logger << "\n"
21
30
  end
22
31
 
23
32
  private
@@ -0,0 +1,33 @@
1
+ require 'pacproxy'
2
+ require 'yaml'
3
+
4
+ module Pacproxy
5
+ # Pacproxy::Config represent configuration for Pacproxy
6
+ class Config
7
+ include Singleton
8
+ DEFAULT_CONFIG = {
9
+ 'daemonize' => false,
10
+ 'port' => 3128,
11
+ 'pac_file' => { 'location' => nil },
12
+ 'general_log' => { 'location' => 'pacproxy.log' }
13
+ }
14
+
15
+ attr_reader :config
16
+
17
+ def initialize
18
+ @config = DEFAULT_CONFIG
19
+ self
20
+ end
21
+
22
+ def update(yaml_file = 'pacproxy.yml')
23
+ @config.merge!(read_config(yaml_file))
24
+ self
25
+ end
26
+
27
+ def read_config(yaml_file)
28
+ return {} unless yaml_file
29
+ return {} unless File.exist?(yaml_file)
30
+ YAML.load(File.read(yaml_file))
31
+ end
32
+ end
33
+ end
@@ -9,7 +9,14 @@ module Pacproxy
9
9
  attr_accessor :logger
10
10
 
11
11
  def initialize
12
- @logger = Logger.new('pacproxy.log', 7, 10 * 1024 * 1024)
12
+ c = Config.instance.config['general_log']
13
+ return @logger = nil unless c
14
+
15
+ location = c['location'] ? c['location'] : STDOUT
16
+ shift_age = c['shift_age'] ? c['shift_age'] : 0
17
+ shift_size = c['shift_size'] ? c['shift_size'] : 1_048_576
18
+ @logger = Logger.new(location, shift_age, shift_size)
19
+ @logger.level = c['log_level'] ? Logger.const_get(c['log_level']) : Logger::ERROR
13
20
  @logger.progname = 'pacproxy'
14
21
  end
15
22
  end
@@ -13,27 +13,27 @@ module Pacproxy
13
13
  end
14
14
 
15
15
  def debug(message)
16
- general_logger.debug(message)
16
+ general_logger.debug(message) if general_logger
17
17
  end
18
18
 
19
19
  def info(message)
20
- general_logger.info(message)
20
+ general_logger.info(message) if general_logger
21
21
  end
22
22
 
23
23
  def lwarn(message)
24
- general_logger.warn(message)
24
+ general_logger.warn(message) if general_logger
25
25
  end
26
26
 
27
27
  def error(message)
28
- general_logger.error(message)
28
+ general_logger.error(message) if general_logger
29
29
  end
30
30
 
31
31
  def fatal(message)
32
- general_logger.fatal(message)
32
+ general_logger.fatal(message) if general_logger
33
33
  end
34
34
 
35
35
  def accesslog(req, res)
36
- access_logger.accesslog(req, res)
36
+ access_logger.accesslog(req, res) if access_logger
37
37
  end
38
38
  end
39
39
  end
@@ -1,10 +1,18 @@
1
1
  require 'pacproxy'
2
2
  require 'pac'
3
3
  require 'uri'
4
+ require 'thread'
4
5
 
5
6
  module Pacproxy
6
7
  # Pacproxy::PacFile represent proxy.pac file
7
8
  class PacFile
9
+ include Loggable
10
+
11
+ @js_lock = Mutex.new
12
+ class << self
13
+ attr_reader :js_lock
14
+ end
15
+
8
16
  def initialize(file_location, update_interval = 1800)
9
17
  @pac = nil
10
18
  begin_update(file_location, update_interval)
@@ -12,7 +20,9 @@ module Pacproxy
12
20
 
13
21
  def find(uri)
14
22
  return 'DIRECT' unless @pac
15
- @pac.find(uri)
23
+ PacFile.js_lock.synchronize do
24
+ @pac.find(uri)
25
+ end
16
26
  end
17
27
 
18
28
  private
@@ -32,9 +42,8 @@ module Pacproxy
32
42
  def update(file_location)
33
43
  tmp = PAC.load(file_location)
34
44
  @pac = tmp if @pac.nil? || @pac.source != tmp.source
35
- rescue
36
- # log
37
- puts "#{file_location} update error"
45
+ rescue => e
46
+ error("#{file_location} update error: #{e}")
38
47
  end
39
48
  end
40
49
  end
@@ -4,13 +4,15 @@ require 'uri'
4
4
 
5
5
  module Pacproxy
6
6
  # Pacproxy::Pacproxy represent http/https proxy server
7
- class Pacproxy < WEBrick::HTTPProxyServer
7
+ class Pacproxy < WEBrick::HTTPProxyServer # rubocop:disable ClassLength
8
8
  include Loggable
9
9
 
10
10
  def initialize(config = {}, default = WEBrick::Config::HTTP)
11
- config[:Logger] = general_logger
12
- super(config, default)
13
- @pac = PacFile.new(config[:Proxypac])
11
+ super({ Port: config['port'], Logger: general_logger }, default)
12
+ return unless config['pac_file'] && config['pac_file']['location']
13
+
14
+ @pac = PacFile.new(config['pac_file']['location'],
15
+ config['pac_file']['update_interval'])
14
16
  end
15
17
 
16
18
  def proxy_uri(req, res)
@@ -37,6 +39,94 @@ module Pacproxy
37
39
  URI.parse("http://#{basic_auth.unpack('m').first}@#{proxy}")
38
40
  end
39
41
 
42
+ # This method is mainly from WEBrick::HTTPProxyServer.
43
+ # To allow upstream proxy authentication,
44
+ # it operate 407 response from an upstream proxy.
45
+ # see: https://github.com/ruby/ruby/blob/trunk/lib/webrick/httpproxy.rb
46
+ # rubocop:disable all
47
+ def do_CONNECT(req, res)
48
+ # Proxy Authentication
49
+ proxy_auth(req, res)
50
+
51
+ ua = Thread.current[:WEBrickSocket] # User-Agent
52
+ raise WEBrick::HTTPStatus::InternalServerError,
53
+ "[BUG] cannot get socket" unless ua
54
+
55
+ host, port = req.unparsed_uri.split(":", 2)
56
+ # Proxy authentication for upstream proxy server
57
+ if proxy = proxy_uri(req, res)
58
+ proxy_request_line = "CONNECT #{host}:#{port} HTTP/1.0"
59
+ if proxy.userinfo
60
+ credentials = "Basic " + [proxy.userinfo].pack("m").delete("\n")
61
+ end
62
+ host, port = proxy.host, proxy.port
63
+ end
64
+
65
+ begin
66
+ @logger.debug("CONNECT: upstream proxy is `#{host}:#{port}'.")
67
+ os = TCPSocket.new(host, port) # origin server
68
+
69
+ if proxy
70
+ @logger.debug("CONNECT: sending a Request-Line")
71
+ os << proxy_request_line << WEBrick::CRLF
72
+ @logger.debug("CONNECT: > #{proxy_request_line}")
73
+ if credentials
74
+ @logger.debug("CONNECT: sending a credentials")
75
+ os << "Proxy-Authorization: " << credentials << WEBrick::CRLF
76
+ end
77
+ os << WEBrick::CRLF
78
+ proxy_status_line = os.gets(WEBrick::LF)
79
+ @logger.debug("CONNECT: read a Status-Line form the upstream server")
80
+ @logger.debug("CONNECT: < #{proxy_status_line}")
81
+ if /^HTTP\/\d+\.\d+\s+(?<st>200|407)\s*/ =~ proxy_status_line
82
+ res.status = st.to_i
83
+ while line = os.gets(WEBrick::LF)
84
+ res.header['Proxy-Authenticate'] =
85
+ line.split(':')[1] if /Proxy-Authenticate/i =~ line
86
+ break if /\A(#{WEBrick::CRLF}|#{WEBrick::LF})\z/om =~ line
87
+ end
88
+ else
89
+ raise WEBrick::HTTPStatus::BadGateway
90
+ end
91
+ end
92
+ @logger.debug("CONNECT #{host}:#{port}: succeeded")
93
+ rescue => ex
94
+ @logger.debug("CONNECT #{host}:#{port}: failed `#{ex.message}'")
95
+ res.set_error(ex)
96
+ raise WEBrick::HTTPStatus::EOFError
97
+ ensure
98
+ if handler = @config[:ProxyContentHandler]
99
+ handler.call(req, res)
100
+ end
101
+ res.send_response(ua)
102
+ access_log(@config, req, res)
103
+
104
+ # Should clear request-line not to send the response twice.
105
+ # see: HTTPServer#run
106
+ req.parse(WEBrick::NullReader) rescue nil
107
+ end
108
+
109
+ begin
110
+ while fds = IO::select([ua, os])
111
+ if fds[0].member?(ua)
112
+ buf = ua.sysread(1024);
113
+ @logger.debug("CONNECT: #{buf.bytesize} byte from User-Agent")
114
+ os.syswrite(buf)
115
+ elsif fds[0].member?(os)
116
+ buf = os.sysread(1024);
117
+ @logger.debug("CONNECT: #{buf.bytesize} byte from #{host}:#{port}")
118
+ ua.syswrite(buf)
119
+ end
120
+ end
121
+ rescue
122
+ os.close
123
+ @logger.debug("CONNECT #{host}:#{port}: closed")
124
+ end
125
+
126
+ raise WEBrick::HTTPStatus::EOFError
127
+ end
128
+ # rubocop:enable all
129
+
40
130
  def proxy_auth(req, res)
41
131
  @config[:ProxyAuthProc].call(req, res) if @config[:ProxyAuthProc]
42
132
  end
@@ -61,6 +151,25 @@ module Pacproxy
61
151
  end
62
152
  end
63
153
 
154
+ # This method is mainly from WEBrick::HTTPProxyServer.
155
+ # proxy-authenticate can be transferred from a upstream proxy server
156
+ # to a client
157
+ # see: https://github.com/ruby/ruby/blob/trunk/lib/webrick/httpproxy.rb
158
+ HOP_BY_HOP = %w( connection keep-alive upgrade
159
+ proxy-authorization te trailers transfer-encoding )
160
+ SHOULD_NOT_TRANSFER = %w( set-cookie proxy-connection )
161
+ def choose_header(src, dst)
162
+ connections = split_field(src['connection'])
163
+ src.each do |key, value|
164
+ key = key.downcase
165
+ next if HOP_BY_HOP.member?(key) || # RFC2616: 13.5.1
166
+ connections.member?(key) || # RFC2616: 14.10
167
+ SHOULD_NOT_TRANSFER.member?(key) # pragmatics
168
+
169
+ dst[key] = value
170
+ end
171
+ end
172
+
64
173
  def perform_proxy_request(req, res)
65
174
  super
66
175
  accesslog(req, res)
@@ -1,4 +1,4 @@
1
1
  # Pacproxy provides http/https proxy routed with proxy.pac.
2
2
  module Pacproxy
3
- VERSION = '0.0.5'
3
+ VERSION = '0.0.6'
4
4
  end
data/lib/pacproxy.rb CHANGED
@@ -4,6 +4,7 @@ require 'pacproxy/pacproxy'
4
4
  require 'pacproxy/pac_file'
5
5
  require 'pacproxy/general_logger'
6
6
  require 'pacproxy/access_logger'
7
+ require 'pacproxy/config'
7
8
 
8
9
  # Pacproxy provides http/https proxy routed with proxy.pac.
9
10
  module Pacproxy
data/pacproxy.gemspec CHANGED
@@ -28,4 +28,5 @@ Gem::Specification.new do |spec|
28
28
 
29
29
  spec.add_development_dependency 'rubocop', '0.24.1'
30
30
  spec.add_development_dependency 'coveralls', '~> 0.7'
31
+ spec.add_development_dependency 'byebug', '~> 3.4.0'
31
32
  end
data/pacproxy.yml ADDED
@@ -0,0 +1,59 @@
1
+ # pacproxy conifguration
2
+
3
+ # daemonize: [boolean]
4
+ # eg. daemonize: true
5
+ daemonize: true
6
+
7
+ # port: [integer]
8
+ # eg. port: 3128
9
+ port: 3128
10
+
11
+ # pac_file related items
12
+ pac_file:
13
+ # pac_file > location: [string]
14
+ # absolute path is preferred
15
+ # eg. location: /opt/pacproxy/proxy.pac
16
+ # eg. location: http://example.com/proxy.pac
17
+ location: proxy.pac
18
+ # pac_file > update_interval(seconds): [integer]
19
+ # eg. update_interval: 1800
20
+ update_interval: 1800
21
+
22
+ # general log related items
23
+ general_log:
24
+ # general_log > location: [string]
25
+ # absolute path is preferred
26
+ # eg. location: /var/log/pacproxy.log
27
+ location: pacproxy.log
28
+ # general_log > log_level: [string]
29
+ # DEBUG/INFO/WARN/ERROR/FATAL
30
+ # see: http://ruby-doc.org/stdlib-2.1.2/libdoc/logger/rdoc/Logger.html
31
+ # eg. log_level: ERROR
32
+ log_level: ERROR
33
+ # general_log > log_rotate related items
34
+ log_rotate:
35
+ # general_log > log_rotate > shift_age: [integer/string]
36
+ # see: http://ruby-doc.org/stdlib-2.1.2/libdoc/logger/rdoc/Logger.html
37
+ shift_age: 7
38
+ # general_log > log_rotate > shift_size: [integer]
39
+ # see: http://ruby-doc.org/stdlib-2.1.2/libdoc/logger/rdoc/Logger.html
40
+ shift_size: 10485760 #10 * 1024 * 1024
41
+
42
+ # access log related items
43
+ access_log:
44
+ # access_log > location: [string]
45
+ # absolute path is preferred
46
+ # eg. location: /var/log/proxy_access.log
47
+ location: proxy_access.log
48
+ # access_log > format: [string]
49
+ # eg. format: "%h %l %u %t \"%r\" %s %b"
50
+ # see: http://httpd.apache.org/docs/current/en/mod/mod_log_config.html
51
+ format: "%h %l %u %t \"%r\" %s %b"
52
+ # access_log > log_rotate related items
53
+ log_rotate:
54
+ # access_log > log_rotate > shift_age: [integer/string]
55
+ # see: http://ruby-doc.org/stdlib-2.1.2/libdoc/logger/rdoc/Logger.html
56
+ shift_age: 7
57
+ # access_log > log_rotate > shift_size: [integer]
58
+ # see: http://ruby-doc.org/stdlib-2.1.2/libdoc/logger/rdoc/Logger.html
59
+ shift_size: 10485760 #10 * 1024 * 1024
data/proxy.pac CHANGED
@@ -1,3 +1,3 @@
1
1
  function FindProxyForURL(url, host) {
2
- return "PROXY localhost:3128;
2
+ return "DIRECT";
3
3
  }
@@ -3,6 +3,8 @@ require 'spec_helper'
3
3
  describe Pacproxy::AccessLogger do
4
4
  describe 'accesslog' do
5
5
  it 'write Apache common log format' do
6
+ Pacproxy::Config.instance.update('pacproxy.yml')
7
+
6
8
  log = Pacproxy::AccessLogger.instance
7
9
  log.logger = ''
8
10
  now = Time.now
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Pacproxy::Config do
4
+ it 'store values from specified yaml file' do
5
+ c = Pacproxy::Config.instance.update('pacproxy.yml')
6
+
7
+ expect(c.config['daemonize']).to eq(true)
8
+ expect(c.config['port']).to eq(3128)
9
+ expect(c.config['pac_file']['location']).to eq('proxy.pac')
10
+ expect(c.config['general_log']['location']).to eq('pacproxy.log')
11
+ expect(c.config['access_log']['log_rotate']['shift_age']).to eq(7)
12
+ end
13
+ end
@@ -52,9 +52,10 @@ describe Pacproxy do
52
52
  end
53
53
 
54
54
  it 'transfer request to server directly' do
55
- @pacproxy_server =
56
- Pacproxy::Pacproxy.new(Port: 13_128,
57
- Proxypac: 'spec/all_direct.pac')
55
+ c = Pacproxy::Config.instance.config
56
+ c['port'] = 13_128
57
+ c['pac_file']['location'] = 'spec/all_direct.pac'
58
+ @pacproxy_server = Pacproxy::Pacproxy.new(c)
58
59
  Thread.new { @pacproxy_server.start }
59
60
  wait_server_status(@pacproxy_server, :Running)
60
61
 
@@ -67,9 +68,10 @@ describe Pacproxy do
67
68
  end
68
69
 
69
70
  it 'transfer request to server directly via HTTPS' do
70
- @pacproxy_server =
71
- Pacproxy::Pacproxy.new(Port: 13_128,
72
- Proxypac: 'spec/all_direct.pac')
71
+ c = Pacproxy::Config.instance.config
72
+ c['port'] = 13_128
73
+ c['pac_file']['location'] = 'spec/all_direct.pac'
74
+ @pacproxy_server = Pacproxy::Pacproxy.new(c)
73
75
  Thread.new { @pacproxy_server.start }
74
76
  wait_server_status(@pacproxy_server, :Running)
75
77
 
@@ -83,9 +85,10 @@ describe Pacproxy do
83
85
  end
84
86
 
85
87
  it 'transfer request to server directly with PUT method' do
86
- @pacproxy_server =
87
- Pacproxy::Pacproxy.new(Port: 13_128,
88
- Proxypac: 'spec/all_direct.pac')
88
+ c = Pacproxy::Config.instance.config
89
+ c['port'] = 13_128
90
+ c['pac_file']['location'] = 'spec/all_direct.pac'
91
+ @pacproxy_server = Pacproxy::Pacproxy.new(c)
89
92
  Thread.new { @pacproxy_server.start }
90
93
  wait_server_status(@pacproxy_server, :Running)
91
94
 
@@ -98,9 +101,10 @@ describe Pacproxy do
98
101
  end
99
102
 
100
103
  it 'transfer request to server via parent proxy' do
101
- @pacproxy_server =
102
- Pacproxy::Pacproxy.new(Port: 13_128,
103
- Proxypac: 'spec/all_proxy.pac')
104
+ c = Pacproxy::Config.instance.config
105
+ c['port'] = 13_128
106
+ c['pac_file']['location'] = 'spec/all_direct.pac'
107
+ @pacproxy_server = Pacproxy::Pacproxy.new(c)
104
108
  Thread.new { @pacproxy_server.start }
105
109
  wait_server_status(@pacproxy_server, :Running)
106
110
 
@@ -113,9 +117,10 @@ describe Pacproxy do
113
117
  end
114
118
 
115
119
  it 'transfer request to server via parent proxy partially' do
116
- @pacproxy_server =
117
- Pacproxy::Pacproxy.new(Port: 13_128,
118
- Proxypac: 'spec/partial_proxy.pac')
120
+ c = Pacproxy::Config.instance.config
121
+ c['port'] = 13_128
122
+ c['pac_file']['location'] = 'spec/partial_proxy.pac'
123
+ @pacproxy_server = Pacproxy::Pacproxy.new(c)
119
124
  Thread.new { @pacproxy_server.start }
120
125
  wait_server_status(@pacproxy_server, :Running)
121
126
 
@@ -128,9 +133,10 @@ describe Pacproxy do
128
133
  end
129
134
 
130
135
  it 'transfer request with auth to server via parent proxy' do
131
- @pacproxy_server =
132
- Pacproxy::Pacproxy.new(Port: 13_128,
133
- Proxypac: 'spec/all_proxy.pac')
136
+ c = Pacproxy::Config.instance.config
137
+ c['port'] = 13_128
138
+ c['pac_file']['location'] = 'spec/all_proxy.pac'
139
+ @pacproxy_server = Pacproxy::Pacproxy.new(c)
134
140
 
135
141
  Thread.new { @pacproxy_server.start }
136
142
  wait_server_status(@pacproxy_server, :Running)
@@ -140,11 +146,60 @@ describe Pacproxy do
140
146
  %Q(Basic #{['user01:pass01'].pack('m').delete("\n")})
141
147
  }
142
148
  }
143
- p header: header
144
149
  res = c.get('http://127.0.0.1:13080/', header)
145
150
  expect(res.status).to eq(200)
146
151
  res = c.get('http://127.0.0.1:13080/noproxy/', header)
147
152
  expect(res.status).to eq(200)
148
153
  end
154
+
155
+ it 'respond 407 when upstrem proxy respond 407 on http' do
156
+ proxy_proc = proc do |_req, resp|
157
+ resp.header.merge!('Proxy-Authenticate' => "Basic realm=\"proxy\"")
158
+ fail WEBrick::HTTPStatus::ProxyAuthenticationRequired
159
+ end
160
+
161
+ pc = @proxy_server.instance_variable_get('@config')
162
+ @proxy_server.instance_variable_set('@config',
163
+ pc.merge(ProxyAuthProc: proxy_proc))
164
+ c = Pacproxy::Config.instance.config
165
+ c['port'] = 13_128
166
+ c['pac_file']['location'] = 'spec/all_proxy.pac'
167
+ @pacproxy_server = Pacproxy::Pacproxy.new(c)
168
+
169
+ Thread.new { @pacproxy_server.start }
170
+ wait_server_status(@pacproxy_server, :Running)
171
+
172
+ c = HTTPClient.new('http://127.0.0.1:13128')
173
+ res = c.get('http://127.0.0.1:13080/')
174
+ expect(res.status).to eq(407)
175
+ expect(res.header['Proxy-Authenticate']).to eq(["Basic realm=\"proxy\""])
176
+ end
177
+
178
+ it 'respond 407 when upstrem proxy respond 407 on https' do
179
+ proxy_proc = proc do |_req, resp|
180
+ resp.header.merge!('Proxy-Authenticate' => "Basic realm=\"proxy\"")
181
+ fail WEBrick::HTTPStatus::ProxyAuthenticationRequired
182
+ end
183
+
184
+ pc = @proxy_server.instance_variable_get('@config')
185
+ @proxy_server.instance_variable_set('@config',
186
+ pc.merge(ProxyAuthProc: proxy_proc))
187
+ c = Pacproxy::Config.instance.config
188
+ c['port'] = 13_128
189
+ c['pac_file']['location'] = 'spec/all_proxy.pac'
190
+ @pacproxy_server = Pacproxy::Pacproxy.new(c)
191
+
192
+ Thread.new { @pacproxy_server.start }
193
+ wait_server_status(@pacproxy_server, :Running)
194
+
195
+ c = HTTPClient.new('http://127.0.0.1:13128')
196
+ begin
197
+ c.get('https://127.0.0.1:13080/')
198
+ rescue => e
199
+ expect(e.res.status).to eq(407)
200
+ expect(e.res.header['Proxy-Authenticate'])
201
+ .to eq(["Basic realm=\"proxy\""])
202
+ end
203
+ end
149
204
  end
150
205
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pacproxy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - OTA Hiroshi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-26 00:00:00.000000000 Z
11
+ date: 2014-09-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pac
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - ~>
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0.7'
125
+ - !ruby/object:Gem::Dependency
126
+ name: byebug
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ~>
130
+ - !ruby/object:Gem::Version
131
+ version: 3.4.0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ~>
137
+ - !ruby/object:Gem::Version
138
+ version: 3.4.0
125
139
  description: A proxy server works with proxy.pac
126
140
  email:
127
141
  - ota_h@nifty.com
@@ -139,17 +153,20 @@ files:
139
153
  - bin/pacproxy
140
154
  - lib/pacproxy.rb
141
155
  - lib/pacproxy/access_logger.rb
156
+ - lib/pacproxy/config.rb
142
157
  - lib/pacproxy/general_logger.rb
143
158
  - lib/pacproxy/loggable.rb
144
159
  - lib/pacproxy/pac_file.rb
145
160
  - lib/pacproxy/pacproxy.rb
146
161
  - lib/pacproxy/version.rb
147
162
  - pacproxy.gemspec
163
+ - pacproxy.yml
148
164
  - pacproxy/.gitignore
149
165
  - proxy.pac
150
166
  - spec/access_logger_spec.rb
151
167
  - spec/all_direct.pac
152
168
  - spec/all_proxy.pac
169
+ - spec/config_spec.rb
153
170
  - spec/loggable_spec.rb
154
171
  - spec/pac_file_spec.rb
155
172
  - spec/pacproxy_spec.rb
@@ -183,6 +200,7 @@ test_files:
183
200
  - spec/access_logger_spec.rb
184
201
  - spec/all_direct.pac
185
202
  - spec/all_proxy.pac
203
+ - spec/config_spec.rb
186
204
  - spec/loggable_spec.rb
187
205
  - spec/pac_file_spec.rb
188
206
  - spec/pacproxy_spec.rb