devproxy 0.1.0 → 0.2.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.
- data/.travis.yml +5 -0
- data/Gemfile +3 -0
- data/Rakefile +4 -0
- data/data/css/style.css +21 -0
- data/devproxy.gemspec +1 -0
- data/lib/devproxy/cli/server.rb +63 -0
- data/lib/devproxy/cli.rb +58 -1
- data/lib/devproxy/connection.rb +24 -5
- data/lib/devproxy/options.rb +4 -2
- data/lib/devproxy/version.rb +1 -1
- data/readme.md +1 -1
- data/spec/cli_spec.rb +33 -0
- data/spec/options_spec.rb +47 -0
- data/spec/spec_helper.rb +3 -0
- metadata +20 -4
    
        data/.travis.yml
    ADDED
    
    
    
        data/Gemfile
    CHANGED
    
    
    
        data/Rakefile
    CHANGED
    
    
    
        data/data/css/style.css
    ADDED
    
    | @@ -0,0 +1,21 @@ | |
| 1 | 
            +
            body {
         | 
| 2 | 
            +
              text-align: center;
         | 
| 3 | 
            +
            }
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            .details {
         | 
| 6 | 
            +
              width: 100%;
         | 
| 7 | 
            +
            }
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            .details table {
         | 
| 10 | 
            +
              margin: auto;
         | 
| 11 | 
            +
              font-size: 30px;
         | 
| 12 | 
            +
              border-collapse: collapse;
         | 
| 13 | 
            +
            }
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            .details table tr:nth-child(odd) {
         | 
| 16 | 
            +
              background-color: #efefef;
         | 
| 17 | 
            +
            }
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            .details table td {
         | 
| 20 | 
            +
              padding: 5px;
         | 
| 21 | 
            +
            }
         | 
    
        data/devproxy.gemspec
    CHANGED
    
    | @@ -11,6 +11,7 @@ Gem::Specification.new do |gem| | |
