diy_rails 0.1.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.
Files changed (155) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +8 -0
  3. data/Gemfile.lock +21 -0
  4. data/README.md +29 -0
  5. data/Rakefile +4 -0
  6. data/lib/diy_rails/version.rb +5 -0
  7. data/lib/diy_rails.rb +8 -0
  8. data/sig/diy_rails.rbs +4 -0
  9. data/vendor/bundle/ruby/3.0.0/bin/rackup +29 -0
  10. data/vendor/bundle/ruby/3.0.0/bin/rake +29 -0
  11. data/vendor/bundle/ruby/3.0.0/cache/rack-2.2.4.gem +0 -0
  12. data/vendor/bundle/ruby/3.0.0/cache/rake-13.0.6.gem +0 -0
  13. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/CHANGELOG.md +708 -0
  14. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/CONTRIBUTING.md +136 -0
  15. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/MIT-LICENSE +20 -0
  16. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/README.rdoc +306 -0
  17. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/Rakefile +130 -0
  18. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/SPEC.rdoc +288 -0
  19. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/bin/rackup +5 -0
  20. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/contrib/rack.png +0 -0
  21. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/contrib/rack.svg +150 -0
  22. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/contrib/rack_logo.svg +164 -0
  23. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/contrib/rdoc.css +412 -0
  24. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/example/lobster.ru +6 -0
  25. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/example/protectedlobster.rb +16 -0
  26. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/example/protectedlobster.ru +10 -0
  27. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/auth/abstract/handler.rb +39 -0
  28. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/auth/abstract/request.rb +47 -0
  29. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/auth/basic.rb +61 -0
  30. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/auth/digest/md5.rb +131 -0
  31. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/auth/digest/nonce.rb +54 -0
  32. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/auth/digest/params.rb +54 -0
  33. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/auth/digest/request.rb +43 -0
  34. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/body_proxy.rb +45 -0
  35. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/builder.rb +257 -0
  36. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/cascade.rb +68 -0
  37. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/chunked.rb +117 -0
  38. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/common_logger.rb +83 -0
  39. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/conditional_get.rb +83 -0
  40. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/config.rb +22 -0
  41. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/content_length.rb +38 -0
  42. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/content_type.rb +30 -0
  43. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/core_ext/regexp.rb +14 -0
  44. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/deflater.rb +144 -0
  45. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/directory.rb +199 -0
  46. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/etag.rb +77 -0
  47. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/events.rb +153 -0
  48. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/file.rb +7 -0
  49. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/files.rb +218 -0
  50. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/handler/cgi.rb +59 -0
  51. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/handler/fastcgi.rb +100 -0
  52. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/handler/lsws.rb +61 -0
  53. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/handler/scgi.rb +71 -0
  54. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/handler/thin.rb +36 -0
  55. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/handler/webrick.rb +129 -0
  56. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/handler.rb +104 -0
  57. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/head.rb +25 -0
  58. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/lint.rb +806 -0
  59. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/lobster.rb +70 -0
  60. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/lock.rb +32 -0
  61. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/logger.rb +20 -0
  62. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/media_type.rb +43 -0
  63. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/method_override.rb +52 -0
  64. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/mime.rb +685 -0
  65. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/mock.rb +273 -0
  66. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/multipart/generator.rb +97 -0
  67. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/multipart/parser.rb +365 -0
  68. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/multipart/uploaded_file.rb +41 -0
  69. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/multipart.rb +64 -0
  70. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/null_logger.rb +39 -0
  71. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/query_parser.rb +221 -0
  72. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/recursive.rb +64 -0
  73. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/reloader.rb +114 -0
  74. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/request.rb +659 -0
  75. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/response.rb +318 -0
  76. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/rewindable_input.rb +94 -0
  77. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/runtime.rb +34 -0
  78. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/sendfile.rb +162 -0
  79. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/server.rb +466 -0
  80. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/session/abstract/id.rb +523 -0
  81. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/session/cookie.rb +203 -0
  82. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/session/memcache.rb +10 -0
  83. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/session/pool.rb +85 -0
  84. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/show_exceptions.rb +390 -0
  85. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/show_status.rb +113 -0
  86. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/static.rb +187 -0
  87. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/tempfile_reaper.rb +22 -0
  88. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/urlmap.rb +97 -0
  89. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/utils.rb +616 -0
  90. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/version.rb +29 -0
  91. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack.rb +141 -0
  92. data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/rack.gemspec +46 -0
  93. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/History.rdoc +2403 -0
  94. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/MIT-LICENSE +21 -0
  95. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/README.rdoc +155 -0
  96. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/command_line_usage.rdoc +158 -0
  97. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/example/Rakefile1 +38 -0
  98. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/example/Rakefile2 +35 -0
  99. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/example/a.c +6 -0
  100. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/example/b.c +6 -0
  101. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/example/main.c +11 -0
  102. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/glossary.rdoc +42 -0
  103. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/jamis.rb +592 -0
  104. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/proto_rake.rdoc +127 -0
  105. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/rake.1 +156 -0
  106. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/rakefile.rdoc +622 -0
  107. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/rational.rdoc +151 -0
  108. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/exe/rake +27 -0
  109. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/application.rb +831 -0
  110. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/backtrace.rb +24 -0
  111. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/clean.rb +78 -0
  112. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/cloneable.rb +17 -0
  113. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/cpu_counter.rb +107 -0
  114. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/default_loader.rb +15 -0
  115. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/dsl_definition.rb +195 -0
  116. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/early_time.rb +22 -0
  117. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/ext/core.rb +26 -0
  118. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/ext/string.rb +176 -0
  119. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/file_creation_task.rb +25 -0
  120. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/file_list.rb +435 -0
  121. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/file_task.rb +54 -0
  122. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/file_utils.rb +134 -0
  123. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/file_utils_ext.rb +134 -0
  124. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/invocation_chain.rb +57 -0
  125. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/invocation_exception_mixin.rb +17 -0
  126. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/late_time.rb +18 -0
  127. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/linked_list.rb +112 -0
  128. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/loaders/makefile.rb +54 -0
  129. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/multi_task.rb +14 -0
  130. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/name_space.rb +38 -0
  131. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/packagetask.rb +222 -0
  132. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/phony.rb +16 -0
  133. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/private_reader.rb +21 -0
  134. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/promise.rb +100 -0
  135. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/pseudo_status.rb +30 -0
  136. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/rake_module.rb +67 -0
  137. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/rake_test_loader.rb +27 -0
  138. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/rule_recursion_overflow_error.rb +20 -0
  139. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/scope.rb +43 -0
  140. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb +434 -0
  141. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task_argument_error.rb +8 -0
  142. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task_arguments.rb +109 -0
  143. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task_manager.rb +331 -0
  144. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/tasklib.rb +12 -0
  145. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/testtask.rb +189 -0
  146. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/thread_history_display.rb +49 -0
  147. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/thread_pool.rb +163 -0
  148. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/trace_output.rb +23 -0
  149. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/version.rb +10 -0
  150. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/win32.rb +51 -0
  151. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake.rb +71 -0
  152. data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/rake.gemspec +100 -0
  153. data/vendor/bundle/ruby/3.0.0/specifications/rack-2.2.4.gemspec +41 -0
  154. data/vendor/bundle/ruby/3.0.0/specifications/rake-13.0.6.gemspec +26 -0
  155. metadata +210 -0
