pacproxy 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +4 -0
- data/.rspec +2 -0
- data/.rubocop.yml +7 -0
- data/.travis.yml +11 -1
- data/README.md +29 -16
- data/bin/pacproxy +10 -0
- data/lib/pacproxy.rb +3 -0
- data/lib/pacproxy/pac_file.rb +17 -21
- data/lib/pacproxy/pacproxy.rb +17 -9
- data/lib/pacproxy/runtime.rb +40 -0
- data/lib/pacproxy/runtimes/base.rb +27 -0
- data/lib/pacproxy/runtimes/node/find.js +18 -0
- data/lib/pacproxy/runtimes/node/node.rb +138 -0
- data/lib/pacproxy/runtimes/node/package.json +15 -0
- data/lib/pacproxy/runtimes/pac/pac.rb +40 -0
- data/lib/pacproxy/util.rb +17 -0
- data/lib/pacproxy/version.rb +1 -1
- data/model/pacproxy.asta +0 -0
- data/pacproxy.gemspec +3 -0
- data/pacproxy.yml +10 -0
- data/spec/pac_file_spec.rb +13 -8
- data/spec/pacproxy_spec.rb +26 -0
- data/spec/runtime_spec.rb +15 -0
- data/spec/util_spec.rb +14 -0
- metadata +79 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a592de5e8ef2da33cd52d19f4ca3360a6204cbdf
|
4
|
+
data.tar.gz: 00e5f8e3243b2f608c40f82df2afb7d90529debd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 504b321afecb58a6b42a985df6057ec628c84ad19e8dd8a16fa81262a84a33865e6b2aa5d3432c87b905c8d48e662b3e50b08ad6929d937dc8bcbc050ff38fc7
|
7
|
+
data.tar.gz: 9422b0603fa43f68ac991f32ca19114ef9d7e0214405799fb94b11340d033f7f95fa14f40e3463292e97d980150426e1dcd7e17589618294d0f87675b513389c
|
data/.gitignore
CHANGED
@@ -25,6 +25,7 @@ build/
|
|
25
25
|
/.bundle/
|
26
26
|
/lib/bundler/man/
|
27
27
|
/vendor/
|
28
|
+
/lib/pacproxy/runtimes/node/node_modules/
|
28
29
|
|
29
30
|
# for a library or gem, you might want to ignore these files since the code is
|
30
31
|
# intended to run in multiple environments; otherwise, check them in:
|
@@ -37,3 +38,6 @@ Gemfile.lock
|
|
37
38
|
|
38
39
|
# for log files
|
39
40
|
*.log
|
41
|
+
|
42
|
+
# for backup files
|
43
|
+
*.bak
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.travis.yml
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
language: ruby
|
2
|
+
cache: bundler
|
3
|
+
|
4
|
+
before_install:
|
5
|
+
- 'test Node = "$PACPROXY_RUNTIME" && sudo apt-get update || true'
|
6
|
+
- 'test Node = "$PACPROXY_RUNTIME" && sudo apt-get install node || true'
|
7
|
+
- 'test Node = "$PACPROXY_RUNTIME" && (cd lib/pacproxy/runtimes/node ; npm install) || true'
|
2
8
|
|
3
9
|
rvm:
|
4
10
|
- 2.0.0
|
5
|
-
- 2.1.
|
11
|
+
- 2.1.4
|
12
|
+
|
13
|
+
env:
|
14
|
+
- PACPROXY_RUNTIME=Node
|
15
|
+
- PACPROXY_RUNTIME=
|
data/README.md
CHANGED
@@ -1,27 +1,23 @@
|
|
1
|
-
# Pacproxy
|
1
|
+
# Pacproxy [](https://travis-ci.org/otahi/pacproxy)[](https://coveralls.io/r/otahi/pacproxy?branch=master)[](https://codeclimate.com/github/otahi/pacproxy)[](http://badge.fury.io/rb/pacproxy)
|
2
2
|
|
3
|
-
Pacproxy provides http/https proxy
|
4
|
-
|
5
|
-
|
6
|
-
[](https://coveralls.io/r/otahi/pacproxy?branch=master)
|
7
|
-
[](https://codeclimate.com/github/otahi/pacproxy)
|
8
|
-
[](http://badge.fury.io/rb/pacproxy)
|
3
|
+
Pacproxy provides an http/https proxy server which does proxy access according with a local/remote proxy.pac.
|
4
|
+
If your user agent is behind of the corporate proxy server and it does not recognize proxy.pac,
|
5
|
+
Proxypac transfers both your Internet and Intranet access correctly.
|
9
6
|
|
10
7
|
## Usage
|
11
8
|
|
12
|
-
|
13
|
-
|
14
|
-
or
|
9
|
+
You can run pacproxy with specified proxy.pac location, running port and so on.
|
15
10
|
|
16
|
-
$ bundle exec pacproxy -
|
11
|
+
$ bundle exec pacproxy -P http://sample.org/proxy.pac -p 3128
|
17
12
|
|
18
13
|
or
|
19
14
|
|
20
|
-
$ bundle exec pacproxy -P proxy.pac -p 3128
|
15
|
+
$ bundle exec pacproxy -P /opt/pacproxy/sample-proxy.pac -p 3128
|
21
16
|
|
22
17
|
or
|
23
18
|
|
24
|
-
$ bundle exec pacproxy -
|
19
|
+
$ bundle exec pacproxy -c pacproxy.yml
|
20
|
+
|
25
21
|
|
26
22
|
## Configuration
|
27
23
|
|
@@ -37,9 +33,13 @@ Configurable items:
|
|
37
33
|
- access log
|
38
34
|
|
39
35
|
## Installation
|
36
|
+
You can select Ruby javascript runtimes or Node.js
|
40
37
|
|
41
|
-
|
38
|
+
### With a Ruby javascript runtime
|
39
|
+
Puts these lines on Gemfile, for example:
|
42
40
|
|
41
|
+
source 'https://rubygems.org'
|
42
|
+
|
43
43
|
gem 'pacproxy'
|
44
44
|
gem 'therubyracer'
|
45
45
|
|
@@ -47,16 +47,29 @@ And then execute:
|
|
47
47
|
|
48
48
|
$ bundle
|
49
49
|
|
50
|
+
### With Node.js
|
51
|
+
Install node.js runtime before this installation.
|
52
|
+
Puts these lines on Gemfile, for example:
|
53
|
+
|
54
|
+
source 'https://rubygems.org'
|
55
|
+
|
56
|
+
gem 'pacproxy'
|
57
|
+
|
58
|
+
And then execute:
|
59
|
+
|
60
|
+
$ bundle
|
61
|
+
$ bundle exec pacproxy --npminstall
|
62
|
+
|
50
63
|
## Requirements
|
51
64
|
|
52
65
|
Before or After installing the `pacproxy` gem,
|
53
|
-
you need to install a JavaScript runtime
|
54
|
-
(see [pac](https://github.com/samuelkadolph/ruby-pac/blob/master/README.md)):
|
66
|
+
you need to install a JavaScript runtime.:
|
55
67
|
|
56
68
|
* [therubyracer](https://rubygems.org/gems/therubyracer) Google V8 embedded within Ruby
|
57
69
|
* [therubyrhino](https://rubygems.org/gems/therubyrhino/) Mozilla Rhino embedded within JRuby
|
58
70
|
* [johnson](https://rubygems.org/gems/johnson/) Mozilla SpiderMonkey embedded within Ruby 1.8
|
59
71
|
* [mustang](https://rubygems.org/gems/mustang/) Mustang V8 embedded within Ruby
|
72
|
+
* [Node.js](http://nodejs.org/) Node.js runtime
|
60
73
|
|
61
74
|
## Contributing
|
62
75
|
|
data/bin/pacproxy
CHANGED
@@ -25,6 +25,16 @@ OptionParser.new do |o|
|
|
25
25
|
o.on('-P PROXYPAC', String, 'specify proxy.pac location') do |pac|
|
26
26
|
config.merge!('pac_file' => { 'location' => pac })
|
27
27
|
end
|
28
|
+
o.on('--npminstall', 'install node libraries') do
|
29
|
+
fail 'No npm found!' unless Pacproxy::Util.which('npm')
|
30
|
+
|
31
|
+
node_dir = File.join([File.dirname(__FILE__)] +
|
32
|
+
%w(.. lib pacproxy runtimes node))
|
33
|
+
FileUtils.cd(node_dir) do
|
34
|
+
system('npm install')
|
35
|
+
end
|
36
|
+
exit
|
37
|
+
end
|
28
38
|
o.on('-h', 'show this help') do
|
29
39
|
puts o
|
30
40
|
exit
|
data/lib/pacproxy.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'pacproxy/version'
|
2
|
+
require 'pacproxy/util'
|
2
3
|
require 'pacproxy/loggable'
|
3
4
|
require 'pacproxy/pacproxy'
|
4
5
|
require 'pacproxy/pac_file'
|
@@ -6,6 +7,8 @@ require 'pacproxy/general_logger'
|
|
6
7
|
require 'pacproxy/access_logger'
|
7
8
|
require 'pacproxy/config'
|
8
9
|
|
10
|
+
require 'pacproxy/runtime'
|
11
|
+
|
9
12
|
# Pacproxy provides http/https proxy routed with proxy.pac.
|
10
13
|
module Pacproxy
|
11
14
|
end
|
data/lib/pacproxy/pac_file.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'pacproxy'
|
2
|
-
require 'pac'
|
3
2
|
require 'uri'
|
4
3
|
require 'thread'
|
5
4
|
|
@@ -8,42 +7,39 @@ module Pacproxy
|
|
8
7
|
class PacFile
|
9
8
|
include Loggable
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
def initialize(file_location, update_interval = 1800)
|
11
|
+
begin
|
12
|
+
require 'pac'
|
13
|
+
rescue RuntimeUnavailable
|
14
|
+
info('No javascript runtime found for pac')
|
15
|
+
end
|
16
|
+
@file_location = file_location
|
17
|
+
@update_interval = update_interval
|
18
|
+
@runtime = Runtime.new
|
19
|
+
begin_update
|
14
20
|
end
|
15
21
|
|
16
|
-
def
|
17
|
-
@
|
18
|
-
begin_update(file_location, update_interval)
|
22
|
+
def shutdown
|
23
|
+
@runtime.shutdown
|
19
24
|
end
|
20
25
|
|
21
26
|
def find(uri)
|
22
|
-
return 'DIRECT' unless @
|
23
|
-
|
24
|
-
@pac.find(uri)
|
25
|
-
end
|
27
|
+
return 'DIRECT' unless @runtime
|
28
|
+
@runtime.find(uri)
|
26
29
|
end
|
27
30
|
|
28
31
|
private
|
29
32
|
|
30
|
-
def begin_update
|
33
|
+
def begin_update
|
31
34
|
is_updated = false
|
32
35
|
Thread.new do
|
33
36
|
loop do
|
34
|
-
update(file_location)
|
37
|
+
@runtime.update(@file_location)
|
35
38
|
is_updated = true
|
36
|
-
sleep(update_interval)
|
39
|
+
sleep(@update_interval)
|
37
40
|
end
|
38
41
|
end
|
39
42
|
sleep 0.01 until is_updated
|
40
43
|
end
|
41
|
-
|
42
|
-
def update(file_location)
|
43
|
-
tmp = PAC.load(file_location)
|
44
|
-
@pac = tmp if @pac.nil? || @pac.source != tmp.source
|
45
|
-
rescue => e
|
46
|
-
error("#{file_location} update error: #{e}")
|
47
|
-
end
|
48
44
|
end
|
49
45
|
end
|
data/lib/pacproxy/pacproxy.rb
CHANGED
@@ -9,12 +9,18 @@ module Pacproxy
|
|
9
9
|
|
10
10
|
def initialize(config = {}, default = WEBrick::Config::HTTP)
|
11
11
|
super({ Port: config['port'], Logger: general_logger }, default)
|
12
|
+
@auth = config['auth']
|
12
13
|
return unless config['pac_file'] && config['pac_file']['location']
|
13
14
|
|
14
15
|
@pac = PacFile.new(config['pac_file']['location'],
|
15
16
|
config['pac_file']['update_interval'])
|
16
17
|
end
|
17
18
|
|
19
|
+
def shutdown
|
20
|
+
@pac.shutdown
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
18
24
|
def proxy_uri(req, res)
|
19
25
|
super(req, res)
|
20
26
|
return unless @pac
|
@@ -27,16 +33,18 @@ module Pacproxy
|
|
27
33
|
def create_proxy_uri(proxy, header)
|
28
34
|
return nil unless proxy
|
29
35
|
return URI.parse("http://#{proxy}") unless
|
30
|
-
header.key?('proxy-authorization')
|
31
|
-
|
32
|
-
auth
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
36
|
+
@auth || header.key?('proxy-authorization')
|
37
|
+
|
38
|
+
if @auth
|
39
|
+
basic_auth = "#{@auth['user']}:#{@auth['password']}"
|
40
|
+
elsif header.key?('proxy-authorization')
|
41
|
+
auth = header['proxy-authorization'][0]
|
42
|
+
pattern = /basic (\S+)/i
|
43
|
+
basic_auth = pattern.match(auth)[1].unpack('m').first
|
44
|
+
header.delete('proxy-authorization')
|
45
|
+
end
|
38
46
|
|
39
|
-
URI.parse("http://#{basic_auth
|
47
|
+
URI.parse("http://#{basic_auth}@#{proxy}")
|
40
48
|
end
|
41
49
|
|
42
50
|
# This method is mainly from WEBrick::HTTPProxyServer.
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'pacproxy'
|
2
|
+
require 'pacproxy/runtimes/node/node'
|
3
|
+
require 'pacproxy/runtimes/pac/pac'
|
4
|
+
|
5
|
+
module Pacproxy
|
6
|
+
# Pacproxy::Runtime represet runtime
|
7
|
+
class Runtime
|
8
|
+
include Loggable
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@runtime = autodetect
|
12
|
+
end
|
13
|
+
|
14
|
+
def shutdown
|
15
|
+
@runtime.shutdown
|
16
|
+
end
|
17
|
+
|
18
|
+
def find(url)
|
19
|
+
@runtime.find(url)
|
20
|
+
end
|
21
|
+
|
22
|
+
def update(file_location)
|
23
|
+
@runtime.update(file_location)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def autodetect
|
29
|
+
name = ENV['PACPROXY_RUNTIME']
|
30
|
+
return Runtimes::Node.runtime if name || /Node/ =~ name
|
31
|
+
|
32
|
+
ENV['JS_RUNTIME'] = name
|
33
|
+
return Runtimes::Pac.runtime if Runtimes::Pac.runtime
|
34
|
+
return Runtimes::Node.runtime if Runtimes::Node.runtime
|
35
|
+
|
36
|
+
fail(RuntimeUnavailable,
|
37
|
+
'No runtime supporting proxy.pac')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'pacproxy'
|
2
|
+
|
3
|
+
module Pacproxy
|
4
|
+
module Runtimes
|
5
|
+
# Pacproxy::Runtimes::Basee represet basic runtime
|
6
|
+
class Base
|
7
|
+
include Loggable
|
8
|
+
|
9
|
+
attr_reader :source
|
10
|
+
|
11
|
+
def self.runtime
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
end
|
16
|
+
|
17
|
+
def shutdown
|
18
|
+
end
|
19
|
+
|
20
|
+
def update(_file_location)
|
21
|
+
end
|
22
|
+
|
23
|
+
def find(_url)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
var dnode = require('dnode');
|
2
|
+
var pac = require('pac-resolver');
|
3
|
+
var source;
|
4
|
+
|
5
|
+
process.on('uncaughtException', function(err){});
|
6
|
+
|
7
|
+
var server = dnode({
|
8
|
+
find : function(source, uri, host, cb) {
|
9
|
+
var FindProxyForURL = pac(source);
|
10
|
+
FindProxyForURL(uri, host, function (err, res) {
|
11
|
+
if (err) res = "DIRECT";
|
12
|
+
cb(res);
|
13
|
+
});
|
14
|
+
}
|
15
|
+
});
|
16
|
+
|
17
|
+
var port = process.argv[2];
|
18
|
+
server.listen(port);
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'pacproxy'
|
2
|
+
require 'pacproxy/runtimes/base'
|
3
|
+
|
4
|
+
require 'open-uri'
|
5
|
+
require 'dnode'
|
6
|
+
require 'thread'
|
7
|
+
require 'os'
|
8
|
+
|
9
|
+
module Pacproxy
|
10
|
+
module Runtimes
|
11
|
+
# Pacproxy::Runtimes::Node represet node js runtime
|
12
|
+
class Node < Base
|
13
|
+
include Loggable
|
14
|
+
|
15
|
+
TIMEOUT_JS_CALL = 0.5
|
16
|
+
TIMEOUT_JS_SERVER = 5
|
17
|
+
attr_reader :source
|
18
|
+
|
19
|
+
def self.runtime
|
20
|
+
if Util.which('node').nil?
|
21
|
+
error('No PAC supported runtime')
|
22
|
+
fail(RuntimeUnavailable,
|
23
|
+
'No PAC supported runtime')
|
24
|
+
end
|
25
|
+
new
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
js = File.join(File.dirname(__FILE__), 'find.js')
|
30
|
+
|
31
|
+
retries = 3
|
32
|
+
begin
|
33
|
+
Timeout.timeout(TIMEOUT_JS_SERVER) do
|
34
|
+
server = TCPServer.new('127.0.0.1', 0)
|
35
|
+
@port = server.addr[1]
|
36
|
+
server.close
|
37
|
+
if OS.windows?
|
38
|
+
@server_pid = start_server
|
39
|
+
else
|
40
|
+
@server_pid = fork { exec('node', js, @port.to_s) }
|
41
|
+
Process.detach(@server_pid)
|
42
|
+
end
|
43
|
+
sleep 0.01 until port_open?
|
44
|
+
end
|
45
|
+
rescue Timeout::Error
|
46
|
+
shutdown
|
47
|
+
if retries > 0
|
48
|
+
retries -= 1
|
49
|
+
lwarn('Timeout. Initialize Node.js server.')
|
50
|
+
retry
|
51
|
+
else
|
52
|
+
error('Gave up to retry Initialize Node.js server.')
|
53
|
+
raise 'Gave up to retry Initialize Node.js server.'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def shutdown
|
59
|
+
if OS.windows?
|
60
|
+
stop_server(@server_pid)
|
61
|
+
else
|
62
|
+
Process.kill(:INT, @server_pid)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def update(file_location)
|
67
|
+
@source = open(file_location, proxy: false).read
|
68
|
+
rescue
|
69
|
+
@source = nil
|
70
|
+
end
|
71
|
+
|
72
|
+
def find(url)
|
73
|
+
return 'DIRECT' unless @source
|
74
|
+
uri = URI.parse(url)
|
75
|
+
call_find(uri)
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def port_open?
|
81
|
+
Timeout.timeout(TIMEOUT_JS_CALL) do
|
82
|
+
begin
|
83
|
+
TCPSocket.new('127.0.0.1', @port).close
|
84
|
+
return true
|
85
|
+
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
|
86
|
+
return false
|
87
|
+
end
|
88
|
+
end
|
89
|
+
rescue Timeout::Error
|
90
|
+
false
|
91
|
+
end
|
92
|
+
|
93
|
+
def call_find(uri, retries = 3)
|
94
|
+
proxy = nil
|
95
|
+
begin
|
96
|
+
thread = Thread.new do
|
97
|
+
DNode.new.connect('127.0.0.1', @port) do |remote|
|
98
|
+
remote.find(@source, uri, uri.host,
|
99
|
+
proc do |p|
|
100
|
+
proxy = p
|
101
|
+
EM.stop
|
102
|
+
end)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
thread.join(TIMEOUT_JS_CALL)
|
106
|
+
proxy
|
107
|
+
rescue Timeout::Error
|
108
|
+
if retries > 0
|
109
|
+
retries -= 1
|
110
|
+
lwarn('Timeout. Retring call_find.')
|
111
|
+
retry
|
112
|
+
else
|
113
|
+
error('Gave up Retry call_find.')
|
114
|
+
nil
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def rand_string
|
120
|
+
(0...16).map { ('a'..'z').to_a[rand(26)] }.join
|
121
|
+
end
|
122
|
+
|
123
|
+
def start_server
|
124
|
+
require 'win32/process'
|
125
|
+
Process.create(
|
126
|
+
app_name: Util.which('node'),
|
127
|
+
creation_flags: Process::DETACHED_PROCESS
|
128
|
+
)
|
129
|
+
end
|
130
|
+
|
131
|
+
def stop_server(server_info)
|
132
|
+
require 'win32/process'
|
133
|
+
return unless server_info || server_info.respond_to?(:process_id)
|
134
|
+
Process.kill('ExitProcess', [server_info.process_id])
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
{
|
2
|
+
"name": "pacproxy",
|
3
|
+
"description": "A proxy server works with proxy.pac",
|
4
|
+
"repository": {
|
5
|
+
"type": "git",
|
6
|
+
"url": "https://github.com/otahi/pacproxy.git"
|
7
|
+
},
|
8
|
+
"dependencies": {
|
9
|
+
"dnode": "^1.2.0",
|
10
|
+
"pac-resolver": "^1.2.2"
|
11
|
+
},
|
12
|
+
"author": "Hiroshi OTA",
|
13
|
+
"license": "MIT",
|
14
|
+
"readme": "See: https://github.com/otahi/pacproxy"
|
15
|
+
}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'pacproxy'
|
2
|
+
require 'pacproxy/runtimes/base'
|
3
|
+
|
4
|
+
require 'open-uri'
|
5
|
+
require 'thread'
|
6
|
+
|
7
|
+
module Pacproxy
|
8
|
+
module Runtimes
|
9
|
+
# Pacproxy::Runtimes::Pac represent Pac
|
10
|
+
class Pac < Base
|
11
|
+
include Loggable
|
12
|
+
|
13
|
+
attr_reader :source
|
14
|
+
|
15
|
+
@js_lock = Mutex.new
|
16
|
+
class << self
|
17
|
+
attr_reader :js_lock
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.runtime
|
21
|
+
PAC.runtime
|
22
|
+
new
|
23
|
+
end
|
24
|
+
|
25
|
+
def find(url)
|
26
|
+
return 'DIRECT' unless @pac
|
27
|
+
Pac.js_lock.synchronize do
|
28
|
+
@pac.find(url)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def update(file_location)
|
33
|
+
tmp = PAC.load(file_location)
|
34
|
+
@pac = tmp if @pac.nil? || @pac.source != tmp.source
|
35
|
+
rescue => e
|
36
|
+
error("#{file_location} update error: #{e}")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'pacproxy'
|
2
|
+
|
3
|
+
module Pacproxy
|
4
|
+
# Pacproxy::PacUtil is utility
|
5
|
+
class Util
|
6
|
+
def self.which(cmd)
|
7
|
+
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
8
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
9
|
+
exts.each do |ext|
|
10
|
+
exe = File.join(path, "#{cmd}#{ext}")
|
11
|
+
return exe if File.executable?(exe) && !File.directory?(exe)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
nil
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/pacproxy/version.rb
CHANGED
data/model/pacproxy.asta
ADDED
Binary file
|
data/pacproxy.gemspec
CHANGED
@@ -19,6 +19,9 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_dependency 'pac', '~> 1.0.0'
|
22
|
+
spec.add_dependency 'dnode', '~> 0.0.2'
|
23
|
+
spec.add_dependency 'os', '~> 0.9.6'
|
24
|
+
spec.add_dependency 'win32-process', '~> 0.7.4'
|
22
25
|
|
23
26
|
spec.add_development_dependency 'bundler', '~> 1.6'
|
24
27
|
spec.add_development_dependency 'rspec', '~> 3.0.0'
|
data/pacproxy.yml
CHANGED
@@ -19,6 +19,16 @@ pac_file:
|
|
19
19
|
# eg. update_interval: 1800
|
20
20
|
update_interval: 1800
|
21
21
|
|
22
|
+
# upstream proxy authorization related items
|
23
|
+
# auth > user: [string]
|
24
|
+
# user name for upstream proxy server
|
25
|
+
# auth > password: [string]
|
26
|
+
# password for upstream proxy server
|
27
|
+
# eg.
|
28
|
+
# auth:
|
29
|
+
# user: user100
|
30
|
+
# password: abcd1234
|
31
|
+
|
22
32
|
# general log related items
|
23
33
|
general_log:
|
24
34
|
# general_log > location: [string]
|
data/spec/pac_file_spec.rb
CHANGED
@@ -1,24 +1,29 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Pacproxy::PacFile do
|
4
|
+
after(:each) do
|
5
|
+
@pac_file.shutdown
|
6
|
+
end
|
7
|
+
|
4
8
|
describe 'PacFile#find' do
|
5
9
|
it 'returns proxyurl in pac file' do
|
6
|
-
pac_file = Pacproxy::PacFile.new('spec/all_proxy.pac')
|
7
|
-
expect(pac_file.find('http://sample.org/')).to eq('PROXY localhost:13081')
|
10
|
+
@pac_file = Pacproxy::PacFile.new('spec/all_proxy.pac')
|
11
|
+
expect(@pac_file.find('http://sample.org/')).to eq('PROXY localhost:13081')
|
8
12
|
end
|
9
13
|
it 'returns DIRECT when no pac file' do
|
10
|
-
pac_file = Pacproxy::PacFile.new('')
|
11
|
-
expect(pac_file.find('http://sample.org/')).to eq('DIRECT')
|
14
|
+
@pac_file = Pacproxy::PacFile.new('')
|
15
|
+
expect(@pac_file.find('http://sample.org/')).to eq('DIRECT')
|
12
16
|
end
|
13
17
|
end
|
14
18
|
describe 'PacFile#update' do
|
15
19
|
it 'has same pac file if no change' do
|
16
|
-
pac_file = Pacproxy::PacFile.new('spec/all_proxy.pac', 0.01)
|
17
|
-
expect(pac_file
|
20
|
+
@pac_file = Pacproxy::PacFile.new('spec/all_proxy.pac', 0.01)
|
21
|
+
expect(@pac_file.instance_variable_get('@runtime'))
|
22
|
+
.to receive(:update).at_least(2).times
|
18
23
|
|
19
|
-
first_pac = pac_file.instance_variable_get(:@pac)
|
24
|
+
first_pac = @pac_file.instance_variable_get(:@pac)
|
20
25
|
sleep 0.2
|
21
|
-
second_pac = pac_file.instance_variable_get(:@pac)
|
26
|
+
second_pac = @pac_file.instance_variable_get(:@pac)
|
22
27
|
expect(second_pac).to eq(first_pac)
|
23
28
|
end
|
24
29
|
end
|
data/spec/pacproxy_spec.rb
CHANGED
@@ -152,6 +152,32 @@ describe Pacproxy do
|
|
152
152
|
expect(res.status).to eq(200)
|
153
153
|
end
|
154
154
|
|
155
|
+
it 'transfer request with overridden auth to server via parent proxy' do
|
156
|
+
auth = nil
|
157
|
+
proxy_proc = proc do |req, _resp|
|
158
|
+
auth = req.header['proxy-authorization']
|
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
|
+
|
165
|
+
c = Pacproxy::Config.instance.config
|
166
|
+
c['port'] = 13_128
|
167
|
+
c['pac_file']['location'] = 'spec/partial_proxy.pac'
|
168
|
+
c['auth'] = { 'user' => 'user01', 'password' => 'pass01' }
|
169
|
+
|
170
|
+
@pacproxy_server = Pacproxy::Pacproxy.new(c)
|
171
|
+
Thread.new { @pacproxy_server.start }
|
172
|
+
wait_server_status(@pacproxy_server, :Running)
|
173
|
+
|
174
|
+
c = HTTPClient.new('http://127.0.0.1:13128')
|
175
|
+
res = c.get('http://127.0.0.1:13080/')
|
176
|
+
expect(res.status).to eq(200)
|
177
|
+
expect(auth)
|
178
|
+
.to eq([%Q(Basic #{['user01:pass01'].pack('m').delete("\n")})])
|
179
|
+
end
|
180
|
+
|
155
181
|
it 'respond 407 when upstrem proxy respond 407 on http' do
|
156
182
|
proxy_proc = proc do |_req, resp|
|
157
183
|
resp.header.merge!('Proxy-Authenticate' => "Basic realm=\"proxy\"")
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Pacproxy::Runtime do
|
4
|
+
|
5
|
+
after(:each) do
|
6
|
+
@runtime.shutdown
|
7
|
+
end
|
8
|
+
|
9
|
+
describe 'Runtime#new' do
|
10
|
+
it 'returns Pacproxy::Runtime' do
|
11
|
+
@runtime = Pacproxy::Runtime.new
|
12
|
+
expect(@runtime).to be_kind_of(Pacproxy::Runtime)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/spec/util_spec.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Pacproxy::Util do
|
4
|
+
describe 'Util#which' do
|
5
|
+
it 'return "/bin/sh" when "sh" is given' do
|
6
|
+
l = Pacproxy::Util.which('sh')
|
7
|
+
expect(l).to eq('/bin/sh')
|
8
|
+
end
|
9
|
+
it 'return nil when "unknown command" is given' do
|
10
|
+
l = Pacproxy::Util.which('unknown command')
|
11
|
+
expect(l).to be_nil
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
metadata
CHANGED
@@ -1,97 +1,139 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pacproxy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
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-
|
11
|
+
date: 2014-11-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pac
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 1.0.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 1.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: dnode
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.0.2
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.0.2
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: os
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.9.6
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.9.6
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: win32-process
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.7.4
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.7.4
|
27
69
|
- !ruby/object:Gem::Dependency
|
28
70
|
name: bundler
|
29
71
|
requirement: !ruby/object:Gem::Requirement
|
30
72
|
requirements:
|
31
|
-
- - ~>
|
73
|
+
- - "~>"
|
32
74
|
- !ruby/object:Gem::Version
|
33
75
|
version: '1.6'
|
34
76
|
type: :development
|
35
77
|
prerelease: false
|
36
78
|
version_requirements: !ruby/object:Gem::Requirement
|
37
79
|
requirements:
|
38
|
-
- - ~>
|
80
|
+
- - "~>"
|
39
81
|
- !ruby/object:Gem::Version
|
40
82
|
version: '1.6'
|
41
83
|
- !ruby/object:Gem::Dependency
|
42
84
|
name: rspec
|
43
85
|
requirement: !ruby/object:Gem::Requirement
|
44
86
|
requirements:
|
45
|
-
- - ~>
|
87
|
+
- - "~>"
|
46
88
|
- !ruby/object:Gem::Version
|
47
89
|
version: 3.0.0
|
48
90
|
type: :development
|
49
91
|
prerelease: false
|
50
92
|
version_requirements: !ruby/object:Gem::Requirement
|
51
93
|
requirements:
|
52
|
-
- - ~>
|
94
|
+
- - "~>"
|
53
95
|
- !ruby/object:Gem::Version
|
54
96
|
version: 3.0.0
|
55
97
|
- !ruby/object:Gem::Dependency
|
56
98
|
name: rake
|
57
99
|
requirement: !ruby/object:Gem::Requirement
|
58
100
|
requirements:
|
59
|
-
- - ~>
|
101
|
+
- - "~>"
|
60
102
|
- !ruby/object:Gem::Version
|
61
103
|
version: 10.3.2
|
62
104
|
type: :development
|
63
105
|
prerelease: false
|
64
106
|
version_requirements: !ruby/object:Gem::Requirement
|
65
107
|
requirements:
|
66
|
-
- - ~>
|
108
|
+
- - "~>"
|
67
109
|
- !ruby/object:Gem::Version
|
68
110
|
version: 10.3.2
|
69
111
|
- !ruby/object:Gem::Dependency
|
70
112
|
name: httpclient
|
71
113
|
requirement: !ruby/object:Gem::Requirement
|
72
114
|
requirements:
|
73
|
-
- - ~>
|
115
|
+
- - "~>"
|
74
116
|
- !ruby/object:Gem::Version
|
75
117
|
version: 2.4.0
|
76
118
|
type: :development
|
77
119
|
prerelease: false
|
78
120
|
version_requirements: !ruby/object:Gem::Requirement
|
79
121
|
requirements:
|
80
|
-
- - ~>
|
122
|
+
- - "~>"
|
81
123
|
- !ruby/object:Gem::Version
|
82
124
|
version: 2.4.0
|
83
125
|
- !ruby/object:Gem::Dependency
|
84
126
|
name: therubyracer
|
85
127
|
requirement: !ruby/object:Gem::Requirement
|
86
128
|
requirements:
|
87
|
-
- - ~>
|
129
|
+
- - "~>"
|
88
130
|
- !ruby/object:Gem::Version
|
89
131
|
version: 0.12.1
|
90
132
|
type: :development
|
91
133
|
prerelease: false
|
92
134
|
version_requirements: !ruby/object:Gem::Requirement
|
93
135
|
requirements:
|
94
|
-
- - ~>
|
136
|
+
- - "~>"
|
95
137
|
- !ruby/object:Gem::Version
|
96
138
|
version: 0.12.1
|
97
139
|
- !ruby/object:Gem::Dependency
|
@@ -112,28 +154,28 @@ dependencies:
|
|
112
154
|
name: coveralls
|
113
155
|
requirement: !ruby/object:Gem::Requirement
|
114
156
|
requirements:
|
115
|
-
- - ~>
|
157
|
+
- - "~>"
|
116
158
|
- !ruby/object:Gem::Version
|
117
159
|
version: '0.7'
|
118
160
|
type: :development
|
119
161
|
prerelease: false
|
120
162
|
version_requirements: !ruby/object:Gem::Requirement
|
121
163
|
requirements:
|
122
|
-
- - ~>
|
164
|
+
- - "~>"
|
123
165
|
- !ruby/object:Gem::Version
|
124
166
|
version: '0.7'
|
125
167
|
- !ruby/object:Gem::Dependency
|
126
168
|
name: byebug
|
127
169
|
requirement: !ruby/object:Gem::Requirement
|
128
170
|
requirements:
|
129
|
-
- - ~>
|
171
|
+
- - "~>"
|
130
172
|
- !ruby/object:Gem::Version
|
131
173
|
version: 3.4.0
|
132
174
|
type: :development
|
133
175
|
prerelease: false
|
134
176
|
version_requirements: !ruby/object:Gem::Requirement
|
135
177
|
requirements:
|
136
|
-
- - ~>
|
178
|
+
- - "~>"
|
137
179
|
- !ruby/object:Gem::Version
|
138
180
|
version: 3.4.0
|
139
181
|
description: A proxy server works with proxy.pac
|
@@ -144,8 +186,10 @@ executables:
|
|
144
186
|
extensions: []
|
145
187
|
extra_rdoc_files: []
|
146
188
|
files:
|
147
|
-
- .gitignore
|
148
|
-
- .
|
189
|
+
- ".gitignore"
|
190
|
+
- ".rspec"
|
191
|
+
- ".rubocop.yml"
|
192
|
+
- ".travis.yml"
|
149
193
|
- Gemfile
|
150
194
|
- LICENSE
|
151
195
|
- README.md
|
@@ -158,7 +202,15 @@ files:
|
|
158
202
|
- lib/pacproxy/loggable.rb
|
159
203
|
- lib/pacproxy/pac_file.rb
|
160
204
|
- lib/pacproxy/pacproxy.rb
|
205
|
+
- lib/pacproxy/runtime.rb
|
206
|
+
- lib/pacproxy/runtimes/base.rb
|
207
|
+
- lib/pacproxy/runtimes/node/find.js
|
208
|
+
- lib/pacproxy/runtimes/node/node.rb
|
209
|
+
- lib/pacproxy/runtimes/node/package.json
|
210
|
+
- lib/pacproxy/runtimes/pac/pac.rb
|
211
|
+
- lib/pacproxy/util.rb
|
161
212
|
- lib/pacproxy/version.rb
|
213
|
+
- model/pacproxy.asta
|
162
214
|
- pacproxy.gemspec
|
163
215
|
- pacproxy.yml
|
164
216
|
- pacproxy/.gitignore
|
@@ -171,7 +223,9 @@ files:
|
|
171
223
|
- spec/pac_file_spec.rb
|
172
224
|
- spec/pacproxy_spec.rb
|
173
225
|
- spec/partial_proxy.pac
|
226
|
+
- spec/runtime_spec.rb
|
174
227
|
- spec/spec_helper.rb
|
228
|
+
- spec/util_spec.rb
|
175
229
|
homepage: https://github.com/otahi/pacproxy
|
176
230
|
licenses:
|
177
231
|
- MIT
|
@@ -182,17 +236,17 @@ require_paths:
|
|
182
236
|
- lib
|
183
237
|
required_ruby_version: !ruby/object:Gem::Requirement
|
184
238
|
requirements:
|
185
|
-
- -
|
239
|
+
- - ">="
|
186
240
|
- !ruby/object:Gem::Version
|
187
241
|
version: '0'
|
188
242
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
189
243
|
requirements:
|
190
|
-
- -
|
244
|
+
- - ">="
|
191
245
|
- !ruby/object:Gem::Version
|
192
246
|
version: '0'
|
193
247
|
requirements: []
|
194
248
|
rubyforge_project:
|
195
|
-
rubygems_version: 2.
|
249
|
+
rubygems_version: 2.2.2
|
196
250
|
signing_key:
|
197
251
|
specification_version: 4
|
198
252
|
summary: A proxy server works with proxy.pac
|
@@ -205,4 +259,6 @@ test_files:
|
|
205
259
|
- spec/pac_file_spec.rb
|
206
260
|
- spec/pacproxy_spec.rb
|
207
261
|
- spec/partial_proxy.pac
|
262
|
+
- spec/runtime_spec.rb
|
208
263
|
- spec/spec_helper.rb
|
264
|
+
- spec/util_spec.rb
|