rack 2.0.9.3 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rack might be problematic. Click here for more details.

Files changed (201) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +808 -0
  3. data/CONTRIBUTING.md +142 -0
  4. data/{COPYING → MIT-LICENSE} +4 -2
  5. data/README.md +293 -0
  6. data/SPEC.rdoc +340 -0
  7. data/lib/rack/auth/abstract/handler.rb +6 -2
  8. data/lib/rack/auth/abstract/request.rb +4 -2
  9. data/lib/rack/auth/basic.rb +7 -4
  10. data/lib/rack/auth/digest/md5.rb +1 -129
  11. data/lib/rack/auth/digest/nonce.rb +1 -51
  12. data/lib/rack/auth/digest/params.rb +1 -52
  13. data/lib/rack/auth/digest/request.rb +1 -41
  14. data/lib/rack/auth/digest.rb +256 -0
  15. data/lib/rack/body_proxy.rb +18 -15
  16. data/lib/rack/builder.rb +151 -40
  17. data/lib/rack/cascade.rb +30 -12
  18. data/lib/rack/chunked.rb +74 -23
  19. data/lib/rack/common_logger.rb +49 -36
  20. data/lib/rack/conditional_get.rb +33 -26
  21. data/lib/rack/config.rb +2 -0
  22. data/lib/rack/constants.rb +63 -0
  23. data/lib/rack/content_length.rb +13 -16
  24. data/lib/rack/content_type.rb +12 -8
  25. data/lib/rack/deflater.rb +84 -45
  26. data/lib/rack/directory.rb +90 -64
  27. data/lib/rack/etag.rb +17 -23
  28. data/lib/rack/events.rb +23 -20
  29. data/lib/rack/file.rb +5 -172
  30. data/lib/rack/files.rb +216 -0
  31. data/lib/rack/head.rb +10 -9
  32. data/lib/rack/headers.rb +154 -0
  33. data/lib/rack/lint.rb +786 -645
  34. data/lib/rack/lock.rb +4 -6
  35. data/lib/rack/logger.rb +4 -0
  36. data/lib/rack/media_type.rb +10 -5
  37. data/lib/rack/method_override.rb +8 -2
  38. data/lib/rack/mime.rb +17 -1
  39. data/lib/rack/mock.rb +2 -195
  40. data/lib/rack/mock_request.rb +166 -0
  41. data/lib/rack/mock_response.rb +126 -0
  42. data/lib/rack/multipart/generator.rb +21 -15
  43. data/lib/rack/multipart/parser.rb +161 -118
  44. data/lib/rack/multipart/uploaded_file.rb +19 -7
  45. data/lib/rack/multipart.rb +23 -41
  46. data/lib/rack/null_logger.rb +11 -0
  47. data/lib/rack/query_parser.rb +126 -65
  48. data/lib/rack/recursive.rb +9 -5
  49. data/lib/rack/reloader.rb +6 -4
  50. data/lib/rack/request.rb +331 -74
  51. data/lib/rack/response.rb +223 -70
  52. data/lib/rack/rewindable_input.rb +28 -8
  53. data/lib/rack/runtime.rb +11 -8
  54. data/lib/rack/sendfile.rb +42 -33
  55. data/lib/rack/show_exceptions.rb +35 -18
  56. data/lib/rack/show_status.rb +25 -15
  57. data/lib/rack/static.rb +30 -18
  58. data/lib/rack/tempfile_reaper.rb +16 -5
  59. data/lib/rack/urlmap.rb +14 -6
  60. data/lib/rack/utils.rb +268 -260
  61. data/lib/rack/version.rb +34 -0
  62. data/lib/rack.rb +15 -92
  63. metadata +44 -207
  64. data/HISTORY.md +0 -520
  65. data/README.rdoc +0 -316
  66. data/Rakefile +0 -116
  67. data/SPEC +0 -263
  68. data/bin/rackup +0 -4
  69. data/contrib/rack.png +0 -0
  70. data/contrib/rack.svg +0 -150
  71. data/contrib/rack_logo.svg +0 -164
  72. data/contrib/rdoc.css +0 -412
  73. data/example/lobster.ru +0 -4
  74. data/example/protectedlobster.rb +0 -14
  75. data/example/protectedlobster.ru +0 -8
  76. data/lib/rack/handler/cgi.rb +0 -60
  77. data/lib/rack/handler/fastcgi.rb +0 -100
  78. data/lib/rack/handler/lsws.rb +0 -61
  79. data/lib/rack/handler/scgi.rb +0 -70
  80. data/lib/rack/handler/thin.rb +0 -36
  81. data/lib/rack/handler/webrick.rb +0 -120
  82. data/lib/rack/handler.rb +0 -99
  83. data/lib/rack/lobster.rb +0 -70
  84. data/lib/rack/server.rb +0 -395
  85. data/lib/rack/session/abstract/id.rb +0 -510
  86. data/lib/rack/session/cookie.rb +0 -204
  87. data/lib/rack/session/memcache.rb +0 -99
  88. data/lib/rack/session/pool.rb +0 -83
  89. data/rack.gemspec +0 -34
  90. data/test/builder/an_underscore_app.rb +0 -5
  91. data/test/builder/anything.rb +0 -5
  92. data/test/builder/comment.ru +0 -4
  93. data/test/builder/end.ru +0 -5
  94. data/test/builder/line.ru +0 -1
  95. data/test/builder/options.ru +0 -2
  96. data/test/cgi/assets/folder/test.js +0 -1
  97. data/test/cgi/assets/fonts/font.eot +0 -1
  98. data/test/cgi/assets/images/image.png +0 -1
  99. data/test/cgi/assets/index.html +0 -1
  100. data/test/cgi/assets/javascripts/app.js +0 -1
  101. data/test/cgi/assets/stylesheets/app.css +0 -1
  102. data/test/cgi/lighttpd.conf +0 -26
  103. data/test/cgi/rackup_stub.rb +0 -6
  104. data/test/cgi/sample_rackup.ru +0 -5
  105. data/test/cgi/test +0 -9
  106. data/test/cgi/test+directory/test+file +0 -1
  107. data/test/cgi/test.fcgi +0 -9
  108. data/test/cgi/test.gz +0 -0
  109. data/test/cgi/test.ru +0 -5
  110. data/test/gemloader.rb +0 -10
  111. data/test/helper.rb +0 -34
  112. data/test/multipart/bad_robots +0 -259
  113. data/test/multipart/binary +0 -0
  114. data/test/multipart/content_type_and_no_filename +0 -6
  115. data/test/multipart/empty +0 -10
  116. data/test/multipart/fail_16384_nofile +0 -814
  117. data/test/multipart/file1.txt +0 -1
  118. data/test/multipart/filename_and_modification_param +0 -7
  119. data/test/multipart/filename_and_no_name +0 -6
  120. data/test/multipart/filename_with_encoded_words +0 -7
  121. data/test/multipart/filename_with_escaped_quotes +0 -6
  122. data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
  123. data/test/multipart/filename_with_null_byte +0 -7
  124. data/test/multipart/filename_with_percent_escaped_quotes +0 -6
  125. data/test/multipart/filename_with_single_quote +0 -7
  126. data/test/multipart/filename_with_unescaped_percentages +0 -6
  127. data/test/multipart/filename_with_unescaped_percentages2 +0 -6
  128. data/test/multipart/filename_with_unescaped_percentages3 +0 -6
  129. data/test/multipart/filename_with_unescaped_quotes +0 -6
  130. data/test/multipart/ie +0 -6
  131. data/test/multipart/invalid_character +0 -6
  132. data/test/multipart/mixed_files +0 -21
  133. data/test/multipart/nested +0 -10
  134. data/test/multipart/none +0 -9
  135. data/test/multipart/quoted +0 -15
  136. data/test/multipart/rack-logo.png +0 -0
  137. data/test/multipart/semicolon +0 -6
  138. data/test/multipart/text +0 -15
  139. data/test/multipart/three_files_three_fields +0 -31
  140. data/test/multipart/unity3d_wwwform +0 -11
  141. data/test/multipart/webkit +0 -32
  142. data/test/rackup/config.ru +0 -31
  143. data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
  144. data/test/spec_auth_basic.rb +0 -89
  145. data/test/spec_auth_digest.rb +0 -260
  146. data/test/spec_body_proxy.rb +0 -85
  147. data/test/spec_builder.rb +0 -233
  148. data/test/spec_cascade.rb +0 -63
  149. data/test/spec_cgi.rb +0 -84
  150. data/test/spec_chunked.rb +0 -103
  151. data/test/spec_common_logger.rb +0 -107
  152. data/test/spec_conditional_get.rb +0 -103
  153. data/test/spec_config.rb +0 -23
  154. data/test/spec_content_length.rb +0 -86
  155. data/test/spec_content_type.rb +0 -46
  156. data/test/spec_deflater.rb +0 -375
  157. data/test/spec_directory.rb +0 -148
  158. data/test/spec_etag.rb +0 -108
  159. data/test/spec_events.rb +0 -133
  160. data/test/spec_fastcgi.rb +0 -85
  161. data/test/spec_file.rb +0 -264
  162. data/test/spec_handler.rb +0 -57
  163. data/test/spec_head.rb +0 -46
  164. data/test/spec_lint.rb +0 -520
  165. data/test/spec_lobster.rb +0 -59
  166. data/test/spec_lock.rb +0 -204
  167. data/test/spec_logger.rb +0 -24
  168. data/test/spec_media_type.rb +0 -42
  169. data/test/spec_method_override.rb +0 -110
  170. data/test/spec_mime.rb +0 -51
  171. data/test/spec_mock.rb +0 -359
  172. data/test/spec_multipart.rb +0 -721
  173. data/test/spec_null_logger.rb +0 -21
  174. data/test/spec_recursive.rb +0 -75
  175. data/test/spec_request.rb +0 -1423
  176. data/test/spec_response.rb +0 -528
  177. data/test/spec_rewindable_input.rb +0 -128
  178. data/test/spec_runtime.rb +0 -50
  179. data/test/spec_sendfile.rb +0 -125
  180. data/test/spec_server.rb +0 -193
  181. data/test/spec_session_abstract_id.rb +0 -31
  182. data/test/spec_session_abstract_session_hash.rb +0 -45
  183. data/test/spec_session_cookie.rb +0 -442
  184. data/test/spec_session_memcache.rb +0 -357
  185. data/test/spec_session_persisted_secure_secure_session_hash.rb +0 -73
  186. data/test/spec_session_pool.rb +0 -247
  187. data/test/spec_show_exceptions.rb +0 -93
  188. data/test/spec_show_status.rb +0 -104
  189. data/test/spec_static.rb +0 -184
  190. data/test/spec_tempfile_reaper.rb +0 -64
  191. data/test/spec_thin.rb +0 -96
  192. data/test/spec_urlmap.rb +0 -237
  193. data/test/spec_utils.rb +0 -742
  194. data/test/spec_version.rb +0 -11
  195. data/test/spec_webrick.rb +0 -206
  196. data/test/static/another/index.html +0 -1
  197. data/test/static/foo.html +0 -1
  198. data/test/static/index.html +0 -1
  199. data/test/testrequest.rb +0 -78
  200. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  201. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
