spider-gazelle 3.0.2 → 3.0.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: 1eb9ae4b8211936cdaf58a02132000044bb58ae3
4
- data.tar.gz: 7044a353674ec95eb7aea471e1fc619641b4ec15
3
+ metadata.gz: 89774225b2801a3f2556563940da21588a6fef70
4
+ data.tar.gz: 441d840391e7ccb87d98b4bd2830b80a2ed6b1e6
5
5
  SHA512:
6
- metadata.gz: deff3abf19ba3fdf58250e0b47b27658b4ec183cc5ee5d8f3860c47563314a144aeed2e4efd40de1157d4777976fbfd962fdd74c280d1882264c1b038306a24c
7
- data.tar.gz: 72d2d3b04dc181fd1f39d97425123664d2b5c4c2886f2e50d74cd58751231414b2a2de99ecfe82a77a5b711e0586eb775e14080e360ad5a3a8629412d6f0d37b
6
+ metadata.gz: 96c3c3b76bf21d2756db7e9b51a50f4125ed26a8b60f12ba8e789b0e73aff65ccdd0a933254485bb600f340ce82b42f9bc8c324deb27eec29a1f14002c762712
7
+ data.tar.gz: 1208f6382502b44b2f02099fd527441d0e923100c7c26801fd5582a48fb53c698d25672e7b85f4f95ddd159ca7c29d7570523bf514b389a64fdbf137855d75b4
@@ -62,13 +62,12 @@ module SpiderGazelle
62
62
  end
63
63
 
64
64
  PROTOCOLS = ['h2', 'http/1.1'].freeze
65
- FALLBACK = 'http/1.1'
66
65
  def self.configure_tls(opts)
67
66
  return false unless opts[:tls]
68
67
 
69
68
  tls = {
70
69
  protocols: PROTOCOLS,
71
- fallback: FALLBACK
70
+ fallback: 'http/1.1'
72
71
  }
73
72
  tls[:verify_peer] = true if opts[:verify_peer]
74
73
  tls[:ciphers] = opts[:ciphers] if opts[:ciphers]
@@ -31,11 +31,6 @@ module SpiderGazelle
31
31
  req.header.frozen? ? req.header = header : req.header << header
32
32
  end
33
33
 
34
- DASH = '-'
35
- UNDERSCORE = '_'
36
- HTTP_META = 'HTTP_'
37
- COMMA = ', '
38
-
39
34
  def on_header_value(parser, value)
40
35
  req = @connection.parsing
41
36
  if req.header.frozen?
@@ -43,11 +38,11 @@ module SpiderGazelle
43
38
  else
44
39
  header = req.header
45
40
  header.upcase!
46
- header.gsub!(DASH, UNDERSCORE)
47
- header.prepend(HTTP_META)
41
+ header.gsub!('-', '_')
42
+ header.prepend('HTTP_')
48
43
  header.freeze
49
44
  if req.env[header]
50
- req.env[header] << COMMA
45
+ req.env[header] << ', '
51
46
  req.env[header] << value
52
47
  else
53
48
  req.env[header] = String.new(value)
@@ -99,16 +94,13 @@ module SpiderGazelle
99
94
  def self.on_progress(data, socket); end
100
95
  DUMMY_PROGRESS = self.method :on_progress
101
96
 
102
- HTTP = 'http'
103
- HTTPS = 'https'
104
-
105
97
  def load(socket, port, app, tls)
106
98
  @socket = socket
107
99
  @port = port
108
100
  @app = app
109
101
 
110
102
  @remote_ip = socket.peername[0]
111
- @scheme = tls ? HTTPS : HTTP
103
+ @scheme = tls ? 'https' : 'http'
112
104
 
113
105
  set_on_close(socket)
114
106
  end
@@ -161,12 +153,10 @@ module SpiderGazelle
161
153
  @parsing = Request.new @thread, @app, @port, @remote_ip, @scheme, @socket
162
154
  end
163
155
 
164
- REQUEST_METHOD = 'REQUEST_METHOD'
165
156
  def headers_complete
