spider-gazelle 1.2.0 → 2.0.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.
@@ -1,206 +0,0 @@
1
- # Thanks to Puma https://github.com/puma/puma/blob/master/lib/puma/const.rb
2
- require "rack"
3
-
4
- module SpiderGazelle
5
- # UnsupportedOption = Class.new(RuntimeError)
6
-
7
- # Every standard HTTP code mapped to the appropriate message. These are
8
- # used so frequently that they are placed directly in SpiderGazelle for easy
9
- # access rather than SpiderGazelle::Const itself.
10
- HTTP_STATUS_CODES = Rack::Utils::HTTP_STATUS_CODES
11
-
12
- # # For some HTTP status codes the client only expects headers.
13
- # STATUS_WITH_NO_ENTITY_BODY = Hash[Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.map { |s|
14
- # [s, true]
15
- # }]
16
-
17
- # Based on http://rack.rubyforge.org/doc/SPEC.html
18
- # Frequently used constants when constructing requests or responses. Many times
19
- # the constant just refers to a string with the same contents. Using these constants
20
- # gave about a 3% to 10% performance improvement over using the strings directly.
21
- #
22
- # The constants are frozen because Hash#[]= when called with a String key dups
23
- # the String UNLESS the String is frozen. This saves us therefore 2 object
24
- # allocations when creating the env hash later.
25
- #
26
- # While SpiderGazelle does try to emulate the CGI/1.2 protocol, it does not use the REMOTE_IDENT,
27
- # REMOTE_USER, or REMOTE_HOST parameters since those are either a security problem or
28
- # too taxing on performance.
29
- module Const
30
- SPIDER_GAZELLE_VERSION = VERSION = "1.2.0".freeze
31
- # CODE_NAME = "Earl of Sandwich Partition"
32
- SERVER = "SpiderGazelle".freeze
33
-
34
- # FAST_TRACK_KA_TIMEOUT = 0.2
35
-
36
- # # The default number of seconds for another request within a persistent
37
- # # session.
38
- # PERSISTENT_TIMEOUT = 20
39
-
40
- # # The default number of seconds to wait until we get the first data
41
- # # for the request
42
- # FIRST_DATA_TIMEOUT = 30
43
-
44
- # # How long to wait when getting some write blocking on the socket when
45
- # # sending data back
46
- # WRITE_TIMEOUT = 10
47
-
48
- # DATE = "Date".freeze
49
-
50
- SCRIPT_NAME = "SCRIPT_NAME".freeze
51
-
52
- # The original URI requested by the client.
53
- REQUEST_URI= "REQUEST_URI".freeze
54
- REQUEST_PATH = "REQUEST_PATH".freeze
55
-
56
- PATH_INFO = "PATH_INFO".freeze
57
-
58
- # SPIDER_GAZELLE_TMP_BASE = "spider-gazelle".freeze
59
-
60
- # # Indicate that we couldn"t parse the request
61
- ERROR_400_RESPONSE = "HTTP/1.1 400 Bad Request\r\n\r\n".freeze
62
-
63
- # The standard empty 404 response for bad requests. Use Error4040Handler for custom stuff.
64
- ERROR_404_RESPONSE = "HTTP/1.1 404 Not Found\r\nConnection: close\r\nServer: #{SERVER} #{SPIDER_GAZELLE_VERSION}\r\n\r\nNOT FOUND".freeze
65
-
66
- # The standard empty 408 response for requests that timed out.
67
- ERROR_408_RESPONSE = "HTTP/1.1 408 Request Timeout\r\nConnection: close\r\nServer: #{SERVER} #{SPIDER_GAZELLE_VERSION}\r\n\r\n".freeze
68
-
69
- # Indicate that there was an internal error, obviously.
70
- ERROR_500_RESPONSE = "HTTP/1.1 500 Internal Server Error\r\n\r\n".freeze
71
- EMPTY_RESPONSE = [''.freeze].freeze
72
-
73
- # A common header for indicating the server is too busy. Not used yet.
74
- ERROR_503_RESPONSE = "HTTP/1.1 503 Service Unavailable\r\n\r\nBUSY".freeze
75
-
76
- # # The basic max request size we"ll try to read.
77
- # CHUNK_SIZE = 16 * 1024
78
- HEX_SIZE_CHUNKED_RESPONSE = 16
79
- INTERNAL_PIPE_BACKLOG = 16
80
-
81
- # # This is the maximum header that is allowed before a client is booted. The parser detects
82
- # # this, but we"d also like to do this as well.
83
- # MAX_HEADER = 1024 * (80 + 32)
84
-
85
- # # Maximum request body size before it is moved out of memory and into a tempfile for reading.
86
- # MAX_BODY = MAX_HEADER
87
-
88
- # # A frozen format for this is about 15% faster
89
- # STATUS_FORMAT = "HTTP/1.1 %d %s\r\nConnection: close\r\n".freeze
90
-
91
- CONTENT_TYPE = "CONTENT_TYPE".freeze
92
- HTTP_CONTENT_TYPE = "HTTP_CONTENT_TYPE".freeze
93
- DEFAULT_TYPE = "text/plain".freeze
94
-
95
- # LAST_MODIFIED = "Last-Modified".freeze
96
- ETAG = "ETag".freeze
97
- # SLASH = "/".freeze
98
- REQUEST_METHOD = "REQUEST_METHOD".freeze
99
- # GET = "GET".freeze
100
- HEAD = "HEAD".freeze
101
- # # ETag is based on the apache standard of hex mtime-size-inode (inode is 0 on win32)
102
- # ETAG_FORMAT = "\"%x-%x-%x\"".freeze
103
- LINE_END = "\r\n".freeze
104
- REMOTE_ADDR = "REMOTE_ADDR".freeze
105
- # HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR".freeze
106
- # HTTP_IF_MODIFIED_SINCE = "HTTP_IF_MODIFIED_SINCE".freeze
107
- # HTTP_IF_NONE_MATCH = "HTTP_IF_NONE_MATCH".freeze
108
- # REDIRECT = "HTTP/1.1 302 Found\r\nLocation: %s\r\nConnection: close\r\n\r\n".freeze
109
- # HOST = "HOST".freeze
110
-
111
- HTTP_META = "HTTP_".freeze
112
- # Portion of the request following a "?" (empty if none)
113
- QUERY_STRING = "QUERY_STRING".freeze
114
- # Required although HTTP_HOST takes priority if set
115
- SERVER_NAME = "SERVER_NAME".freeze
116
- # Required (set in spider.rb init)
117
- SERVER_PORT = "SERVER_PORT".freeze
118
- HTTP_HOST = "HTTP_HOST".freeze
119
- PORT_80 = "80".freeze
120
- PORT_443 = "443".freeze
121
- LOCALHOST = "localhost".freeze
122
-
123
- HTTP_STATUS_DEFAULT = proc { "CUSTOM" }
124
- SERVER_PROTOCOL = "SERVER_PROTOCOL".freeze
125
- HTTP_11 = "HTTP/1.1".freeze
126
- # HTTP_10 = "HTTP/1.0".freeze
127
-
128
- SERVER_SOFTWARE = "SERVER_SOFTWARE".freeze
129
- GATEWAY_INTERFACE = "GATEWAY_INTERFACE".freeze
130
- CGI_VER = "CGI/1.2".freeze
131
-
132
- # STOP_COMMAND = "?".freeze
133
- # HALT_COMMAND = "!".freeze
134
- # RESTART_COMMAND = "R".freeze
135
-
136
- RACK = "rack".freeze
137
- RACK_VERSION = "rack.version".freeze
138
- RACK_ERRORS = "rack.errors".freeze
139
- RACK_MULTITHREAD = "rack.multithread".freeze
140
- RACK_MULTIPROCESS = "rack.multiprocess".freeze
141
- RACK_RUN_ONCE = "rack.run_once".freeze
142
-
143
- # An IO like object containing all the request body
144
- RACK_INPUT = "rack.input".freeze
145
- # http or https
146
- RACK_URL_SCHEME = "rack.url_scheme".freeze
147
- # RACK_AFTER_REPLY = "rack.after_reply".freeze
148
- # SPIDER_GAZELLE_SOCKET = "spider-gazelle.socket".freeze
149
- # SPIDER_GAZELLE_CONFIG = "spider-gazelle.config".freeze
150
-
151
- ASCII_8BIT = "ASCII-8BIT".freeze
152
-
153
- HTTP = "http".freeze
154
- HTTPS = "https".freeze
155
-
156
- # HTTPS_KEY = "HTTPS".freeze
157
-
158
- # HTTP_VERSION = "HTTP_VERSION".freeze
159
- # HTTP_CONNECTION = "HTTP_CONNECTION".freeze
160
-
161
- # HTTP_11_200 = "HTTP/1.1 200 OK\r\n".freeze
162
- # HTTP_10_200 = "HTTP/1.0 200 OK\r\n".freeze
163
-
164
- CLOSE = "close".freeze
165
- KEEP_ALIVE = "Keep-Alive".freeze
166
-
167
- CONTENT_LENGTH = "CONTENT_LENGTH".freeze
168
- HTTP_CONTENT_LENGTH = "HTTP_CONTENT_LENGTH".freeze
169
- CONTENT_LENGTH2 = "Content-Length".freeze
170
- # CONTENT_LENGTH_S = "Content-Length: ".freeze
171
- TRANSFER_ENCODING = "Transfer-Encoding".freeze
172
-
173
- CONNECTION = "Connection".freeze
174
- # CONNECTION_CLOSE = "Connection: close\r\n".freeze
175
- # CONNECTION_KEEP_ALIVE = "Connection: Keep-Alive\r\n".freeze
176
-
177
- CHUNKED = "chunked".freeze
178
- # TRANSFER_ENCODING_CHUNKED = "Transfer-Encoding: chunked\r\n".freeze
179
- CLOSE_CHUNKED = "0\r\n\r\n".freeze
180
-
181
- COMMA = ", ".freeze
182
- COLON_SPACE = ": ".freeze
183
- COLON = ":".freeze
184
- DASH = "-".freeze
185
- UNDERSCORE = "_".freeze
186
- SPACE = " ".freeze
187
- NEWLINE = "\n".freeze
188
- EMPTY = "".freeze
189
- QUESTION_MARK = "?".freeze
190
-
191
- ZERO = "0".freeze
192
-
193
- # Hijacking IO is supported
194
- HIJACK_P = "rack.hijack?".freeze
195
- # Callback for indicating that this socket will be hijacked
196
- HIJACK = "rack.hijack".freeze
197
- # The object for performing IO on after hijack is called
198
- HIJACK_IO = "rack.hijack_io".freeze
199
-
200
- ASYNC = "async.callback".freeze
201
-
202
- USE_TLS = 'T'.freeze
203
- NO_TLS = 'F'.freeze
204
- KILL_GAZELLE = 'k'.freeze
205
- end
206
- end
@@ -1,103 +0,0 @@
1
- require 'spider-gazelle/const'
2
- require 'stringio'
3
-
4
- module SpiderGazelle
5
- class Request
6
- include Const
7
-
8
- # TODO:: Add HTTP headers to the env and capitalise them and prefix them with HTTP_
9
- # convert - signs to underscores
10
- PROTO_ENV = {
11
- RACK_VERSION => ::Rack::VERSION, # Should be an array of integers
12
- RACK_ERRORS => $stderr, # An error stream that supports: puts, write and flush
13
- RACK_MULTITHREAD => true, # can the app be simultaneously invoked by another thread?
14
- RACK_MULTIPROCESS => false, # will the app be simultaneously be invoked in a separate process?
15
- RACK_RUN_ONCE => false, # this isn't CGI so will always be false
16
-
17
- SCRIPT_NAME => ENV['SCRIPT_NAME'] || EMPTY, # The virtual path of the app base (empty if root)
18
- SERVER_PROTOCOL => HTTP_11,
19
-
20
- GATEWAY_INTERFACE => CGI_VER,
21
- SERVER_SOFTWARE => SERVER
22
- }
23
-
24
- attr_accessor :env, :url, :header, :body, :keep_alive, :upgrade, :deferred
25
- attr_reader :hijacked, :response
26
-
27
- def initialize(connection, app)
28
- @app = app
29
- @body = ''
30
- @header = ''
31
- @url = ''
32
- @env = PROTO_ENV.dup
33
- @loop = connection.loop
34
- @env[SERVER_PORT] = connection.port
35
- @env[REMOTE_ADDR] = connection.remote_ip
36
- @env[RACK_URL_SCHEME] = connection.tls ? HTTPS : HTTP
37
- @env[ASYNC] = connection.async_callback
38
- end
39
-
40
- def execute!
41
- @env[CONTENT_LENGTH] = @env.delete(HTTP_CONTENT_LENGTH) || @body.length
42
- @env[CONTENT_TYPE] = @env.delete(HTTP_CONTENT_TYPE) || DEFAULT_TYPE
43
- @env[REQUEST_URI] = @url.freeze
44
-
45
- # For Rack::Lint on 1.9, ensure that the encoding is always for spec
46
- @body.force_encoding(ASCII_8BIT) if @body.respond_to?(:force_encoding)
47
- @env[RACK_INPUT] = StringIO.new @body
48
-
49
- # Break the request into its components
50
- query_start = @url.index QUESTION_MARK
51
- if query_start
52
- path = @url[0...query_start].freeze
53
- @env[PATH_INFO] = path
54
- @env[REQUEST_PATH] = path
55
- @env[QUERY_STRING] = @url[query_start + 1..-1].freeze
56
- else
57
- @env[PATH_INFO] = @url
58
- @env[REQUEST_PATH] = @url
59
- @env[QUERY_STRING] = EMPTY
60
- end
61
-
62
- # Grab the host name from the request
63
- if host = @env[HTTP_HOST]
64
- if colon = host.index(COLON)
65
- @env[SERVER_NAME] = host[0, colon]
66
- @env[SERVER_PORT] = host[colon+1, host.bytesize]
67
- else
68
- @env[SERVER_NAME] = host
69
- @env[SERVER_PORT] = PROTO_ENV[SERVER_PORT]
70
- end
71
- else
72
- @env[SERVER_NAME] = LOCALHOST
73
- @env[SERVER_PORT] = PROTO_ENV[SERVER_PORT]
74
- end
75
-
76
- # Provide hijack options if this is an upgrade request
77
- if @upgrade == true
78
- @env[HIJACK_P] = true
79
- @env[HIJACK] = method :hijack
80
- end
81
-
82
- # Execute the request
83
- @response = catch(:async) { @app.call @env }
84
- if @response.nil? || @response[0] == -1
85
- @deferred = @loop.defer
86
-
87
- # close the body for deferred responses
88
- unless @response.nil?
89
- body = @response[2]
90
- body.close if body.respond_to?(:close)
91
- end
92
- end
93
- @response
94
- end
95
-
96
- protected
97
-
98
- def hijack
99
- @hijacked = @loop.defer
100
- @env[HIJACK_IO] = @hijacked.promise
101
- end
102
- end
103
- end