spider-gazelle 3.0.2 → 3.0.3
Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 89774225b2801a3f2556563940da21588a6fef70
|
4
|
+
data.tar.gz: 441d840391e7ccb87d98b4bd2830b80a2ed6b1e6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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:
|
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!(
|
47
|
-
header.prepend(
|
41
|
+
header.gsub!('-', '_')
|
42
|
+
header.prepend('HTTP_')
|
48
43
|
header.freeze
|
49
44
|
if req.env[header]
|
50
|
-
req.env[header] <<
|
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 ?
|
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[
|
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 <<
|
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[
|
269
|
+
if headers['Content-Length']
|
290
270
|
type = :raw
|
291
271
|
else
|
292
272
|
type = :http
|
293
|
-
headers[
|
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[
|
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[
|
367
|
-
headers[
|
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[
|
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
|
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 <<
|
368
|
+
header << ': '
|
392
369
|
header << value
|
393
|
-
header <<
|
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[
|
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?
|
406
|
-
value.to_s.split(
|
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 <<
|
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(
|
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
|
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
|
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
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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[
|
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) ||
|
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[
|
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
|
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] =
|
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(
|
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] =
|
74
|
+
@env['SERVER_NAME'] = 'localhost'
|
123
75
|
end
|
124
76
|
|
125
|
-
if @upgrade == true && @env[HTTP_UPGRADE] ==
|
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[
|
131
|
-
@env[
|
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
|
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.
|
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-
|
11
|
+
date: 2016-11-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: http-parser
|