166
- @parsing.env[REQUEST_METHOD] = @state.http_method.to_s
157
+ @parsing.env['REQUEST_METHOD'] = @state.http_method.to_s
167
158
  end
168
159
 
169
- ASYNC = "async.callback"
170
160
  def finished_parsing
171
161
  request = @parsing
172
162
  @parsing = nil
@@ -180,7 +170,7 @@ module SpiderGazelle
180
170
  # Process the async request in the same way as Mizuno
181
171
  # See: http://polycrystal.org/2012/04/15/asynchronous_responses_in_rack.html
182
172
  # Process a response that was marked as async.
183
- request.env[ASYNC] = proc { |data|
173
+ request.env['async.callback'] = proc { |data|
184
174
  @thread.schedule { request.defer.resolve([request, data]) }
185
175
  }
186
176
  request.upgrade = @state.upgrade?
@@ -235,16 +225,6 @@ module SpiderGazelle
235
225
  process_next
236
226
  end
237
227
 
238
-
239
- HEAD = 'HEAD'
240
- ETAG = 'ETag'
241
- HTTP_ETAG = 'HTTP_ETAG'
242
- CONTENT_LENGTH2 = 'Content-Length'
243
- TRANSFER_ENCODING = 'Transfer-Encoding'
244
- CHUNKED = 'chunked'
245
- ZERO = '0'
246
- NOT_MODIFIED_304 = "HTTP/1.1 304 Not Modified\r\n"
247
-
248
228
  def send_next_response
249
229
  request, result = @responses.shift
250
230
  @transmitting = request
@@ -262,7 +242,7 @@ module SpiderGazelle
262
242
  body.close if body.respond_to?(:close)
263
243
  else
264
244
  status, headers, body = result
265
- send_body = request.env[REQUEST_METHOD] != HEAD
245
+ send_body = request.env['REQUEST_METHOD'] != 'HEAD'
266
246
 
267
247
  # If a file, stream the body in a non-blocking fashion
268
248
  if body.respond_to? :to_path
@@ -280,17 +260,17 @@ module SpiderGazelle
280
260
  #if etag == request.env[HTTP_ETAG]
281
261
  # header = NOT_MODIFIED_304.dup
282
262
  # add_header(header, ETAG, etag)
283
- # header << LINE_END
263
+ # header << "\r\n"
284
264
  # @socket.write header
285
265
  # return
286
266
  #end
287
267
  #headers[ETAG] ||= etag
288
268
 
289
- if headers[CONTENT_LENGTH2]
269
+ if headers['Content-Length']
290
270
  type = :raw
291
271
  else
292
272
  type = :http
293
- headers[TRANSFER_ENCODING] = CHUNKED
273
+ headers['Transfer-Encoding'] = 'chunked'
294
274
  end
295
275
 
296
276
  data_written = true
@@ -339,7 +319,7 @@ module SpiderGazelle
339
319
  # Optimize the response
340
320
  begin
341
321
  if body.size < 2
342
- headers[CONTENT_LENGTH2] = body.size == 1 ? body[0].bytesize.to_s : ZERO
322
+ headers['Content-Length'] = body.size == 1 ? body[0].bytesize.to_s : '0'
343
323
  end
344
324
  rescue # just in case
345
325
  end
@@ -359,59 +339,51 @@ module SpiderGazelle
359
339
  end
360
340
  end
361
341
 
362
- CLOSE_CHUNKED = "0\r\n\r\n"
363
342
  def write_response(request, status, headers, body)
364
343
  keep_alive = request.keep_alive
365
344
 
366
- if headers[CONTENT_LENGTH2]
367
- headers[CONTENT_LENGTH2] = headers[CONTENT_LENGTH2].to_s
345
+ if headers['Content-Length']
346
+ headers['Content-Length'] = headers['Content-Length'].to_s
368
347
  write_headers keep_alive, status, headers
369
348
 
370
349
  # Stream the response (pass directly into @socket.write)
371
350
  body.each &@socket.method(:write)
372
351
  @socket.shutdown if keep_alive == false
373
352
  else
374
- headers[TRANSFER_ENCODING] = CHUNKED
353
+ headers['Transfer-Encoding'] = 'chunked'
375
354
  write_headers keep_alive, status, headers
376
355
 
377
356
  # Stream the response
378
357
  body.each &@write_chunk
379
358
 
380
- @socket.write CLOSE_CHUNKED
359
+ @socket.write "0\r\n\r\n"
381
360
  @socket.shutdown if keep_alive == false
382
361
  end
383
362
 
384
363
  body.close if body.respond_to?(:close)
385
364
  end
386
365
 
387
- COLON_SPACE = ': '
388
- LINE_END = "\r\n"
389
366
  def add_header(header, key, value)
390
367
  header << key
391
- header << COLON_SPACE
368
+ header << ': '
392
369
  header << value
393
- header << LINE_END
370
+ header << "\r\n"
394
371
  end
395
372
 
396
- CONNECTION = "Connection"
397
- NEWLINE = "\n"
398
- CLOSE = "close"
399
- RACK = "rack"
400
373
  def write_headers(keep_alive, status, headers)
401
- headers[CONNECTION] = CLOSE if keep_alive == false
374
+ headers['Connection'] = 'close' if keep_alive == false
402
375
 
403
376
  header = String.new("HTTP/1.1 #{status} #{fetch_code(status)}\r\n")
404
377
  headers.each do |key, value|
405
- next if key.start_with? RACK
406
- value.to_s.split(NEWLINE).each {|val| add_header(header, key, val)}
378
+ next if key.start_with? 'rack'
379
+ value.to_s.split("\n").each {|val| add_header(header, key, val)}
407
380
  end
408
- header << LINE_END
381
+ header << "\r\n"
409
382
  @socket.write header
410
383
  end
411
384
 
412
- HEX_ENCODED = 16
413
385
  def write_chunk(part)
414
- chunk = part.bytesize.to_s(HEX_ENCODED) << LINE_END << part << LINE_END
386
+ chunk = part.bytesize.to_s(16) << "\r\n" << part << "\r\n"
415
387
  @socket.write chunk
416
388
  end
417
389
 
@@ -446,19 +418,17 @@ module SpiderGazelle
446
418
  end
447
419
  end
448
420
 
449
- ERROR_400_RESPONSE = "HTTP/1.1 400 Bad Request\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"
450
421
  def send_parsing_error
451
422
  @logger.info "Parsing error!"
452
423
  @socket.stop_read
453
- @socket.write ERROR_400_RESPONSE
424
+ @socket.write "HTTP/1.1 400 Bad Request\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"
454
425
  @socket.shutdown
455
426
  end
456
427
 
457
- ERROR_500_RESPONSE = "HTTP/1.1 500 Internal Server Error\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"
458
428
  def send_internal_error
459
429
  @logger.info "Internal error"
460
430
  @socket.stop_read
461
- @socket.write ERROR_500_RESPONSE
431
+ @socket.write "HTTP/1.1 500 Internal Server Error\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"
462
432
  @socket.shutdown
463
433
  end
464
434
  end
@@ -5,46 +5,26 @@ require 'rack' # Ruby webserver abstraction
5
5
 
6
6
  module SpiderGazelle
7
7
  class Request < ::Libuv::Q::DeferredPromise
8
- RACK_VERSION = 'rack.version'
9
- RACK_ERRORS = 'rack.errors'
10
- RACK_MULTITHREAD = "rack.multithread"
11
- RACK_MULTIPROCESS = "rack.multiprocess"
12
- RACK_RUN_ONCE = "rack.run_once"
13
- SCRIPT_NAME = "SCRIPT_NAME"
14
- EMPTY = ''
15
- SERVER_PROTOCOL = "SERVER_PROTOCOL"
16
- HTTP_11 = "HTTP/1.1"
17
- SERVER_SOFTWARE = "SERVER_SOFTWARE"
18
- GATEWAY_INTERFACE = "GATEWAY_INTERFACE"
19
- CGI_VER = "CGI/1.2"
20
- SERVER = "SpiderGazelle"
21
- LOCALHOST = 'localhost'
22
-
23
8
 
24
9
  # TODO:: Add HTTP headers to the env and capitalise them and prefix them with HTTP_
25
10
  # convert - signs to underscores
26
11
  PROTO_ENV = {
27
- RACK_VERSION => ::Rack::VERSION, # Should be an array of integers
28
- RACK_ERRORS => $stderr, # An error stream that supports: puts, write and flush
29
- RACK_MULTITHREAD => true, # can the app be simultaneously invoked by another thread?
30
- RACK_MULTIPROCESS => true, # will the app be simultaneously be invoked in a separate process?
31
- RACK_RUN_ONCE => false, # this isn't CGI so will always be false
32
-
33
- SCRIPT_NAME => ENV['SCRIPT_NAME'] || EMPTY, # The virtual path of the app base (empty if root)
34
- SERVER_PROTOCOL => HTTP_11,
35
-
36
- GATEWAY_INTERFACE => CGI_VER,
37
- SERVER_SOFTWARE => SERVER
12
+ 'rack.version' => ::Rack::VERSION, # Should be an array of integers
13
+ 'rack.errors' => $stderr, # An error stream that supports: puts, write and flush
14
+ 'rack.multithread' => true, # can the app be simultaneously invoked by another thread?
15
+ 'rack.multiprocess' => false, # will the app be simultaneously be invoked in a separate process?
16
+ 'rack.run_once' => false, # this isn't CGI so will always be false
17
+ 'SCRIPT_NAME' => ENV['SCRIPT_NAME'] || '', # The virtual path of the app base (empty if root)
18
+ 'SERVER_PROTOCOL' => 'HTTP/1.1',
19
+
20
+ 'GATEWAY_INTERFACE' => 'CGI/1.2',
21
+ 'SERVER_SOFTWARE' => 'SpiderGazelle'
38
22
  }
39
23
 
40
24
  attr_accessor :env, :url, :header, :body, :keep_alive, :upgrade
41
25
  attr_reader :hijacked, :defer, :is_async
42
26
 
43
27
 
44
- SERVER_PORT = "SERVER_PORT"
45
- REMOTE_ADDR = "REMOTE_ADDR"
46
- RACK_URL_SCHEME = "rack.url_scheme"
47
-
48
28
  def initialize(thread, app, port, remote_ip, scheme, socket)
49
29
  super(thread, thread.defer)
50
30
 
@@ -54,81 +34,53 @@ module SpiderGazelle
54
34
  @header = String.new
55
35
  @url = String.new
56
36
  @env = PROTO_ENV.dup
57
- @env[SERVER_PORT] = port
58
- @env[REMOTE_ADDR] = remote_ip
59
- @env[RACK_URL_SCHEME] = scheme
37
+ @env['SERVER_PORT'] = port
38
+ @env['REMOTE_ADDR'] = remote_ip
39
+ @env['rack.url_scheme'] = scheme
60
40
  end
61
-
62
-
63
- CONTENT_LENGTH = "CONTENT_LENGTH"
64
- HTTP_CONTENT_LENGTH = "HTTP_CONTENT_LENGTH"
65
- CONTENT_TYPE = "CONTENT_TYPE"
66
- HTTP_CONTENT_TYPE = "HTTP_CONTENT_TYPE"
67
- DEFAULT_TYPE = "text/plain"
68
- REQUEST_URI= "REQUEST_URI"
69
- ASCII_8BIT = "ASCII-8BIT"
70
- RACK_INPUT = "rack.input"
71
- PATH_INFO = "PATH_INFO"
72
- REQUEST_PATH = "REQUEST_PATH"
73
- QUERY_STRING = "QUERY_STRING"
74
- HTTP_HOST = "HTTP_HOST"
75
- COLON = ":"
76
- SERVER_NAME = "SERVER_NAME"
77
- # Hijacking IO is supported
78
- HIJACK_P = "rack.hijack?"
79
- # Callback for indicating that this socket will be hijacked
80
- HIJACK = "rack.hijack"
81
- # The object for performing IO on after hijack is called
82
- HIJACK_IO = "rack.hijack_io"
83
- QUESTION_MARK = "?"
84
41
 
85
- HTTP_UPGRADE = 'HTTP_UPGRADE'
86
- USE_HTTP2 = 'h2c'
87
-
88
-
89
-
90
42
 
91
43
  def execute!
92
- @env[CONTENT_LENGTH] = @env.delete(HTTP_CONTENT_LENGTH) || @body.bytesize.to_s
93
- @env[CONTENT_TYPE] = @env.delete(HTTP_CONTENT_TYPE) || DEFAULT_TYPE
94
- @env[REQUEST_URI] = @url.freeze
44
+ @env['CONTENT_LENGTH'] = @env.delete('HTTP_CONTENT_LENGTH') || @body.bytesize.to_s
45
+ @env['CONTENT_TYPE'] = @env.delete('HTTP_CONTENT_TYPE') || 'text/plain'
46
+ @env['REQUEST_URI'] = @url.freeze
95
47
 
96
48
  # For Rack::Lint on 1.9, ensure that the encoding is always for spec
97
- @body.force_encoding(ASCII_8BIT)
98
- @env[RACK_INPUT] = StringIO.new @body
49
+ @body.force_encoding(Encoding::ASCII_8BIT)
50
+ @env['rack.input'] = StringIO.new @body
99
51
 
100
52
  # Break the request into its components
101
- query_start = @url.index QUESTION_MARK
53
+ query_start = @url.index '?'
102
54
  if query_start
103
55
  path = @url[0...query_start].freeze
104
- @env[PATH_INFO] = path
105
- @env[REQUEST_PATH] = path
106
- @env[QUERY_STRING] = @url[query_start + 1..-1].freeze
56
+ @env['PATH_INFO'] = path
57
+ @env['REQUEST_PATH'] = path
58
+ @env['QUERY_STRING'] = @url[query_start + 1..-1].freeze
107
59
  else
108
- @env[PATH_INFO] = @url
109
- @env[REQUEST_PATH] = @url
110
- @env[QUERY_STRING] = EMPTY
60
+ @env['PATH_INFO'] = @url
61
+ @env['REQUEST_PATH'] = @url
62
+ @env['QUERY_STRING'] = ''
111
63
  end
112
64
 
113
65
  # Grab the host name from the request
114
- if host = @env[HTTP_HOST]
115
- if colon = host.index(COLON)
116
- @env[SERVER_NAME] = host[0, colon]
117
- @env[SERVER_PORT] = host[colon + 1, host.bytesize]
66
+ if host = @env['HTTP_HOST']
67
+ if colon = host.index(':')
68
+ @env['SERVER_NAME'] = host[0, colon]
69
+ @env['SERVER_PORT'] = host[colon + 1, host.bytesize]
118
70
  else
119
- @env[SERVER_NAME] = host
71
+ @env['SERVER_NAME'] = host
120
72
  end
121
73
  else
122
- @env[SERVER_NAME] = LOCALHOST
74
+ @env['SERVER_NAME'] = 'localhost'
123
75
  end
124
76
 
125
- if @upgrade == true && @env[HTTP_UPGRADE] == USE_HTTP2
77
+ if @upgrade == true && @env['HTTP_UPGRADE'] == 'h2c'
126
78
  # TODO:: implement the upgrade process here
127
79
  end
128
80
 
129
81
  # Provide hijack options
130
- @env[HIJACK_P] = true
131
- @env[HIJACK] = proc { @env[HIJACK_IO] = @socket }
82
+ @env['rack.hijack?'] = true
83
+ @env['rack.hijack'] = proc { @env['rack.hijack_io'] = @socket }
132
84
 
133
85
  # Execute the request
134
86
  # NOTE:: Catch was overloaded by Promise so this does the trick now
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SpiderGazelle
4
- VERSION = '3.0.2'
4
+ VERSION = '3.0.3'
5
5
  EXEC_NAME = 'sg'
6
6
  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: 3.0.2
4
+ version: 3.0.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: 2016-11-14 00:00:00.000000000 Z
11
+ date: 2016-11-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http-parser