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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 389b76b304d2c434532df00b18f0e772b7bca616
4
- data.tar.gz: de17af1941a3ce3cf24a65ec069a1e33bf5490f6
3
+ metadata.gz: ddf67f2f83bb093e412603cfaccbdff9465fd492
4
+ data.tar.gz: 418b883c22f28aec01358f7e1583b5102eed3452
5
5
  SHA512:
6
- metadata.gz: d3751fe5f50137772b2b434cf8ab2bbbeb8c597e343977ca99fd43de1cc5592f7897d756ae04e1ba4d81adbe60de712ab6f8169a42eb3a62bc9b91b6ccd60d90
7
- data.tar.gz: 1bd6d81f822682a1c52b0c1f843e0f3323f69cc80e7effd755c092874fd6019692f8a705d92d87509393654034ac3a0d885b4c43ad88660f2247fc6834df5734
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
- ::Libuv::Loop.default.run do |logger|
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
- 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
- server = ::SpiderGazelle::Spider.new(app, options)
26
-
27
- puts "Spider-Gazelle #{::SpiderGazelle::VERSION} starting..."
28
- puts "* Environment: #{ENV['RACK_ENV']}"
29
- puts "* Listening on tcp://#{options[:Host]}:#{options[:Port]}"
30
-
31
- yield server if block_given?
32
-
33
- server.run
34
- end
35
-
36
- def self.valid_options
37
- {
38
- "Host=HOST" => "Hostname to listen on (default: 0.0.0.0)",
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(rackup)
18
- id = @loaded[rackup.to_sym]
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 rackup
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[rackup.to_sym] = id
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
- :host => '0.0.0.0',
9
- :port => 3000,
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[:port]
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[:host], @port, @new_connection)
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, :driver, :socket
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
- def write(data)
56
- @socket.write(data)
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
 
@@ -1,3 +1,3 @@
1
1
  module SpiderGazelle
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
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.2
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-19 00:00:00.000000000 Z
11
+ date: 2014-01-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake