spider-gazelle 0.1.2 → 0.1.3
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/bin/sg +1 -24
- data/lib/rack/handler/spider-gazelle.rb +33 -41
- data/lib/spider-gazelle/app_store.rb +7 -5
- data/lib/spider-gazelle/binding.rb +4 -4
- data/lib/spider-gazelle/connection.rb +2 -4
- data/lib/spider-gazelle/request.rb +3 -0
- data/lib/spider-gazelle/spider.rb +41 -0
- data/lib/spider-gazelle/upgrades/websocket.rb +23 -7
- data/lib/spider-gazelle/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ddf67f2f83bb093e412603cfaccbdff9465fd492
|
|
4
|
+
data.tar.gz: 418b883c22f28aec01358f7e1583b5102eed3452
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8e6bf5475f273760fb5bcbcd0e73988a292d3f473d95e96a6b043168b303b46403fac5e4c2b1201693ef2b51cdd3b250b1ef593c43ba2407e2e006443101556c
|
|
7
|
+
data.tar.gz: 5c62a4b4dd5a142b2a0f8090cac2ff67a2004305bf9c0ca78d2c4c8cb4e7043115d8b9b338180d76ab249af439838fce58ea093bac83dbc26d3936fec5c77659
|
data/bin/sg
CHANGED
|
@@ -64,29 +64,6 @@ ENV['RACK_ENV'] = options[:environment].to_s
|
|
|
64
64
|
# Force process mode on Windows (pipes + sockets not working at the moment)
|
|
65
65
|
ENV['SG_MODE'] = 'no_ipc' if ::FFI::Platform.windows?
|
|
66
66
|
|
|
67
|
-
::
|
|
68
|
-
logger.progress do |level, errorid, error|
|
|
69
|
-
begin
|
|
70
|
-
puts "Log called: #{level}: #{errorid}\n#{error.message}\n#{error.backtrace.join("\n")}\n"
|
|
71
|
-
rescue Exception
|
|
72
|
-
p 'error in gazelle logger'
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
puts "Look out! Here comes Spider-Gazelle #{::SpiderGazelle::VERSION}!"
|
|
77
|
-
puts "* Environment: #{ENV['RACK_ENV']} on #{RUBY_ENGINE || 'ruby'} #{RUBY_VERSION}"
|
|
78
|
-
server = ::SpiderGazelle::Spider.instance
|
|
79
|
-
server.loaded.then do
|
|
80
|
-
puts "* Loading: #{options[:rackup]}"
|
|
81
|
-
server.load(options[:rackup], options).catch(proc {|e|
|
|
82
|
-
puts "#{e.message}\n#{e.backtrace.join("\n") unless e.backtrace.nil?}\n"
|
|
83
|
-
}).finally do
|
|
84
|
-
# This will execute if the TCP binding is lost
|
|
85
|
-
server.shutdown
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
puts "* Listening on tcp://#{options[:host]}:#{options[:port]}"
|
|
89
|
-
end
|
|
90
|
-
end
|
|
67
|
+
::SpiderGazelle::Spider.run options[:rackup], options
|
|
91
68
|
|
|
92
69
|
puts "\nSpider-Gazelle leaps through the veldt"
|
|
@@ -3,45 +3,37 @@ require 'spider-gazelle'
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
module Rack
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"Port=PORT" => "Port to listen on (default: 8080)",
|
|
40
|
-
"Quiet" => "Don't report each request"
|
|
41
|
-
}
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
register :sg, SpiderGazelle
|
|
46
|
-
end
|
|
6
|
+
module Handler
|
|
7
|
+
module SpiderGazelle
|
|
8
|
+
DEFAULT_OPTIONS = {
|
|
9
|
+
:Host => '0.0.0.0',
|
|
10
|
+
:Port => 8080,
|
|
11
|
+
:Verbose => false
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
def self.run(app, options = {})
|
|
15
|
+
options = DEFAULT_OPTIONS.merge(options)
|
|
16
|
+
|
|
17
|
+
if options[:Verbose]
|
|
18
|
+
app = Rack::CommonLogger.new(app, STDOUT)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
if options[:environment]
|
|
22
|
+
ENV['RACK_ENV'] = options[:environment].to_s
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
::SpiderGazelle::Spider.run app, options
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.valid_options
|
|
29
|
+
{
|
|
30
|
+
"Host=HOST" => "Hostname to listen on (default: 0.0.0.0)",
|
|
31
|
+
"Port=PORT" => "Port to listen on (default: 8080)",
|
|
32
|
+
"Quiet" => "Don't report each request"
|
|
33
|
+
}
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
register :'spider-gazelle', SpiderGazelle
|
|
38
|
+
end
|
|
47
39
|
end
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
require 'thread'
|
|
2
|
-
require 'radix'
|
|
2
|
+
require 'radix/base'
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
module SpiderGazelle
|
|
@@ -14,11 +14,13 @@ module SpiderGazelle
|
|
|
14
14
|
@loaded = ThreadSafe::Cache.new
|
|
15
15
|
|
|
16
16
|
# Load an app and assign it an ID
|
|
17
|
-
def self.load(
|
|
18
|
-
|
|
17
|
+
def self.load(app, options={})
|
|
18
|
+
is_rack_app = !app.is_a?(String)
|
|
19
|
+
app_key = is_rack_app ? app.class.name.to_sym : app.to_sym
|
|
20
|
+
id = @loaded[app_key]
|
|
19
21
|
|
|
20
22
|
if id.nil?
|
|
21
|
-
app, options = ::Rack::Builder.parse_file
|
|
23
|
+
app, options = ::Rack::Builder.parse_file(app) unless is_rack_app
|
|
22
24
|
|
|
23
25
|
count = 0
|
|
24
26
|
@mutex.synchronize {
|
|
@@ -26,7 +28,7 @@ module SpiderGazelle
|
|
|
26
28
|
}
|
|
27
29
|
id = Radix.convert(count, B10, B65).to_sym
|
|
28
30
|
@apps[id] = app
|
|
29
|
-
@loaded[
|
|
31
|
+
@loaded[app_key] = id
|
|
30
32
|
end
|
|
31
33
|
|
|
32
34
|
id
|
|
@@ -5,8 +5,8 @@ require 'set'
|
|
|
5
5
|
module SpiderGazelle
|
|
6
6
|
class Binding
|
|
7
7
|
DEFAULT_OPTIONS = {
|
|
8
|
-
:
|
|
9
|
-
:
|
|
8
|
+
:Host => '0.0.0.0',
|
|
9
|
+
:Port => 3000,
|
|
10
10
|
:tls => false,
|
|
11
11
|
:optimize_for_latency => true,
|
|
12
12
|
:backlog => 1024
|
|
@@ -21,7 +21,7 @@ module SpiderGazelle
|
|
|
21
21
|
@options = DEFAULT_OPTIONS.merge(options)
|
|
22
22
|
@loop = loop
|
|
23
23
|
@delegate = delegate
|
|
24
|
-
@port = @options[:
|
|
24
|
+
@port = @options[:Port]
|
|
25
25
|
@tls = @options[:tls]
|
|
26
26
|
@optimize = @options[:optimize_for_latency]
|
|
27
27
|
|
|
@@ -34,7 +34,7 @@ module SpiderGazelle
|
|
|
34
34
|
def bind
|
|
35
35
|
# Bind the socket
|
|
36
36
|
@tcp = @loop.tcp
|
|
37
|
-
@tcp.bind(@options[:
|
|
37
|
+
@tcp.bind(@options[:Host], @port, @new_connection)
|
|
38
38
|
@tcp.listen(@options[:backlog])
|
|
39
39
|
|
|
40
40
|
# Delegate errors
|
|
@@ -197,8 +197,6 @@ module SpiderGazelle
|
|
|
197
197
|
|
|
198
198
|
# If a file, stream the body in a non-blocking fashion
|
|
199
199
|
if body.respond_to? :to_path
|
|
200
|
-
headers[CONNECTION] = CLOSE if @request.keep_alive == false
|
|
201
|
-
|
|
202
200
|
if headers[CONTENT_LENGTH]
|
|
203
201
|
type = :raw
|
|
204
202
|
else
|
|
@@ -250,8 +248,6 @@ module SpiderGazelle
|
|
|
250
248
|
end
|
|
251
249
|
|
|
252
250
|
def write_response(status, headers, body)
|
|
253
|
-
headers[CONNECTION] = CLOSE if @request.keep_alive == false
|
|
254
|
-
|
|
255
251
|
if headers[CONTENT_LENGTH]
|
|
256
252
|
headers[CONTENT_LENGTH] = headers[CONTENT_LENGTH].to_s
|
|
257
253
|
write_headers(status, headers)
|
|
@@ -282,6 +278,8 @@ module SpiderGazelle
|
|
|
282
278
|
end
|
|
283
279
|
|
|
284
280
|
def write_headers(status, headers)
|
|
281
|
+
headers[CONNECTION] = CLOSE if @request.keep_alive == false
|
|
282
|
+
|
|
285
283
|
header = "HTTP/1.1 #{status} #{fetch_code(status)}\r\n"
|
|
286
284
|
headers.each do |key, value|
|
|
287
285
|
next if key.start_with? RACK
|
|
@@ -87,6 +87,8 @@ module SpiderGazelle
|
|
|
87
87
|
@env.delete(HTTP_CONNECTION)
|
|
88
88
|
|
|
89
89
|
@env[REQUEST_URI] = @url.freeze
|
|
90
|
+
# For Rack::Lint on 1.9, ensure that the encoding is always for spec
|
|
91
|
+
@body.force_encoding('ASCII-8BIT') if @body.respond_to?(:force_encoding)
|
|
90
92
|
@env[RACK_INPUT] = StringIO.new(@body)
|
|
91
93
|
|
|
92
94
|
# Break the request into its components
|
|
@@ -99,6 +101,7 @@ module SpiderGazelle
|
|
|
99
101
|
else
|
|
100
102
|
@env[PATH_INFO] = @url
|
|
101
103
|
@env[REQUEST_PATH] = @url
|
|
104
|
+
@env[QUERY_STRING] = ''
|
|
102
105
|
end
|
|
103
106
|
|
|
104
107
|
# Grab the host name from the request
|
|
@@ -17,6 +17,11 @@ module SpiderGazelle
|
|
|
17
17
|
STATES = [:reanimating, :running, :squashing, :dead]
|
|
18
18
|
MODES = [:thread, :process, :no_ipc] # TODO:: implement clustering using processes
|
|
19
19
|
|
|
20
|
+
DEFAULT_OPTIONS = {
|
|
21
|
+
:Host => '0.0.0.0',
|
|
22
|
+
:Port => 8080,
|
|
23
|
+
:Verbose => false
|
|
24
|
+
}
|
|
20
25
|
|
|
21
26
|
attr_reader :state, :mode, :threads, :logger
|
|
22
27
|
|
|
@@ -66,6 +71,42 @@ module SpiderGazelle
|
|
|
66
71
|
end
|
|
67
72
|
end
|
|
68
73
|
|
|
74
|
+
def run(&block)
|
|
75
|
+
@web.run &block
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def self.run(app, options = {})
|
|
79
|
+
options = DEFAULT_OPTIONS.merge(options)
|
|
80
|
+
|
|
81
|
+
instance.run do |logger|
|
|
82
|
+
logger.progress do |level, errorid, error|
|
|
83
|
+
begin
|
|
84
|
+
puts "Log called: #{level}: #{errorid}\n#{error.message}\n#{error.backtrace.join("\n")}\n"
|
|
85
|
+
rescue Exception
|
|
86
|
+
p 'error in gazelle logger'
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
puts "Look out! Here comes Spider-Gazelle #{::SpiderGazelle::VERSION}!"
|
|
91
|
+
puts "* Environment: #{ENV['RACK_ENV']} on #{RUBY_ENGINE || 'ruby'} #{RUBY_VERSION}"
|
|
92
|
+
server = ::SpiderGazelle::Spider.instance
|
|
93
|
+
server.loaded.then do
|
|
94
|
+
puts "* Loading: #{app}"
|
|
95
|
+
|
|
96
|
+
# yield server if block_given?
|
|
97
|
+
|
|
98
|
+
server.load(app, options).catch(proc {|e|
|
|
99
|
+
puts "#{e.message}\n#{e.backtrace.join("\n") unless e.backtrace.nil?}\n"
|
|
100
|
+
}).finally do
|
|
101
|
+
# This will execute if the TCP binding is lost
|
|
102
|
+
server.shutdown
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
puts "* Listening on tcp://#{options[:Host]}:#{options[:Port]}"
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
69
110
|
# Provides a promise that resolves when we are read to start binding applications
|
|
70
111
|
#
|
|
71
112
|
# @return [::Libuv::Q::Promise] that indicates when the gazelles are loaded
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
require 'websocket/driver'
|
|
2
|
+
require 'forwardable'
|
|
2
3
|
|
|
3
4
|
|
|
4
5
|
module SpiderGazelle
|
|
5
6
|
# TODO:: make a promise that resolves when closed
|
|
6
7
|
class Websocket < ::Libuv::Q::DeferredPromise
|
|
7
|
-
attr_reader :env, :url, :
|
|
8
|
+
attr_reader :env, :url, :loop
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
def initialize(tcp, env)
|
|
@@ -29,10 +30,15 @@ module SpiderGazelle
|
|
|
29
30
|
@driver.on(:error, &method(:on_error))
|
|
30
31
|
end
|
|
31
32
|
|
|
32
|
-
def start
|
|
33
|
-
@driver.start
|
|
34
|
-
end
|
|
35
33
|
|
|
34
|
+
extend Forwardable
|
|
35
|
+
def_delegators :@driver, :start, :ping, :protocol, :ready_state, :set_header, :state, :close
|
|
36
|
+
def_delegators :@socket, :write
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# Write some text to the websocket connection
|
|
40
|
+
#
|
|
41
|
+
# @param string [String] a string of data to be sent to the far end
|
|
36
42
|
def text(string)
|
|
37
43
|
data = string.to_s
|
|
38
44
|
@loop.schedule do
|
|
@@ -40,6 +46,9 @@ module SpiderGazelle
|
|
|
40
46
|
end
|
|
41
47
|
end
|
|
42
48
|
|
|
49
|
+
# Write some binary data to the websocket connection
|
|
50
|
+
#
|
|
51
|
+
# @param array [Array] an array of bytes to be sent to the far end
|
|
43
52
|
def binary(array)
|
|
44
53
|
data = array.to_a
|
|
45
54
|
@loop.schedule do
|
|
@@ -47,13 +56,20 @@ module SpiderGazelle
|
|
|
47
56
|
end
|
|
48
57
|
end
|
|
49
58
|
|
|
59
|
+
# Used to define a callback when data is received from the client
|
|
60
|
+
#
|
|
61
|
+
# @param callback [Proc] the callback to be called when data is received
|
|
50
62
|
def progress(callback = nil, &blk)
|
|
51
63
|
@progress = callback || blk
|
|
52
64
|
end
|
|
53
65
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
66
|
+
# Used to define a callback when the websocket connection is established
|
|
67
|
+
# Data sent before this callback is buffered.
|
|
68
|
+
#
|
|
69
|
+
# @param callback [Proc] the callback to be triggered on establishment
|
|
70
|
+
def on_open(callback = nil, &blk)
|
|
71
|
+
callback ||= blk
|
|
72
|
+
@driver.on(:open, &callback)
|
|
57
73
|
end
|
|
58
74
|
|
|
59
75
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: spider-gazelle
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stephen von Takach
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2014-01-
|
|
11
|
+
date: 2014-01-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rake
|