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
|