@@ -0,0 +1,273 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+ require 'stringio'
5
+ require_relative '../rack'
6
+ require 'cgi/cookie'
7
+
8
+ module Rack
9
+ # Rack::MockRequest helps testing your Rack application without
10
+ # actually using HTTP.
11
+ #
12
+ # After performing a request on a URL with get/post/put/patch/delete, it
13
+ # returns a MockResponse with useful helper methods for effective
14
+ # testing.
15
+ #
16
+ # You can pass a hash with additional configuration to the
17
+ # get/post/put/patch/delete.
18
+ # <tt>:input</tt>:: A String or IO-like to be used as rack.input.
19
+ # <tt>:fatal</tt>:: Raise a FatalWarning if the app writes to rack.errors.
20
+ # <tt>:lint</tt>:: If true, wrap the application in a Rack::Lint.
21
+
22
+ class MockRequest
23
+ class FatalWarning < RuntimeError
24
+ end
25
+
26
+ class FatalWarner
27
+ def puts(warning)
28
+ raise FatalWarning, warning
29
+ end
30
+
31
+ def write(warning)
32
+ raise FatalWarning, warning
33
+ end
34
+
35
+ def flush
36
+ end
37
+
38
+ def string
39
+ ""
40
+ end
41
+ end
42
+
43
+ DEFAULT_ENV = {
44
+ RACK_VERSION => Rack::VERSION,
45
+ RACK_INPUT => StringIO.new,
46
+ RACK_ERRORS => StringIO.new,
47
+ RACK_MULTITHREAD => true,
48
+ RACK_MULTIPROCESS => true,
49
+ RACK_RUNONCE => false,
50
+ }.freeze
51
+
52
+ def initialize(app)
53
+ @app = app
54
+ end
55
+
56
+ # Make a GET request and return a MockResponse. See #request.
57
+ def get(uri, opts = {}) request(GET, uri, opts) end
58
+ # Make a POST request and return a MockResponse. See #request.
59
+ def post(uri, opts = {}) request(POST, uri, opts) end
60
+ # Make a PUT request and return a MockResponse. See #request.
61
+ def put(uri, opts = {}) request(PUT, uri, opts) end
62
+ # Make a PATCH request and return a MockResponse. See #request.
63
+ def patch(uri, opts = {}) request(PATCH, uri, opts) end
64
+ # Make a DELETE request and return a MockResponse. See #request.
65
+ def delete(uri, opts = {}) request(DELETE, uri, opts) end
66
+ # Make a HEAD request and return a MockResponse. See #request.
67
+ def head(uri, opts = {}) request(HEAD, uri, opts) end
68
+ # Make an OPTIONS request and return a MockResponse. See #request.
69
+ def options(uri, opts = {}) request(OPTIONS, uri, opts) end
70
+
71
+ # Make a request using the given request method for the given
72
+ # uri to the rack application and return a MockResponse.
73
+ # Options given are passed to MockRequest.env_for.
74
+ def request(method = GET, uri = "", opts = {})
75
+ env = self.class.env_for(uri, opts.merge(method: method))
76
+
77
+ if opts[:lint]
78
+ app = Rack::Lint.new(@app)
79
+ else
80
+ app = @app
81
+ end
82
+
83
+ errors = env[RACK_ERRORS]
84
+ status, headers, body = app.call(env)
85
+ MockResponse.new(status, headers, body, errors)
86
+ ensure
87
+ body.close if body.respond_to?(:close)
88
+ end
89
+
90
+ # For historical reasons, we're pinning to RFC 2396.
91
+ # URI::Parser = URI::RFC2396_Parser
92
+ def self.parse_uri_rfc2396(uri)
93
+ @parser ||= URI::Parser.new
94
+ @parser.parse(uri)
95
+ end
96
+
97
+ # Return the Rack environment used for a request to +uri+.
98
+ # All options that are strings are added to the returned environment.
99
+ # Options:
100
+ # :fatal :: Whether to raise an exception if request outputs to rack.errors
101
+ # :input :: The rack.input to set
102
+ # :method :: The HTTP request method to use
103
+ # :params :: The params to use
104
+ # :script_name :: The SCRIPT_NAME to set
105
+ def self.env_for(uri = "", opts = {})
106
+ uri = parse_uri_rfc2396(uri)
107
+ uri.path = "/#{uri.path}" unless uri.path[0] == ?/
108
+
109
+ env = DEFAULT_ENV.dup
110
+
111
+ env[REQUEST_METHOD] = (opts[:method] ? opts[:method].to_s.upcase : GET).b
112
+ env[SERVER_NAME] = (uri.host || "example.org").b
113
+ env[SERVER_PORT] = (uri.port ? uri.port.to_s : "80").b
114
+ env[QUERY_STRING] = (uri.query.to_s).b
115
+ env[PATH_INFO] = ((!uri.path || uri.path.empty?) ? "/" : uri.path).b
116
+ env[RACK_URL_SCHEME] = (uri.scheme || "http").b
117
+ env[HTTPS] = (env[RACK_URL_SCHEME] == "https" ? "on" : "off").b
118
+
119
+ env[SCRIPT_NAME] = opts[:script_name] || ""
120
+
121
+ if opts[:fatal]
122
+ env[RACK_ERRORS] = FatalWarner.new
123
+ else
124
+ env[RACK_ERRORS] = StringIO.new
125
+ end
126
+
127
+ if params = opts[:params]
128
+ if env[REQUEST_METHOD] == GET
129
+ params = Utils.parse_nested_query(params) if params.is_a?(String)
130
+ params.update(Utils.parse_nested_query(env[QUERY_STRING]))
131
+ env[QUERY_STRING] = Utils.build_nested_query(params)
132
+ elsif !opts.has_key?(:input)
133
+ opts["CONTENT_TYPE"] = "application/x-www-form-urlencoded"
134
+ if params.is_a?(Hash)
135
+ if data = Rack::Multipart.build_multipart(params)
136
+ opts[:input] = data
137
+ opts["CONTENT_LENGTH"] ||= data.length.to_s
138
+ opts["CONTENT_TYPE"] = "multipart/form-data; boundary=#{Rack::Multipart::MULTIPART_BOUNDARY}"
139
+ else
140
+ opts[:input] = Utils.build_nested_query(params)
141
+ end
142
+ else
143
+ opts[:input] = params
144
+ end
145
+ end
146
+ end
147
+
148
+ empty_str = String.new
149
+ opts[:input] ||= empty_str
150
+ if String === opts[:input]
151
+ rack_input = StringIO.new(opts[:input])
152
+ else
153
+ rack_input = opts[:input]
154
+ end
155
+
156
+ rack_input.set_encoding(Encoding::BINARY)
157
+ env[RACK_INPUT] = rack_input
158
+
159
+ env["CONTENT_LENGTH"] ||= env[RACK_INPUT].size.to_s if env[RACK_INPUT].respond_to?(:size)
160
+
161
+ opts.each { |field, value|
162
+ env[field] = value if String === field
163
+ }
164
+
165
+ env
166
+ end
167
+ end
168
+
169
+ # Rack::MockResponse provides useful helpers for testing your apps.
170
+ # Usually, you don't create the MockResponse on your own, but use
171
+ # MockRequest.
172
+
173
+ class MockResponse < Rack::Response
174
+ class << self
175
+ alias [] new
176
+ end
177
+
178
+ # Headers
179
+ attr_reader :original_headers, :cookies
180
+
181
+ # Errors
182
+ attr_accessor :errors
183
+
184
+ def initialize(status, headers, body, errors = StringIO.new(""))
185
+ @original_headers = headers
186
+ @errors = errors.string if errors.respond_to?(:string)
187
+ @cookies = parse_cookies_from_header
188
+
189
+ super(body, status, headers)
190
+
191
+ buffered_body!
192
+ end
193
+
194
+ def =~(other)
195
+ body =~ other
196
+ end
197
+
198
+ def match(other)
199
+ body.match other
200
+ end
201
+
202
+ def body
203
+ # FIXME: apparently users of MockResponse expect the return value of
204
+ # MockResponse#body to be a string. However, the real response object
205
+ # returns the body as a list.
206
+ #
207
+ # See spec_showstatus.rb:
208
+ #
209
+ # should "not replace existing messages" do
210
+ # ...
211
+ # res.body.should == "foo!"
212
+ # end
213
+ buffer = String.new
214
+
215
+ super.each do |chunk|
216
+ buffer << chunk
217
+ end
218
+
219
+ return buffer
220
+ end
221
+
222
+ def empty?
223
+ [201, 204, 304].include? status
224
+ end
225
+
226
+ def cookie(name)
227
+ cookies.fetch(name, nil)
228
+ end
229
+
230
+ private
231
+
232
+ def parse_cookies_from_header
233
+ cookies = Hash.new
234
+ if original_headers.has_key? 'Set-Cookie'
235
+ set_cookie_header = original_headers.fetch('Set-Cookie')
236
+ set_cookie_header.split("\n").each do |cookie|
237
+ cookie_name, cookie_filling = cookie.split('=', 2)
238
+ cookie_attributes = identify_cookie_attributes cookie_filling
239
+ parsed_cookie = CGI::Cookie.new(
240
+ 'name' => cookie_name.strip,
241
+ 'value' => cookie_attributes.fetch('value'),
242
+ 'path' => cookie_attributes.fetch('path', nil),
243
+ 'domain' => cookie_attributes.fetch('domain', nil),
244
+ 'expires' => cookie_attributes.fetch('expires', nil),
245
+ 'secure' => cookie_attributes.fetch('secure', false)
246
+ )
247
+ cookies.store(cookie_name, parsed_cookie)
248
+ end
249
+ end
250
+ cookies
251
+ end
252
+
253
+ def identify_cookie_attributes(cookie_filling)
254
+ cookie_bits = cookie_filling.split(';')
255
+ cookie_attributes = Hash.new
256
+ cookie_attributes.store('value', cookie_bits[0].strip)
257
+ cookie_bits.each do |bit|
258
+ if bit.include? '='
259
+ cookie_attribute, attribute_value = bit.split('=')
260
+ cookie_attributes.store(cookie_attribute.strip, attribute_value.strip)
261
+ if cookie_attribute.include? 'max-age'
262
+ cookie_attributes.store('expires', Time.now + attribute_value.strip.to_i)
263
+ end
264
+ end
265
+ if bit.include? 'secure'
266
+ cookie_attributes.store('secure', true)
267
+ end
268
+ end
269
+ cookie_attributes
270
+ end
271
+
272
+ end
273
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ module Multipart
5
+ class Generator
6
+ def initialize(params, first = true)
7
+ @params, @first = params, first
8
+
9
+ if @first && !@params.is_a?(Hash)
10
+ raise ArgumentError, "value must be a Hash"
11
+ end
12
+ end
13
+
14
+ def dump
15
+ return nil if @first && !multipart?
16
+ return flattened_params unless @first
17
+
18
+ flattened_params.map do |name, file|
19
+ if file.respond_to?(:original_filename)
20
+ if file.path
21
+ ::File.open(file.path, 'rb') do |f|
22
+ f.set_encoding(Encoding::BINARY)
23
+ content_for_tempfile(f, file, name)
24
+ end
25
+ else
26
+ content_for_tempfile(file, file, name)
27
+ end
28
+ else
29
+ content_for_other(file, name)
30
+ end
31
+ end.join << "--#{MULTIPART_BOUNDARY}--\r"
32
+ end
33
+
34
+ private
35
+ def multipart?
36
+ query = lambda { |value|
37
+ case value
38
+ when Array
39
+ value.any?(&query)
40
+ when Hash
41
+ value.values.any?(&query)
42
+ when Rack::Multipart::UploadedFile
43
+ true
44
+ end
45
+ }
46
+
47
+ @params.values.any?(&query)
48
+ end
49
+
50
+ def flattened_params
51
+ @flattened_params ||= begin
52
+ h = Hash.new
53
+ @params.each do |key, value|
54
+ k = @first ? key.to_s : "[#{key}]"
55
+
56
+ case value
57
+ when Array
58
+ value.map { |v|
59
+ Multipart.build_multipart(v, false).each { |subkey, subvalue|
60
+ h["#{k}[]#{subkey}"] = subvalue
61
+ }
62
+ }
63
+ when Hash
64
+ Multipart.build_multipart(value, false).each { |subkey, subvalue|
65
+ h[k + subkey] = subvalue
66
+ }
67
+ else
68
+ h[k] = value
69
+ end
70
+ end
71
+ h
72
+ end
73
+ end
74
+
75
+ def content_for_tempfile(io, file, name)
76
+ length = ::File.stat(file.path).size if file.path
77
+ filename = "; filename=\"#{Utils.escape(file.original_filename)}\"" if file.original_filename
78
+ <<-EOF
79
+ --#{MULTIPART_BOUNDARY}\r
80
+ Content-Disposition: form-data; name="#{name}"#{filename}\r
81
+ Content-Type: #{file.content_type}\r
82
+ #{"Content-Length: #{length}\r\n" if length}\r
83
+ #{io.read}\r
84
+ EOF
85
+ end
86
+
87
+ def content_for_other(file, name)
88
+ <<-EOF
89
+ --#{MULTIPART_BOUNDARY}\r
90
+ Content-Disposition: form-data; name="#{name}"\r
91
+ \r
92
+ #{file}\r
93
+ EOF
94
+ end
95
+ end
96
+ end
97
+ end