| 11 11 | 
             
              gem.summary       = %q{https://devproxy.io client gem}
         | 
| 12 12 | 
             
              gem.description   = %q{https://devproxy.io client gem}
         | 
| 13 13 | 
             
              gem.homepage      = "https://github.com/boz/devproxy"
         | 
| 14 | 
            +
              gem.license       = "MIT"
         | 
| 14 15 |  | 
| 15 16 | 
             
              gem.add_dependency "net-ssh", "~> 2.6.7"
         | 
| 16 17 | 
             
              gem.add_development_dependency "rspec"
         | 
| @@ -0,0 +1,63 @@ | |
| 1 | 
            +
            require 'webrick'
         | 
| 2 | 
            +
            require 'cgi'
         | 
| 3 | 
            +
            class Devproxy::CLI::Server < WEBrick::HTTPServer
         | 
| 4 | 
            +
              class Servlet < WEBrick::HTTPServlet::AbstractServlet
         | 
| 5 | 
            +
                def do_GET(request,response)
         | 
| 6 | 
            +
                  token   = request.cookies.detect { |x| x.name == "DEVPROXY" }
         | 
| 7 | 
            +
                  token &&= token.value
         | 
| 8 | 
            +
                  token ||= "NONE"
         | 
| 9 | 
            +
                  sysname = "#{%x{whoami}}@#{%x{hostname}}"
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  response.status          = 200
         | 
| 12 | 
            +
                  response['Content-Type'] = "text/html"
         | 
| 13 | 
            +
                  response.body = %{
         | 
| 14 | 
            +
                    <html>
         | 
| 15 | 
            +
                    <head>
         | 
| 16 | 
            +
                      <link rel="stylesheet" href="/css/style.css">
         | 
| 17 | 
            +
                      <title>Devproxy Test Server</title>
         | 
| 18 | 
            +
                    </head>
         | 
| 19 | 
            +
                    <body>
         | 
| 20 | 
            +
                      <h1>Hello from #{h(sysname)}</h2>
         | 
| 21 | 
            +
                      <div class="details">
         | 
| 22 | 
            +
                        <table>
         | 
| 23 | 
            +
                          <caption>Tunnel Details</caption>
         | 
| 24 | 
            +
                          <tbody>
         | 
| 25 | 
            +
                            <tr>
         | 
| 26 | 
            +
                              <td>host</td><td>#{h(request.host)}</td>
         | 
| 27 | 
            +
                            </tr>
         | 
| 28 | 
            +
                            <tr>
         | 
| 29 | 
            +
                              <td>protocol</td><td>#{h(request['x-forwarded-proto'])}</td>
         | 
| 30 | 
            +
                            </tr>
         | 
| 31 | 
            +
                            <tr>
         | 
| 32 | 
            +
                              <td>token</td><td>#{h(token)}</td>
         | 
| 33 | 
            +
                            </tr>
         | 
| 34 | 
            +
                          </tbody>
         | 
| 35 | 
            +
                        </table>
         | 
| 36 | 
            +
                      </div>
         | 
| 37 | 
            +
                    </body>
         | 
| 38 | 
            +
                    </html>
         | 
| 39 | 
            +
                  }
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
                def h(str)
         | 
| 42 | 
            +
                  CGI::escape_html(str)
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
              def initialize(*args)
         | 
| 46 | 
            +
                super
         | 
| 47 | 
            +
                mount "/"   , Servlet
         | 
| 48 | 
            +
                mount "/css", WEBrick::HTTPServlet::FileHandler, File.join(File.dirname(__FILE__),"..","..","..","data","css")
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
              def start(*args)
         | 
| 52 | 
            +
                @mutex  ||= Mutex.new
         | 
| 53 | 
            +
                @thread ||= Thread.new do
         | 
| 54 | 
            +
                  super(*args)
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
              def shutdown
         | 
| 59 | 
            +
                @mutex.synchronize do
         | 
| 60 | 
            +
                  super
         | 
| 61 | 
            +
                end if @mutex
         | 
| 62 | 
            +
              end
         | 
| 63 | 
            +
            end
         | 
    
        data/lib/devproxy/cli.rb
    CHANGED
    
    | @@ -1,10 +1,54 @@ | |
| 1 1 | 
             
            require 'devproxy/connection'
         | 
| 2 2 | 
             
            require 'devproxy/options'
         | 
| 3 3 | 
             
            require 'optparse'
         | 
| 4 | 
            +
             | 
| 4 5 | 
             
            module Devproxy
         | 
| 5 6 | 
             
              class CLI < Devproxy::Connection
         | 
| 7 | 
            +
                class Options < Devproxy::Options
         | 
| 8 | 
            +
                  attr_accessor(:test)
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                autoload :Server, 'devproxy/cli/server'
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def initialize *args
         | 
| 14 | 
            +
                  super(*args)
         | 
| 15 | 
            +
                  initialize_test_server
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                def loop!
         | 
| 19 | 
            +
                  start_test_server
         | 
| 20 | 
            +
                  super
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def stop!
         | 
| 24 | 
            +
                  stop_test_server
         | 
| 25 | 
            +
                  super
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                protected
         | 
| 29 | 
            +
                def testing?
         | 
| 30 | 
            +
                  options.test
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                def initialize_test_server
         | 
| 34 | 
            +
                  return unless testing?
         | 
| 35 | 
            +
                  @test_server = Server.new({
         | 
| 36 | 
            +
                    :Port        => options.port,
         | 
| 37 | 
            +
                    :BindAddress => options.listen,
         | 
| 38 | 
            +
                  })
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                def start_test_server
         | 
| 42 | 
            +
                  return unless testing?
         | 
| 43 | 
            +
                  @test_server.start
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
                def stop_test_server
         | 
| 46 | 
            +
                  return unless testing?
         | 
| 47 | 
            +
                  @test_server.stop
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 6 50 | 
             
                def self.parse(argv)
         | 
| 7 | 
            -
                  options =  | 
| 51 | 
            +
                  options = Options::default
         | 
| 8 52 | 
             
                  opts    = OptionParser.new
         | 
| 9 53 | 
             
                  opts.banner = "Usage: devproxy user [proxy] [options...]"
         | 
| 10 54 |  | 
| @@ -21,7 +65,20 @@ module Devproxy | |
| 21 65 | 
             
                    options.port = x
         | 
| 22 66 | 
             
                  end
         | 
| 23 67 |  | 
| 68 | 
            +
                  opts.on "--test-server", "Launch local server for testing" do |x|
         | 
| 69 | 
            +
                    options.test = true
         | 
| 70 | 
            +
                  end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                  opts.on "-v", "--verbose",
         | 
| 73 | 
            +
                          "Verbose output (default: #{options.verbose})" do |x|
         | 
| 74 | 
            +
                    options.verbose = true
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
             | 
| 24 77 | 
             
                  if ENV['DEVPROXY_DEVELOPMENT']
         | 
| 78 | 
            +
                    opts.on "-l ADDRESS", "--listen ADDRESS",
         | 
| 79 | 
            +
                            "Local address to listen on (default: #{options.listen})" do |x|
         | 
| 80 | 
            +
                      options.listen = x
         | 
| 81 | 
            +
                    end
         | 
| 25 82 | 
             
                    opts.on "--host HOST", "remote hostname." do |x|
         | 
| 26 83 | 
             
                      options.host = x
         | 
| 27 84 | 
             
                    end
         | 
    
        data/lib/devproxy/connection.rb
    CHANGED
    
    | @@ -5,6 +5,7 @@ module Devproxy | |
| 5 5 | 
             
              class Connection
         | 
| 6 6 | 
             
                class Error                 < StandardError; end
         | 
| 7 7 | 
             
                class Error::Authentication < Error        ; end
         | 
| 8 | 
            +
                HEARTBEAT = "HEARTBEAT"
         | 
| 8 9 |  | 
| 9 10 | 
             
                attr_reader :options, :ssh
         | 
| 10 11 |  | 
| @@ -28,15 +29,27 @@ module Devproxy | |
| 28 29 | 
             
                  @halt
         | 
| 29 30 | 
             
                end
         | 
| 30 31 |  | 
| 31 | 
            -
                def  | 
| 32 | 
            -
                  $stdout. | 
| 32 | 
            +
                def on_connected
         | 
| 33 | 
            +
                  $stdout.puts "Tunneling requests from https://#{options.proxy}.devproxy.io to #{options.listen} port #{options.port}"
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                def on_heartbeat data
         | 
| 37 | 
            +
                  return unless options.verbose
         | 
| 38 | 
            +
                  $stdout.write "."
         | 
| 33 39 | 
             
                  if (@dotno += 1) % MAX_DOTS == 0
         | 
| 34 40 | 
             
                    $stdout.write "\n"
         | 
| 35 41 | 
             
                  end
         | 
| 36 42 | 
             
                end
         | 
| 37 43 |  | 
| 44 | 
            +
                def on_stdout data
         | 
| 45 | 
            +
                  $stdout.write("\n") if options.verbose
         | 
| 46 | 
            +
                  $stdout.puts(data)
         | 
| 47 | 
            +
                  reset_dots!
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 38 50 | 
             
                def on_stderr data
         | 
| 39 | 
            -
                  $ | 
| 51 | 
            +
                  $stdout.write("\n") if options.verbose
         | 
| 52 | 
            +
                  $stderr.puts(data)
         | 
| 40 53 | 
             
                  reset_dots!
         | 
| 41 54 | 
             
                end
         | 
| 42 55 |  | 
| @@ -56,10 +69,14 @@ module Devproxy | |
| 56 69 | 
             
                def self.create(options)
         | 
| 57 70 | 
             
                  ssh        = open_ssh(options)
         | 
| 58 71 | 
             
                  connection = new(options,ssh)
         | 
| 59 | 
            -
                  ssh.forward.remote(options.port, | 
| 72 | 
            +
                  ssh.forward.remote(options.port,options.listen,0,'0.0.0.0')
         | 
| 60 73 | 
             
                  channel    = ssh.exec(options.proxy) do |ch,stream,data|
         | 
| 61 74 | 
             
                    if stream == :stdout
         | 
| 62 | 
            -
                       | 
| 75 | 
            +
                      if data.start_with?(HEARTBEAT)
         | 
| 76 | 
            +
                        connection.on_heartbeat(data)
         | 
| 77 | 
            +
                      else
         | 
| 78 | 
            +
                        connection.on_stdout(data)
         | 
| 79 | 
            +
                      end
         | 
| 63 80 | 
             
                    else
         | 
| 64 81 | 
             
                      connection.on_stderr(data)
         | 
| 65 82 | 
             
                    end
         | 
| @@ -67,6 +84,7 @@ module Devproxy | |
| 67 84 | 
             
                  channel.on_close do
         | 
| 68 85 | 
             
                    connection.on_close
         | 
| 69 86 | 
             
                  end
         | 
| 87 | 
            +
                  connection.on_connected
         | 
| 70 88 | 
             
                  connection
         | 
| 71 89 | 
             
                rescue Net::SSH::AuthenticationFailed
         | 
| 72 90 | 
             
                  raise Error::Authentication, "Authentication Failed: Invalid username or SSH key"
         | 
| @@ -74,6 +92,7 @@ module Devproxy | |
| 74 92 | 
             
                def self.open_ssh(options)
         | 
| 75 93 | 
             
                  Net::SSH.start(options.host, options.username,{
         | 
| 76 94 | 
             
                    :port => options.remote_port,
         | 
| 95 | 
            +
                    :user_known_hosts_file => "/dev/null",
         | 
| 77 96 | 
             
                  })
         | 
| 78 97 | 
             
                end
         | 
| 79 98 | 
             
              end
         | 
    
        data/lib/devproxy/options.rb
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            module Devproxy
         | 
| 2 | 
            -
              class Options < Struct.new(:user, :proxy, :port, :host, :remote_port)
         | 
| 2 | 
            +
              class Options < Struct.new(:user, :proxy, :port, :host, :remote_port, :listen, :verbose)
         | 
| 3 3 | 
             
                def username
         | 
| 4 | 
            -
                  "devproxy-#{user}"
         | 
| 4 | 
            +
                  "devproxy-#{user}" if !!user && !user.empty?
         | 
| 5 5 | 
             
                end
         | 
| 6 6 | 
             
                def valid?
         | 
| 7 7 | 
             
                  !( user.nil?  || user.empty?      ||
         | 
| @@ -14,6 +14,8 @@ module Devproxy | |
| 14 14 | 
             
                  default.host        = "ssh.devproxy.io"
         | 
| 15 15 | 
             
                  default.remote_port = 2222
         | 
| 16 16 | 
             
                  default.port        = 3000
         | 
| 17 | 
            +
                  default.listen      = "0.0.0.0"
         | 
| 18 | 
            +
                  default.verbose     = false
         | 
| 17 19 | 
             
                  default
         | 
| 18 20 | 
             
                end
         | 
| 19 21 | 
             
              end
         | 
    
        data/lib/devproxy/version.rb
    CHANGED
    
    
    
        data/readme.md
    CHANGED
    
    
    
        data/spec/cli_spec.rb
    ADDED
    
    | @@ -0,0 +1,33 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
            describe Devproxy::CLI do
         | 
| 3 | 
            +
              describe "#parse" do
         | 
| 4 | 
            +
                it "should default the proxy to the given name" do
         | 
| 5 | 
            +
                  options = parse("foo")
         | 
| 6 | 
            +
                  expect(options.user).to  eq("foo")
         | 
| 7 | 
            +
                  expect(options.proxy).to eq("foo")
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
                it "should accept a different proxy name" do
         | 
| 10 | 
            +
                  options = parse("foo","bar")
         | 
| 11 | 
            +
                  expect(options.user).to  eq("foo")
         | 
| 12 | 
            +
                  expect(options.proxy).to eq("bar")
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
                it "should parse the port option" do
         | 
| 15 | 
            +
                  expect(parse("foo","bar","-p"    ,"20").port).to eq(20)
         | 
| 16 | 
            +
                  expect(parse("foo","bar","--port","20").port).to eq(20)
         | 
| 17 | 
            +
                  expect(parse("foo","bar"              ).port).to eq(Devproxy::Options.default.port)
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
                it "should parse the test server option" do
         | 
| 20 | 
            +
                  expect(parse("foo","bar","--test-server").test).to be_true
         | 
| 21 | 
            +
                  expect(parse("foo","bar"                ).test).to be_false
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
                it "should parse the verbose option" do
         | 
| 24 | 
            +
                  expect(parse("foo","bar","-v"       ).verbose).to be_true
         | 
| 25 | 
            +
                  expect(parse("foo","bar","--verbose").verbose).to be_true
         | 
| 26 | 
            +
                  expect(parse("foo","bar"            ).verbose).to be_false
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
              def parse(*args)
         | 
| 31 | 
            +
                Devproxy::CLI::parse(args)
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
            end
         | 
| @@ -0,0 +1,47 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
            describe Devproxy::Options do
         | 
| 3 | 
            +
              describe "defaults" do
         | 
| 4 | 
            +
                it "should have default values" do
         | 
| 5 | 
            +
                  options = default_options
         | 
| 6 | 
            +
                  expect(options.host        ).to eq("ssh.devproxy.io")
         | 
| 7 | 
            +
                  expect(options.remote_port ).to eq(2222)
         | 
| 8 | 
            +
                  expect(options.port        ).to eq(3000)
         | 
| 9 | 
            +
                  expect(options.listen      ).to eq("0.0.0.0")
         | 
| 10 | 
            +
                  expect(options.verbose     ).to eq(false)
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
                it "should not have username or proxy" do
         | 
| 13 | 
            +
                  options = default_options
         | 
| 14 | 
            +
                  expect(options.username).to be_nil
         | 
| 15 | 
            +
                  expect(options.proxy   ).to be_nil
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              describe "valid?" do
         | 
| 20 | 
            +
                it "should require a username" do
         | 
| 21 | 
            +
                  expect(default_options(:proxy => "foo")).to_not be_valid
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
                it "should require a username" do
         | 
| 24 | 
            +
                  expect(default_options(:user => "bar")).to_not be_valid
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
                it "should only need a username and proxy" do
         | 
| 27 | 
            +
                  expect(default_options(:proxy => "foo", :user => "bar")).to be_valid
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
              describe "username" do
         | 
| 32 | 
            +
                it "should include name" do
         | 
| 33 | 
            +
                  expect(default_options(:user => "bar").username).to include("bar")
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
                it "should be nil if no name is given" do
         | 
| 36 | 
            +
                  expect(default_options.username).to be_nil
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
              end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
              def default_options(options = {})
         | 
| 41 | 
            +
                default = Devproxy::Options.default
         | 
| 42 | 
            +
                options.each do |key,value|
         | 
| 43 | 
            +
                  default.__send__("#{key}=",value)
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
                default
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
            end
         | 
    
        data/spec/spec_helper.rb
    ADDED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: devproxy
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.2.0
         | 
| 5 5 | 
             
              prerelease: 
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors:
         | 
| @@ -9,7 +9,7 @@ authors: | |
| 9 9 | 
             
            autorequire: 
         | 
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date: 2013-07- | 
| 12 | 
            +
            date: 2013-07-24 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              name: net-ssh
         | 
| @@ -52,20 +52,27 @@ extensions: [] | |
| 52 52 | 
             
            extra_rdoc_files: []
         | 
| 53 53 | 
             
            files:
         | 
| 54 54 | 
             
            - .gitignore
         | 
| 55 | 
            +
            - .travis.yml
         | 
| 55 56 | 
             
            - Gemfile
         | 
| 56 57 | 
             
            - LICENSE.txt
         | 
| 57 58 | 
             
            - Rakefile
         | 
| 58 59 | 
             
            - bin/devproxy
         | 
| 60 | 
            +
            - data/css/style.css
         | 
| 59 61 | 
             
            - devproxy.gemspec
         | 
| 60 62 | 
             
            - lib/devproxy.rb
         | 
| 61 63 | 
             
            - lib/devproxy/cli.rb
         | 
| 64 | 
            +
            - lib/devproxy/cli/server.rb
         | 
| 62 65 | 
             
            - lib/devproxy/connection.rb
         | 
| 63 66 | 
             
            - lib/devproxy/net-ssh-patch.rb
         | 
| 64 67 | 
             
            - lib/devproxy/options.rb
         | 
| 65 68 | 
             
            - lib/devproxy/version.rb
         | 
| 66 69 | 
             
            - readme.md
         | 
| 70 | 
            +
            - spec/cli_spec.rb
         | 
| 71 | 
            +
            - spec/options_spec.rb
         | 
| 72 | 
            +
            - spec/spec_helper.rb
         | 
| 67 73 | 
             
            homepage: https://github.com/boz/devproxy
         | 
| 68 | 
            -
            licenses: | 
| 74 | 
            +
            licenses:
         | 
| 75 | 
            +
            - MIT
         | 
| 69 76 | 
             
            post_install_message: 
         | 
| 70 77 | 
             
            rdoc_options: []
         | 
| 71 78 | 
             
            require_paths:
         | 
| @@ -76,16 +83,25 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 76 83 | 
             
              - - ! '>='
         | 
| 77 84 | 
             
                - !ruby/object:Gem::Version
         | 
| 78 85 | 
             
                  version: '0'
         | 
| 86 | 
            +
                  segments:
         | 
| 87 | 
            +
                  - 0
         | 
| 88 | 
            +
                  hash: -760381207862352631
         | 
| 79 89 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 80 90 | 
             
              none: false
         | 
| 81 91 | 
             
              requirements:
         | 
| 82 92 | 
             
              - - ! '>='
         | 
| 83 93 | 
             
                - !ruby/object:Gem::Version
         | 
| 84 94 | 
             
                  version: '0'
         | 
| 95 | 
            +
                  segments:
         | 
| 96 | 
            +
                  - 0
         | 
| 97 | 
            +
                  hash: -760381207862352631
         | 
| 85 98 | 
             
            requirements: []
         | 
| 86 99 | 
             
            rubyforge_project: 
         | 
| 87 100 | 
             
            rubygems_version: 1.8.25
         | 
| 88 101 | 
             
            signing_key: 
         | 
| 89 102 | 
             
            specification_version: 3
         | 
| 90 103 | 
             
            summary: https://devproxy.io client gem
         | 
| 91 | 
            -
            test_files: | 
| 104 | 
            +
            test_files:
         | 
| 105 | 
            +
            - spec/cli_spec.rb
         | 
| 106 | 
            +
            - spec/options_spec.rb
         | 
| 107 | 
            +
            - spec/spec_helper.rb
         |