@@ -1,70 +0,0 @@
1
- require 'scgi'
2
- require 'stringio'
3
- require 'rack/content_length'
4
- require 'rack/chunked'
5
-
6
- module Rack
7
- module Handler
8
- class SCGI < ::SCGI::Processor
9
- attr_accessor :app
10
-
11
- def self.run(app, options=nil)
12
- options[:Socket] = UNIXServer.new(options[:File]) if options[:File]
13
- new(options.merge(:app=>app,
14
- :host=>options[:Host],
15
- :port=>options[:Port],
16
- :socket=>options[:Socket])).listen
17
- end
18
-
19
- def self.valid_options
20
- environment = ENV['RACK_ENV'] || 'development'
21
- default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
22
-
23
- {
24
- "Host=HOST" => "Hostname to listen on (default: #{default_host})",
25
- "Port=PORT" => "Port to listen on (default: 8080)",
26
- }
27
- end
28
-
29
- def initialize(settings = {})
30
- @app = settings[:app]
31
- super(settings)
32
- end
33
-
34
- def process_request(request, input_body, socket)
35
- env = Hash[request]
36
- env.delete "HTTP_CONTENT_TYPE"
37
- env.delete "HTTP_CONTENT_LENGTH"
38
- env[REQUEST_PATH], env[QUERY_STRING] = env["REQUEST_URI"].split('?', 2)
39
- env[HTTP_VERSION] ||= env[SERVER_PROTOCOL]
40
- env[PATH_INFO] = env[REQUEST_PATH]
41
- env[QUERY_STRING] ||= ""
42
- env[SCRIPT_NAME] = ""
43
-
44
- rack_input = StringIO.new(input_body, encoding: Encoding::BINARY)
45
-
46
- env.update(
47
- RACK_VERSION => Rack::VERSION,
48
- RACK_INPUT => rack_input,
49
- RACK_ERRORS => $stderr,
50
- RACK_MULTITHREAD => true,
51
- RACK_MULTIPROCESS => true,
52
- RACK_RUNONCE => false,
53
- RACK_URL_SCHEME => ["yes", "on", "1"].include?(env[HTTPS]) ? "https" : "http"
54
- )
55
-
56
- status, headers, body = app.call(env)
57
- begin
58
- socket.write("Status: #{status}\r\n")
59
- headers.each do |k, vs|
60
- vs.split("\n").each { |v| socket.write("#{k}: #{v}\r\n")}
61
- end
62
- socket.write("\r\n")
63
- body.each {|s| socket.write(s)}
64
- ensure
65
- body.close if body.respond_to? :close
66
- end
67
- end
68
- end
69
- end
70
- end
@@ -1,36 +0,0 @@
1
- require "thin"
2
- require "thin/server"
3
- require "thin/logging"
4
- require "thin/backends/tcp_server"
5
- require "rack/content_length"
6
- require "rack/chunked"
7
-
8
- module Rack
9
- module Handler
10
- class Thin
11
- def self.run(app, options={})
12
- environment = ENV['RACK_ENV'] || 'development'
13
- default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
14
-
15
- host = options.delete(:Host) || default_host
16
- port = options.delete(:Port) || 8080
17
- args = [host, port, app, options]
18
- # Thin versions below 0.8.0 do not support additional options
19
- args.pop if ::Thin::VERSION::MAJOR < 1 && ::Thin::VERSION::MINOR < 8
20
- server = ::Thin::Server.new(*args)
21
- yield server if block_given?
22
- server.start
23
- end
24
-
25
- def self.valid_options
26
- environment = ENV['RACK_ENV'] || 'development'
27
- default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
28
-
29
- {
30
- "Host=HOST" => "Hostname to listen on (default: #{default_host})",
31
- "Port=PORT" => "Port to listen on (default: 8080)",
32
- }
33
- end
34
- end
35
- end
36
- end
@@ -1,120 +0,0 @@
1
- require 'webrick'
2
- require 'stringio'
3
- require 'rack/content_length'
4
-
5
- # This monkey patch allows for applications to perform their own chunking
6
- # through WEBrick::HTTPResponse if rack is set to true.
7
- class WEBrick::HTTPResponse
8
- attr_accessor :rack
9
-
10
- alias _rack_setup_header setup_header
11
- def setup_header
12
- app_chunking = rack && @header['transfer-encoding'] == 'chunked'
13
-
14
- @chunked = app_chunking if app_chunking
15
-
16
- _rack_setup_header
17
-
18
- @chunked = false if app_chunking
19
- end
20
- end
21
-
22
- module Rack
23
- module Handler
24
- class WEBrick < ::WEBrick::HTTPServlet::AbstractServlet
25
- def self.run(app, options={})
26
- environment = ENV['RACK_ENV'] || 'development'
27
- default_host = environment == 'development' ? 'localhost' : nil
28
-
29
- options[:BindAddress] = options.delete(:Host) || default_host
30
- options[:Port] ||= 8080
31
- @server = ::WEBrick::HTTPServer.new(options)
32
- @server.mount "/", Rack::Handler::WEBrick, app
33
- yield @server if block_given?
34
- @server.start
35
- end
36
-
37
- def self.valid_options
38
- environment = ENV['RACK_ENV'] || 'development'
39
- default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
40
-
41
- {
42
- "Host=HOST" => "Hostname to listen on (default: #{default_host})",
43
- "Port=PORT" => "Port to listen on (default: 8080)",
44
- }
45
- end
46
-
47
- def self.shutdown
48
- @server.shutdown
49
- @server = nil
50
- end
51
-
52
- def initialize(server, app)
53
- super server
54
- @app = app
55
- end
56
-
57
- def service(req, res)
58
- res.rack = true
59
- env = req.meta_vars
60
- env.delete_if { |k, v| v.nil? }
61
-
62
- rack_input = StringIO.new(req.body.to_s)
63
- rack_input.set_encoding(Encoding::BINARY)
64
-
65
- env.update(
66
- RACK_VERSION => Rack::VERSION,
67
- RACK_INPUT => rack_input,
68
- RACK_ERRORS => $stderr,
69
- RACK_MULTITHREAD => true,
70
- RACK_MULTIPROCESS => false,
71
- RACK_RUNONCE => false,
72
- RACK_URL_SCHEME => ["yes", "on", "1"].include?(env[HTTPS]) ? "https" : "http",
73
- RACK_IS_HIJACK => true,
74
- RACK_HIJACK => lambda { raise NotImplementedError, "only partial hijack is supported."},
75
- RACK_HIJACK_IO => nil
76
- )
77
-
78
- env[HTTP_VERSION] ||= env[SERVER_PROTOCOL]
79
- env[QUERY_STRING] ||= ""
80
- unless env[PATH_INFO] == ""
81
- path, n = req.request_uri.path, env[SCRIPT_NAME].length
82
- env[PATH_INFO] = path[n, path.length-n]
83
- end
84
- env[REQUEST_PATH] ||= [env[SCRIPT_NAME], env[PATH_INFO]].join
85
-
86
- status, headers, body = @app.call(env)
87
- begin
88
- res.status = status.to_i
89
- io_lambda = nil
90
- headers.each { |k, vs|
91
- if k == RACK_HIJACK
92
- io_lambda = vs
93
- elsif k.downcase == "set-cookie"
94
- res.cookies.concat vs.split("\n")
95
- else
96
- # Since WEBrick won't accept repeated headers,
97
- # merge the values per RFC 1945 section 4.2.
98
- res[k] = vs.split("\n").join(", ")
99
- end
100
- }
101
-
102
- if io_lambda
103
- rd, wr = IO.pipe
104
- res.body = rd
105
- res.chunked = true
106
- io_lambda.call wr
107
- elsif body.respond_to?(:to_path)
108
- res.body = ::File.open(body.to_path, 'rb')
109
- else
110
- body.each { |part|
111
- res.body << part
112
- }
113
- end
114
- ensure
115
- body.close if body.respond_to? :close
116
- end
117
- end
118
- end
119
- end
120
- end
data/lib/rack/handler.rb DELETED
@@ -1,99 +0,0 @@
1
- module Rack
2
- # *Handlers* connect web servers with Rack.
3
- #
4
- # Rack includes Handlers for Thin, WEBrick, FastCGI, CGI, SCGI
5
- # and LiteSpeed.
6
- #
7
- # Handlers usually are activated by calling <tt>MyHandler.run(myapp)</tt>.
8
- # A second optional hash can be passed to include server-specific
9
- # configuration.
10
- module Handler
11
- def self.get(server)
12
- return unless server
13
- server = server.to_s
14
-
15
- unless @handlers.include? server
16
- load_error = try_require('rack/handler', server)
17
- end
18
-
19
- if klass = @handlers[server]
20
- klass.split("::").inject(Object) { |o, x| o.const_get(x) }
21
- else
22
- const_get(server, false)
23
- end
24
-
25
- rescue NameError => name_error
26
- raise load_error || name_error
27
- end
28
-
29
- # Select first available Rack handler given an `Array` of server names.
30
- # Raises `LoadError` if no handler was found.
31
- #
32
- # > pick ['thin', 'webrick']
33
- # => Rack::Handler::WEBrick
34
- def self.pick(server_names)
35
- server_names = Array(server_names)
36
- server_names.each do |server_name|
37
- begin
38
- return get(server_name.to_s)
39
- rescue LoadError, NameError
40
- end
41
- end
42
-
43
- raise LoadError, "Couldn't find handler for: #{server_names.join(', ')}."
44
- end
45
-
46
- def self.default
47
- # Guess.
48
- if ENV.include?("PHP_FCGI_CHILDREN")
49
- Rack::Handler::FastCGI
50
- elsif ENV.include?(REQUEST_METHOD)
51
- Rack::Handler::CGI
52
- elsif ENV.include?("RACK_HANDLER")
53
- self.get(ENV["RACK_HANDLER"])
54
- else
55
- pick ['puma', 'thin', 'webrick']
56
- end
57
- end
58
-
59
- # Transforms server-name constants to their canonical form as filenames,
60
- # then tries to require them but silences the LoadError if not found
61
- #
62
- # Naming convention:
63
- #
64
- # Foo # => 'foo'
65
- # FooBar # => 'foo_bar.rb'
66
- # FooBAR # => 'foobar.rb'
67
- # FOObar # => 'foobar.rb'
68
- # FOOBAR # => 'foobar.rb'
69
- # FooBarBaz # => 'foo_bar_baz.rb'
70
- def self.try_require(prefix, const_name)
71
- file = const_name.gsub(/^[A-Z]+/) { |pre| pre.downcase }.
72
- gsub(/[A-Z]+[^A-Z]/, '_\&').downcase
73
-
74
- require(::File.join(prefix, file))
75
- nil
76
- rescue LoadError => error
77
- error
78
- end
79
-
80
- def self.register(server, klass)
81
- @handlers ||= {}
82
- @handlers[server.to_s] = klass.to_s
83
- end
84
-
85
- autoload :CGI, "rack/handler/cgi"
86
- autoload :FastCGI, "rack/handler/fastcgi"
87
- autoload :WEBrick, "rack/handler/webrick"
88
- autoload :LSWS, "rack/handler/lsws"
89
- autoload :SCGI, "rack/handler/scgi"
90
- autoload :Thin, "rack/handler/thin"
91
-
92
- register 'cgi', 'Rack::Handler::CGI'
93
- register 'fastcgi', 'Rack::Handler::FastCGI'
94
- register 'webrick', 'Rack::Handler::WEBrick'
95
- register 'lsws', 'Rack::Handler::LSWS'
96
- register 'scgi', 'Rack::Handler::SCGI'
97
- register 'thin', 'Rack::Handler::Thin'
98
- end
99
- end
data/lib/rack/lobster.rb DELETED
@@ -1,70 +0,0 @@
1
- require 'zlib'
2
-
3
- require 'rack/request'
4
- require 'rack/response'
5
-
6
- module Rack
7
- # Paste has a Pony, Rack has a Lobster!
8
- class Lobster
9
- LobsterString = Zlib::Inflate.inflate("eJx9kEEOwyAMBO99xd7MAcytUhPlJyj2
10
- P6jy9i4k9EQyGAnBarEXeCBqSkntNXsi/ZCvC48zGQoZKikGrFMZvgS5ZHd+aGWVuWwhVF0
11
- t1drVmiR42HcWNz5w3QanT+2gIvTVCiE1lm1Y0eU4JGmIIbaKwextKn8rvW+p5PIwFl8ZWJ
12
- I8jyiTlhTcYXkekJAzTyYN6E08A+dk8voBkAVTJQ==".delete("\n ").unpack("m*")[0])
13
-
14
- LambdaLobster = lambda { |env|
15
- if env[QUERY_STRING].include?("flip")
16
- lobster = LobsterString.split("\n").
17
- map { |line| line.ljust(42).reverse }.
18
- join("\n")
19
- href = "?"
20
- else
21
- lobster = LobsterString
22
- href = "?flip"
23
- end
24
-
25
- content = ["<title>Lobstericious!</title>",
26
- "<pre>", lobster, "</pre>",
27
- "<a href='#{href}'>flip!</a>"]
28
- length = content.inject(0) { |a,e| a+e.size }.to_s
29
- [200, {CONTENT_TYPE => "text/html", CONTENT_LENGTH => length}, content]
30
- }
31
-
32
- def call(env)
33
- req = Request.new(env)
34
- if req.GET["flip"] == "left"
35
- lobster = LobsterString.split("\n").map do |line|
36
- line.ljust(42).reverse.
37
- gsub('\\', 'TEMP').
38
- gsub('/', '\\').
39
- gsub('TEMP', '/').
40
- gsub('{','}').
41
- gsub('(',')')
42
- end.join("\n")
43
- href = "?flip=right"
44
- elsif req.GET["flip"] == "crash"
45
- raise "Lobster crashed"
46
- else
47
- lobster = LobsterString
48
- href = "?flip=left"
49
- end
50
-
51
- res = Response.new
52
- res.write "<title>Lobstericious!</title>"
53
- res.write "<pre>"
54
- res.write lobster
55
- res.write "</pre>"
56
- res.write "<p><a href='#{href}'>flip!</a></p>"
57
- res.write "<p><a href='?flip=crash'>crash!</a></p>"
58
- res.finish
59
- end
60
-
61
- end
62
- end
63
-
64
- if $0 == __FILE__
65
- require 'rack'
66
- require 'rack/show_exceptions'
67
- Rack::Server.start(
68
- :app => Rack::ShowExceptions.new(Rack::Lint.new(Rack::Lobster.new)), :Port => 9292
69
- )
70
- end