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
         |