proxy_pac_rb 0.3.8 → 0.4.0
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/.rubocop.yml +1 -0
- data/.travis.yml +2 -1
- data/Gemfile +13 -13
- data/Gemfile.lock +84 -58
- data/README.md +40 -13
- data/features/check_proxy_pac.feature +31 -0
- data/features/compress_proxy_pac.feature +3 -16
- data/features/resolve_proxy.feature +1 -1
- data/lib/proxy_pac_rb/cli/compress_proxy_pac.rb +25 -11
- data/lib/proxy_pac_rb/cli/find_proxy.rb +13 -8
- data/lib/proxy_pac_rb/cli/lint.rb +11 -0
- data/lib/proxy_pac_rb/cli/lint_proxy_pac.rb +37 -0
- data/lib/proxy_pac_rb/cli/runner.rb +5 -0
- data/lib/proxy_pac_rb/cli/shared.rb +4 -0
- data/lib/proxy_pac_rb/cli_validator.rb +14 -0
- data/lib/proxy_pac_rb/errors.rb +19 -0
- data/lib/proxy_pac_rb/javascript.rb +19 -0
- data/lib/proxy_pac_rb/main.rb +22 -0
- data/lib/proxy_pac_rb/parser.rb +32 -21
- data/lib/proxy_pac_rb/proxy_pac.rb +10 -20
- data/lib/proxy_pac_rb/proxy_pac_compressor.rb +9 -0
- data/lib/proxy_pac_rb/proxy_pac_dumper.rb +65 -0
- data/lib/proxy_pac_rb/proxy_pac_file.rb +20 -3
- data/lib/proxy_pac_rb/proxy_pac_linter.rb +82 -0
- data/lib/proxy_pac_rb/proxy_pac_loader.rb +98 -0
- data/lib/proxy_pac_rb/proxy_pac_parser.rb +41 -0
- data/lib/proxy_pac_rb/rack/proxy_pac_compressor.rb +68 -0
- data/lib/proxy_pac_rb/rack/proxy_pac_linter.rb +66 -0
- data/lib/proxy_pac_rb/runtimes/rubyracer.rb +2 -2
- data/lib/proxy_pac_rb/runtimes/rubyrhino.rb +2 -2
- data/lib/proxy_pac_rb/runtimes.rb +3 -3
- data/lib/proxy_pac_rb/version.rb +1 -1
- data/lib/proxy_pac_rb.rb +10 -3
- data/proxy_pac_rb.gemspec +2 -0
- data/spec/api_spec.rb +207 -0
- data/spec/parser_spec.rb +66 -53
- data/spec/rack/proxy_pac_compressor_spec.rb +59 -0
- data/spec/rack/proxy_pac_linter_spec.rb +65 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/matchers/file.rb +23 -0
- data/spec/support/rack_test.rb +1 -0
- data/spec/support/rspec.rb +3 -1
- data/spec/support/webmock.rb +1 -0
- metadata +30 -12
- data/features/support/fixtures.rb +0 -15
- data/lib/proxy_pac_rb/cli.rb +0 -75
- data/lib/proxy_pac_rb/file.rb +0 -21
- data/lib/proxy_pac_rb/javascript_compressor.rb +0 -9
- data/lib/proxy_pac_rb/proxy_pac_template +0 -39
- data/spec/file_spec.rb +0 -45
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module ProxyPacRb
|
3
|
+
module Cli
|
4
|
+
# Find proxy for url
|
5
|
+
class LintProxyPac < Thor::Group
|
6
|
+
include Shared
|
7
|
+
|
8
|
+
class_option :proxy_pac, type: :array, desc: 'Proxy.pac-file(s)', aliases: '-p', required: true
|
9
|
+
|
10
|
+
def pre_init
|
11
|
+
enable_debug_mode
|
12
|
+
end
|
13
|
+
|
14
|
+
def set_variables
|
15
|
+
@proxy_pacs = options[:proxy_pac].map { |p| ProxyPacFile.new source: p }
|
16
|
+
@loader = ProxyPacLoader.new
|
17
|
+
@linter = ProxyPacLinter.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_proxy_pac
|
21
|
+
@proxy_pacs.each do |p|
|
22
|
+
@loader.load(p)
|
23
|
+
@linter.lint(p)
|
24
|
+
|
25
|
+
if p.valid?
|
26
|
+
$stderr.puts %(proxy.pac "#{p.source}" is of type #{p.type} and is valid.)
|
27
|
+
true
|
28
|
+
else
|
29
|
+
$stderr.puts %(proxy.pac "#{p.source}" is of type #{p.type} and is invalid.)
|
30
|
+
|
31
|
+
false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -7,6 +7,8 @@ module ProxyPacRb
|
|
7
7
|
map '-v' => :version
|
8
8
|
map '--version' => :version
|
9
9
|
|
10
|
+
class_option :debug_mode, type: :boolean, default: false, desc: 'Enable debug mode'
|
11
|
+
|
10
12
|
desc 'find', 'Find something'
|
11
13
|
subcommand 'find', Find
|
12
14
|
|
@@ -16,6 +18,9 @@ module ProxyPacRb
|
|
16
18
|
desc 'show', 'Show something'
|
17
19
|
subcommand 'show', Show
|
18
20
|
|
21
|
+
desc 'lint', 'Lint something'
|
22
|
+
subcommand 'lint', Lint
|
23
|
+
|
19
24
|
desc 'version', 'version', hide: true
|
20
25
|
def version
|
21
26
|
invoke 'proxy_pac_rb:cli:show:version'
|
@@ -14,10 +14,24 @@ module ProxyPacRb
|
|
14
14
|
def validate
|
15
15
|
exit_with_message 'You need to provide at least one url. Multiple urls need to be separated by a space.' if empty_url?
|
16
16
|
exit_with_message 'You need to provide a proxy pac file.' if empty_pac_file?
|
17
|
+
exit_with_message %(You need to provide a path to an existing proxy pac file. The file "#{options[:proxy_pac]}" does not exist.) if non_existing_proxy_pac_file?
|
17
18
|
end
|
18
19
|
|
19
20
|
private
|
20
21
|
|
22
|
+
def proxy_pac_url?
|
23
|
+
url = Addressable::URI.parse(options[:proxy_pac])
|
24
|
+
return true if url.host
|
25
|
+
|
26
|
+
false
|
27
|
+
rescue StandardError
|
28
|
+
false
|
29
|
+
end
|
30
|
+
|
31
|
+
def non_existing_proxy_pac_file?
|
32
|
+
!proxy_pac_url? && !File.file?(options[:proxy_pac])
|
33
|
+
end
|
34
|
+
|
21
35
|
def empty_url?
|
22
36
|
options[:urls].blank?
|
23
37
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ProxyPacRb
|
2
|
+
# Raised if proxy pac is invalid
|
3
|
+
class LinterError < StandardError; end
|
4
|
+
|
5
|
+
# raise on error
|
6
|
+
class ProgramError < StandardError; end
|
7
|
+
|
8
|
+
# raise on java script runtime error
|
9
|
+
class RuntimeUnavailableError < StandardError; end
|
10
|
+
|
11
|
+
# raise on invalid argument
|
12
|
+
class InvalidArgumentError < StandardError; end
|
13
|
+
|
14
|
+
# raise on invalid argument
|
15
|
+
class UrlInvalidError < StandardError; end
|
16
|
+
|
17
|
+
# raise if proxy pac could not be compiled
|
18
|
+
class ParserError < StandardError; end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module ProxyPacRb
|
3
|
+
# Parse Proxy pac to file system
|
4
|
+
class Javascript
|
5
|
+
private
|
6
|
+
|
7
|
+
attr_reader :context
|
8
|
+
|
9
|
+
public
|
10
|
+
|
11
|
+
def initialize(context)
|
12
|
+
@context = context
|
13
|
+
end
|
14
|
+
|
15
|
+
def method_missing(*args, &_block)
|
16
|
+
context.call(args.shift, *args)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# Main
|
3
|
+
module ProxyPacRb
|
4
|
+
@debug_mode = false
|
5
|
+
|
6
|
+
class << self
|
7
|
+
private
|
8
|
+
|
9
|
+
attr_accessor :debug_mode
|
10
|
+
|
11
|
+
public
|
12
|
+
|
13
|
+
def debug_mode_enabled?
|
14
|
+
debug_mode == true
|
15
|
+
end
|
16
|
+
|
17
|
+
def enable_debug_mode
|
18
|
+
self.debug_mode = true
|
19
|
+
%w(pry byebug).each { |l| require l }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/proxy_pac_rb/parser.rb
CHANGED
@@ -13,42 +13,53 @@ module ProxyPacRb
|
|
13
13
|
class Parser
|
14
14
|
private
|
15
15
|
|
16
|
-
attr_reader :
|
16
|
+
attr_reader :parser, :loader, :linter
|
17
17
|
|
18
18
|
public
|
19
19
|
|
20
|
-
def initialize(
|
21
|
-
|
20
|
+
def initialize(*args)
|
21
|
+
if args.first.is_a? Hash
|
22
|
+
@parser = ProxyPacParser.new(**args.first)
|
23
|
+
else
|
24
|
+
$stderr.puts 'Deprecated: Use of positional parameters. Please use named parameters: environment: Environment.new.'
|
25
|
+
@parser = ProxyPacParser.new(environment: args.first)
|
26
|
+
end
|
22
27
|
|
23
|
-
@
|
24
|
-
@
|
28
|
+
@loader = ProxyPacLoader.new
|
29
|
+
@linter = ProxyPacLinter.new
|
25
30
|
end
|
26
31
|
|
27
|
-
def
|
28
|
-
|
29
|
-
end
|
32
|
+
def parse(source)
|
33
|
+
pac_file = ProxyPacFile.new source: source
|
30
34
|
|
31
|
-
|
32
|
-
|
33
|
-
|
35
|
+
loader.load(pac_file)
|
36
|
+
linter.lint(pac_file)
|
37
|
+
|
38
|
+
unless pac_file.valid?
|
39
|
+
$stderr.puts %(proxy.pac "#{pac_file.source}" is invalid.)
|
40
|
+
|
41
|
+
return
|
42
|
+
end
|
34
43
|
|
35
|
-
|
36
|
-
create_file(source)
|
44
|
+
parser.parse(pac_file)
|
37
45
|
end
|
38
46
|
|
39
|
-
|
47
|
+
def load(*args)
|
48
|
+
$stderr.puts 'Deprecated: #load. Please use #parse instead.'
|
40
49
|
|
41
|
-
|
42
|
-
|
50
|
+
parse(*args)
|
51
|
+
end
|
43
52
|
|
44
|
-
|
45
|
-
|
53
|
+
def read(*args)
|
54
|
+
$stderr.puts 'Deprecated: #read. Please use #parse instead.'
|
46
55
|
|
47
|
-
|
56
|
+
parse(*args)
|
48
57
|
end
|
49
58
|
|
50
|
-
def
|
51
|
-
|
59
|
+
def source(*args)
|
60
|
+
$stderr.puts 'Deprecated: #source. Please use #parse instead.'
|
61
|
+
|
62
|
+
parse(*args)
|
52
63
|
end
|
53
64
|
end
|
54
65
|
end
|
@@ -1,34 +1,24 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
module ProxyPacRb
|
3
|
-
#
|
2
|
+
# Proxy pac file
|
4
3
|
class ProxyPac
|
5
4
|
private
|
6
5
|
|
7
|
-
attr_reader :
|
6
|
+
attr_reader :javascript
|
8
7
|
|
9
8
|
public
|
10
9
|
|
11
|
-
|
12
|
-
@path = path
|
13
|
-
end
|
10
|
+
attr_reader :file
|
14
11
|
|
15
|
-
def
|
16
|
-
|
12
|
+
def initialize(javascript:, file:)
|
13
|
+
@javascript = javascript
|
14
|
+
@file = file
|
17
15
|
end
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
uri = Addressable::URI.parse(path)
|
23
|
-
|
24
|
-
uri.path = ::File.expand_path(uri.path) if uri.host.nil?
|
25
|
-
|
26
|
-
ENV.delete 'HTTP_PROXY'
|
27
|
-
ENV.delete 'HTTPS_PROXY'
|
28
|
-
ENV.delete 'http_proxy'
|
29
|
-
ENV.delete 'https_proxy'
|
17
|
+
def find(url)
|
18
|
+
uri = Addressable::URI.heuristic_parse(url)
|
19
|
+
fail UrlInvalidError, 'url is missing host' unless uri.host
|
30
20
|
|
31
|
-
|
21
|
+
javascript.FindProxyForURL(url, uri.host)
|
32
22
|
end
|
33
23
|
end
|
34
24
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module ProxyPacRb
|
3
|
+
# Dump Proxy pac to file system
|
4
|
+
class ProxyPacDumper
|
5
|
+
private
|
6
|
+
|
7
|
+
attr_reader :type, :dumpers
|
8
|
+
|
9
|
+
public
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@dumpers = Hash.new { ProxyPacStringDumper.new }
|
13
|
+
@dumpers[:template] = ProxyPacTemplateDumper.new
|
14
|
+
@dumpers[:string] = ProxyPacStringDumper.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def dump(proxy_pac, type:)
|
18
|
+
dumpers[type].dump(proxy_pac)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Dump string to file
|
23
|
+
class ProxyPacStringDumper
|
24
|
+
private
|
25
|
+
|
26
|
+
attr_reader :default_file_name
|
27
|
+
|
28
|
+
public
|
29
|
+
|
30
|
+
def initialize
|
31
|
+
@default_file_name = 'proxy.pac'
|
32
|
+
end
|
33
|
+
|
34
|
+
def dump(proxy_pac)
|
35
|
+
::File.write(default_file_name, proxy_pac.content)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Dump proxy pac based on template
|
40
|
+
class ProxyPacTemplateDumper
|
41
|
+
def dump(proxy_pac)
|
42
|
+
::File.write(output_path(proxy_pac.source), proxy_pac.content)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def in_extension
|
48
|
+
'.in'
|
49
|
+
end
|
50
|
+
|
51
|
+
def out_extension
|
52
|
+
'.out'
|
53
|
+
end
|
54
|
+
|
55
|
+
def output_path(path)
|
56
|
+
if ::File.exist?(path.gsub(/#{in_extension}*$/, '') + in_extension)
|
57
|
+
return path.gsub(/#{in_extension}*$/, '')
|
58
|
+
elsif ::File.exist? path
|
59
|
+
return path + out_extension
|
60
|
+
else
|
61
|
+
fail Errno::ENOENT, "Both paths \"#{path.gsub(/#{in_extension}*$/, '') + in_extension}\" and \"#{path}\" do not exist."
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -1,9 +1,26 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module ProxyPacRb
|
3
|
-
# Pac file
|
4
|
-
class ProxyPacFile
|
3
|
+
# Pac file
|
4
|
+
class ProxyPacFile
|
5
|
+
attr_accessor :valid, :type, :message
|
6
|
+
attr_reader :source
|
7
|
+
attr_writer :content
|
8
|
+
|
9
|
+
def initialize(source:)
|
10
|
+
@source = source
|
11
|
+
@valid = false
|
12
|
+
end
|
13
|
+
|
5
14
|
def content
|
6
|
-
|
15
|
+
@content.dup
|
16
|
+
end
|
17
|
+
|
18
|
+
def type?(t)
|
19
|
+
type == t
|
20
|
+
end
|
21
|
+
|
22
|
+
def valid?
|
23
|
+
valid == true
|
7
24
|
end
|
8
25
|
end
|
9
26
|
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module ProxyPacRb
|
3
|
+
# Dump Proxy pac to file system
|
4
|
+
class ProxyPacLinter
|
5
|
+
private
|
6
|
+
|
7
|
+
attr_reader :rules, :silent
|
8
|
+
|
9
|
+
public
|
10
|
+
|
11
|
+
def initialize(silent: false)
|
12
|
+
@rules = []
|
13
|
+
@rules << Rules::ContainerProxyPacFunction.new
|
14
|
+
@rules << Rules::CanBeParsed.new
|
15
|
+
|
16
|
+
@silent = silent
|
17
|
+
end
|
18
|
+
|
19
|
+
# Load proxy pac
|
20
|
+
#
|
21
|
+
# @param [#source] proxy_pac
|
22
|
+
# The proxy.pac
|
23
|
+
def lint(proxy_pac)
|
24
|
+
rules.each { |r| r.lint(proxy_pac) }
|
25
|
+
|
26
|
+
proxy_pac.valid = true
|
27
|
+
rescue LinterError => err
|
28
|
+
$stderr.puts err.message unless silent
|
29
|
+
|
30
|
+
proxy_pac.message = err.message
|
31
|
+
proxy_pac.valid = false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module Rules
|
36
|
+
# A proxy pac needs to contain FindProxyForURL
|
37
|
+
class ContainerProxyPacFunction
|
38
|
+
def lint(proxy_pac)
|
39
|
+
message = if proxy_pac.type? :string
|
40
|
+
%(proxy.pac is only given as string "#{proxy_pac.source}" and does not contain "FindProxyForURL".)
|
41
|
+
elsif proxy_pac.type? :url
|
42
|
+
%(proxy.pac-url "#{proxy_pac.source}" does not contain "FindProxyForURL".)
|
43
|
+
else
|
44
|
+
%(proxy.pac-file "#{proxy_pac.source}" does not contain "FindProxyForURL".)
|
45
|
+
end
|
46
|
+
|
47
|
+
fail LinterError, message unless proxy_pac.content.include?('FindProxyForURL')
|
48
|
+
|
49
|
+
self
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# A proxy pac needs be parsable
|
54
|
+
class CanBeParsed
|
55
|
+
private
|
56
|
+
|
57
|
+
attr_reader :parser
|
58
|
+
|
59
|
+
public
|
60
|
+
|
61
|
+
def initialize
|
62
|
+
@parser = ProxyPacParser.new
|
63
|
+
end
|
64
|
+
|
65
|
+
def lint(proxy_pac)
|
66
|
+
parser.parse(proxy_pac)
|
67
|
+
|
68
|
+
self
|
69
|
+
rescue => err
|
70
|
+
message = if proxy_pac.type? :string
|
71
|
+
%(proxy.pac is only given as string "#{proxy_pac.source}" cannot be parsed:\n#{err.message}".)
|
72
|
+
elsif proxy_pac.type? :url
|
73
|
+
%(proxy.pac-url "#{proxy_pac.source}" cannot be parsed:\n#{err.message}".)
|
74
|
+
else
|
75
|
+
%(proxy.pac-file "#{proxy_pac.source}" cannot be parsed:\n#{err.message}".)
|
76
|
+
end
|
77
|
+
|
78
|
+
raise LinterError, message
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module ProxyPacRb
|
3
|
+
# Dump Proxy pac to file system
|
4
|
+
class ProxyPacLoader
|
5
|
+
private
|
6
|
+
|
7
|
+
attr_reader :loaders, :default_loader
|
8
|
+
|
9
|
+
public
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@loaders = []
|
13
|
+
@loaders << ProxyPacStringLoader.new
|
14
|
+
@loaders << ProxyPacFileLoader.new
|
15
|
+
@loaders << ProxyPacUriLoader.new
|
16
|
+
|
17
|
+
@default_loader = -> { ProxyPacStringLoader.new }
|
18
|
+
end
|
19
|
+
|
20
|
+
# Load proxy pac
|
21
|
+
#
|
22
|
+
# @param [#source] proxy_pac
|
23
|
+
# The proxy.pac
|
24
|
+
def load(proxy_pac)
|
25
|
+
loaders.find(default_loader) { |l| l.suitable_for? proxy_pac }.load(proxy_pac)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Load proxy pac from string
|
30
|
+
class ProxyPacStringLoader
|
31
|
+
def load(proxy_pac)
|
32
|
+
proxy_pac.content = proxy_pac.source.to_s
|
33
|
+
proxy_pac.type = :string
|
34
|
+
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
def suitable_for?(proxy_pac)
|
39
|
+
proxy_pac.source.include? 'FindProxyForURL'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Load proxy pac from file
|
44
|
+
class ProxyPacFileLoader
|
45
|
+
def load(proxy_pac)
|
46
|
+
proxy_pac.content = ::File.read(proxy_pac.source).chomp
|
47
|
+
proxy_pac.type = :file
|
48
|
+
end
|
49
|
+
|
50
|
+
def suitable_for?(proxy_pac)
|
51
|
+
::File.file? proxy_pac.source
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Load proxy pac from url
|
56
|
+
class ProxyPacUriLoader
|
57
|
+
def load(proxy_pac)
|
58
|
+
proxy_pac.content = Net::HTTP.get(URI(proxy_pac.source))
|
59
|
+
proxy_pac.type = :url
|
60
|
+
end
|
61
|
+
|
62
|
+
def suitable_for?(proxy_pac)
|
63
|
+
uri = Addressable::URI.parse(proxy_pac.source)
|
64
|
+
|
65
|
+
return true unless uri.host.blank?
|
66
|
+
|
67
|
+
false
|
68
|
+
rescue StandardError
|
69
|
+
false
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def with_proxy_environment_variables
|
75
|
+
backup = []
|
76
|
+
|
77
|
+
%w(
|
78
|
+
http_proxy
|
79
|
+
https_proxy
|
80
|
+
HTTP_PROXY
|
81
|
+
HTTPS_PROXY
|
82
|
+
).each do |v|
|
83
|
+
backup << ENV.delete(v)
|
84
|
+
end
|
85
|
+
|
86
|
+
yield
|
87
|
+
ensure
|
88
|
+
%w(
|
89
|
+
http_proxy
|
90
|
+
https_proxy
|
91
|
+
HTTP_PROXY
|
92
|
+
HTTPS_PROXY
|
93
|
+
).each do |v|
|
94
|
+
ENV[v] = backup.shift
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module ProxyPacRb
|
3
|
+
# Parse Proxy pac to file system
|
4
|
+
class ProxyPacParser
|
5
|
+
private
|
6
|
+
|
7
|
+
attr_reader :environment, :runtime
|
8
|
+
|
9
|
+
public
|
10
|
+
|
11
|
+
def initialize(
|
12
|
+
environment: Environment.new,
|
13
|
+
runtime: Runtimes.autodetect
|
14
|
+
)
|
15
|
+
@runtime = runtime
|
16
|
+
@environment = environment
|
17
|
+
end
|
18
|
+
|
19
|
+
def parse(proxy_pac)
|
20
|
+
fail Exceptions::RuntimeUnavailable, "#{runtime.name} is unavailable on this system" unless runtime.available?
|
21
|
+
|
22
|
+
ProxyPac.new(
|
23
|
+
javascript: compile_javascript(proxy_pac.content),
|
24
|
+
file: proxy_pac
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def compile_javascript(content)
|
31
|
+
environment.prepare(content)
|
32
|
+
|
33
|
+
context = runtime.compile(content)
|
34
|
+
context.include environment
|
35
|
+
|
36
|
+
Javascript.new(context)
|
37
|
+
rescue StandardError => err
|
38
|
+
raise ParserError, err.message
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'proxy_pac_rb'
|
2
|
+
require 'rack'
|
3
|
+
|
4
|
+
module ProxyPacRb
|
5
|
+
module Rack
|
6
|
+
# Rack Middleware to compress proxy pac
|
7
|
+
#
|
8
|
+
# @example Sinatra's <server>.rb
|
9
|
+
# require 'proxy_pac_rb/rack/proxy_pac_compressor'
|
10
|
+
# use ProxyPacRb::Rack::ProxyPacCompressor
|
11
|
+
#
|
12
|
+
# @example Rack's config.ru
|
13
|
+
# require 'proxy_pac_rb/rack/proxy_pac_compressor'
|
14
|
+
# use ProxyPacRb::Rack::ProxyPacCompressor
|
15
|
+
#
|
16
|
+
# @example Middleman's config.rb
|
17
|
+
# require 'proxy_pac_rb/rack/proxy_pac_compressor'
|
18
|
+
# use ProxyPacRb::Rack::ProxyPacCompressor
|
19
|
+
#
|
20
|
+
class ProxyPacCompressor
|
21
|
+
private
|
22
|
+
|
23
|
+
attr_reader :compressor, :loader, :enabled
|
24
|
+
|
25
|
+
public
|
26
|
+
|
27
|
+
def initialize(
|
28
|
+
app,
|
29
|
+
enabled: true
|
30
|
+
)
|
31
|
+
@app = app
|
32
|
+
@compressor = ProxyPacRb::ProxyPacCompressor.new
|
33
|
+
@loader = ProxyPacRb::ProxyPacLoader.new
|
34
|
+
@enabled = enabled
|
35
|
+
end
|
36
|
+
|
37
|
+
def call(env)
|
38
|
+
status, headers, body = @app.call(env)
|
39
|
+
|
40
|
+
return [status, headers, body] if enabled == false
|
41
|
+
# rubocop:disable Style/CaseEquality
|
42
|
+
return [status, headers, body] unless headers.key?('Content-Type') \
|
43
|
+
&& %r{application/x-ns-proxy-autoconfig} === headers['Content-Type']
|
44
|
+
# rubocop:enable Style/CaseEquality
|
45
|
+
|
46
|
+
content = [body].flatten.each_with_object('') { |e, a| a << e.to_s }
|
47
|
+
|
48
|
+
begin
|
49
|
+
proxy_pac = ProxyPacFile.new(source: content)
|
50
|
+
|
51
|
+
loader.load(proxy_pac)
|
52
|
+
compressor.compress(proxy_pac)
|
53
|
+
|
54
|
+
content = proxy_pac.content
|
55
|
+
rescue => err
|
56
|
+
status = 500
|
57
|
+
content = err.message
|
58
|
+
end
|
59
|
+
|
60
|
+
headers['Content-Length'] = content.bytesize.to_s if headers['Content-Length']
|
61
|
+
|
62
|
+
[status, headers, [content]]
|
63
|
+
ensure
|
64
|
+
body.close if body.respond_to? :close
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|