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,318 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'time'
4
+
5
+ module Rack
6
+ # Rack::Response provides a convenient interface to create a Rack
7
+ # response.
8
+ #
9
+ # It allows setting of headers and cookies, and provides useful
10
+ # defaults (an OK response with empty headers and body).
11
+ #
12
+ # You can use Response#write to iteratively generate your response,
13
+ # but note that this is buffered by Rack::Response until you call
14
+ # +finish+. +finish+ however can take a block inside which calls to
15
+ # +write+ are synchronous with the Rack response.
16
+ #
17
+ # Your application's +call+ should end returning Response#finish.
18
+ class Response
19
+ def self.[](status, headers, body)
20
+ self.new(body, status, headers)
21
+ end
22
+
23
+ CHUNKED = 'chunked'
24
+ STATUS_WITH_NO_ENTITY_BODY = Utils::STATUS_WITH_NO_ENTITY_BODY
25
+
26
+ attr_accessor :length, :status, :body
27
+ attr_reader :headers
28
+
29
+ # @deprecated Use {#headers} instead.
30
+ alias header headers
31
+
32
+ # Initialize the response object with the specified body, status
33
+ # and headers.
34
+ #
35
+ # @param body [nil, #each, #to_str] the response body.
36
+ # @param status [Integer] the integer status as defined by the
37
+ # HTTP protocol RFCs.
38
+ # @param headers [#each] a list of key-value header pairs which
39
+ # conform to the HTTP protocol RFCs.
40
+ #
41
+ # Providing a body which responds to #to_str is legacy behaviour.
42
+ def initialize(body = nil, status = 200, headers = {})
43
+ @status = status.to_i
44
+ @headers = Utils::HeaderHash[headers]
45
+
46
+ @writer = self.method(:append)
47
+
48
+ @block = nil
49
+
50
+ # Keep track of whether we have expanded the user supplied body.
51
+ if body.nil?
52
+ @body = []
53
+ @buffered = true
54
+ @length = 0
55
+ elsif body.respond_to?(:to_str)
56
+ @body = [body]
57
+ @buffered = true
58
+ @length = body.to_str.bytesize
59
+ else
60
+ @body = body
61
+ @buffered = false
62
+ @length = 0
63
+ end
64
+
65
+ yield self if block_given?
66
+ end
67
+
68
+ def redirect(target, status = 302)
69
+ self.status = status
70
+ self.location = target
71
+ end
72
+
73
+ def chunked?
74
+ CHUNKED == get_header(TRANSFER_ENCODING)
75
+ end
76
+
77
+ # Generate a response array consistent with the requirements of the SPEC.
78
+ # @return [Array] a 3-tuple suitable of `[status, headers, body]`
79
+ # which is suitable to be returned from the middleware `#call(env)` method.
80
+ def finish(&block)
81
+ if STATUS_WITH_NO_ENTITY_BODY[status.to_i]
82
+ delete_header CONTENT_TYPE
83
+ delete_header CONTENT_LENGTH
84
+ close
85
+ return [@status, @headers, []]
86
+ else
87
+ if block_given?
88
+ @block = block
89
+ return [@status, @headers, self]
90
+ else
91
+ return [@status, @headers, @body]
92
+ end
93
+ end
94
+ end
95
+
96
+ alias to_a finish # For *response
97
+
98
+ def each(&callback)
99
+ @body.each(&callback)
100
+ @buffered = true
101
+
102
+ if @block
103
+ @writer = callback
104
+ @block.call(self)
105
+ end
106
+ end
107
+
108
+ # Append to body and update Content-Length.
109
+ #
110
+ # NOTE: Do not mix #write and direct #body access!
111
+ #
112
+ def write(chunk)
113
+ buffered_body!
114
+
115
+ @writer.call(chunk.to_s)
116
+ end
117
+
118
+ def close
119
+ @body.close if @body.respond_to?(:close)
120
+ end
121
+
122
+ def empty?
123
+ @block == nil && @body.empty?
124
+ end
125
+
126
+ def has_header?(key); headers.key? key; end
127
+ def get_header(key); headers[key]; end
128
+ def set_header(key, v); headers[key] = v; end
129
+ def delete_header(key); headers.delete key; end
130
+
131
+ alias :[] :get_header
132
+ alias :[]= :set_header
133
+
134
+ module Helpers
135
+ def invalid?; status < 100 || status >= 600; end
136
+
137
+ def informational?; status >= 100 && status < 200; end
138
+ def successful?; status >= 200 && status < 300; end
139
+ def redirection?; status >= 300 && status < 400; end
140
+ def client_error?; status >= 400 && status < 500; end
141
+ def server_error?; status >= 500 && status < 600; end
142
+
143
+ def ok?; status == 200; end
144
+ def created?; status == 201; end
145
+ def accepted?; status == 202; end
146
+ def no_content?; status == 204; end
147
+ def moved_permanently?; status == 301; end
148
+ def bad_request?; status == 400; end
149
+ def unauthorized?; status == 401; end
150
+ def forbidden?; status == 403; end
151
+ def not_found?; status == 404; end
152
+ def method_not_allowed?; status == 405; end
153
+ def precondition_failed?; status == 412; end
154
+ def unprocessable?; status == 422; end
155
+
156
+ def redirect?; [301, 302, 303, 307, 308].include? status; end
157
+
158
+ def include?(header)
159
+ has_header? header
160
+ end
161
+
162
+ # Add a header that may have multiple values.
163
+ #
164
+ # Example:
165
+ # response.add_header 'Vary', 'Accept-Encoding'
166
+ # response.add_header 'Vary', 'Cookie'
167
+ #
168
+ # assert_equal 'Accept-Encoding,Cookie', response.get_header('Vary')
169
+ #
170
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
171
+ def add_header(key, v)
172
+ if v.nil?
173
+ get_header key
174
+ elsif has_header? key
175
+ set_header key, "#{get_header key},#{v}"
176
+ else
177
+ set_header key, v
178
+ end
179
+ end
180
+
181
+ # Get the content type of the response.
182
+ def content_type
183
+ get_header CONTENT_TYPE
184
+ end
185
+
186
+ # Set the content type of the response.
187
+ def content_type=(content_type)
188
+ set_header CONTENT_TYPE, content_type
189
+ end
190
+
191
+ def media_type
192
+ MediaType.type(content_type)
193
+ end
194
+
195
+ def media_type_params
196
+ MediaType.params(content_type)
197
+ end
198
+
199
+ def content_length
200
+ cl = get_header CONTENT_LENGTH
201
+ cl ? cl.to_i : cl
202
+ end
203
+
204
+ def location
205
+ get_header "Location"
206
+ end
207
+
208
+ def location=(location)
209
+ set_header "Location", location
210
+ end
211
+
212
+ def set_cookie(key, value)
213
+ cookie_header = get_header SET_COOKIE
214
+ set_header SET_COOKIE, ::Rack::Utils.add_cookie_to_header(cookie_header, key, value)
215
+ end
216
+
217
+ def delete_cookie(key, value = {})
218
+ set_header SET_COOKIE, ::Rack::Utils.add_remove_cookie_to_header(get_header(SET_COOKIE), key, value)
219
+ end
220
+
221
+ def set_cookie_header
222
+ get_header SET_COOKIE
223
+ end
224
+
225
+ def set_cookie_header=(v)
226
+ set_header SET_COOKIE, v
227
+ end
228
+
229
+ def cache_control
230
+ get_header CACHE_CONTROL
231
+ end
232
+
233
+ def cache_control=(v)
234
+ set_header CACHE_CONTROL, v
235
+ end
236
+
237
+ # Specifies that the content shouldn't be cached. Overrides `cache!` if already called.
238
+ def do_not_cache!
239
+ set_header CACHE_CONTROL, "no-cache, must-revalidate"
240
+ set_header EXPIRES, Time.now.httpdate
241
+ end
242
+
243
+ # Specify that the content should be cached.
244
+ # @param duration [Integer] The number of seconds until the cache expires.
245
+ # @option directive [String] The cache control directive, one of "public", "private", "no-cache" or "no-store".
246
+ def cache!(duration = 3600, directive: "public")
247
+ unless headers[CACHE_CONTROL] =~ /no-cache/
248
+ set_header CACHE_CONTROL, "#{directive}, max-age=#{duration}"
249
+ set_header EXPIRES, (Time.now + duration).httpdate
250
+ end
251
+ end
252
+
253
+ def etag
254
+ get_header ETAG
255
+ end
256
+
257
+ def etag=(v)
258
+ set_header ETAG, v
259
+ end
260
+
261
+ protected
262
+
263
+ def buffered_body!
264
+ return if @buffered
265
+
266
+ if @body.is_a?(Array)
267
+ # The user supplied body was an array:
268
+ @body = @body.compact
269
+ @body.each do |part|
270
+ @length += part.to_s.bytesize
271
+ end
272
+ else
273
+ # Turn the user supplied body into a buffered array:
274
+ body = @body
275
+ @body = Array.new
276
+
277
+ body.each do |part|
278
+ @writer.call(part.to_s)
279
+ end
280
+
281
+ body.close if body.respond_to?(:close)
282
+ end
283
+
284
+ @buffered = true
285
+ end
286
+
287
+ def append(chunk)
288
+ @body << chunk
289
+
290
+ unless chunked?
291
+ @length += chunk.bytesize
292
+ set_header(CONTENT_LENGTH, @length.to_s)
293
+ end
294
+
295
+ return chunk
296
+ end
297
+ end
298
+
299
+ include Helpers
300
+
301
+ class Raw
302
+ include Helpers
303
+
304
+ attr_reader :headers
305
+ attr_accessor :status
306
+
307
+ def initialize(status, headers)
308
+ @status = status
309
+ @headers = headers
310
+ end
311
+
312
+ def has_header?(key); headers.key? key; end
313
+ def get_header(key); headers[key]; end
314
+ def set_header(key, v); headers[key] = v; end
315
+ def delete_header(key); headers.delete key; end
316
+ end
317
+ end
318
+ end
@@ -0,0 +1,94 @@
1
+ # -*- encoding: binary -*-
2
+ # frozen_string_literal: true
3
+
4
+ require 'tempfile'
5
+
6
+ module Rack
7
+ # Class which can make any IO object rewindable, including non-rewindable ones. It does
8
+ # this by buffering the data into a tempfile, which is rewindable.
9
+ #
10
+ # rack.input is required to be rewindable, so if your input stream IO is non-rewindable
11
+ # by nature (e.g. a pipe or a socket) then you can wrap it in an object of this class
12
+ # to easily make it rewindable.
13
+ #
14
+ # Don't forget to call #close when you're done. This frees up temporary resources that
15
+ # RewindableInput uses, though it does *not* close the original IO object.
16
+ class RewindableInput
17
+ def initialize(io)
18
+ @io = io
19
+ @rewindable_io = nil
20
+ @unlinked = false
21
+ end
22
+
23
+ def gets
24
+ make_rewindable unless @rewindable_io
25
+ @rewindable_io.gets
26
+ end
27
+
28
+ def read(*args)
29
+ make_rewindable unless @rewindable_io
30
+ @rewindable_io.read(*args)
31
+ end
32
+
33
+ def each(&block)
34
+ make_rewindable unless @rewindable_io
35
+ @rewindable_io.each(&block)
36
+ end
37
+
38
+ def rewind
39
+ make_rewindable unless @rewindable_io
40
+ @rewindable_io.rewind
41
+ end
42
+
43
+ # Closes this RewindableInput object without closing the originally
44
+ # wrapped IO object. Cleans up any temporary resources that this RewindableInput
45
+ # has created.
46
+ #
47
+ # This method may be called multiple times. It does nothing on subsequent calls.
48
+ def close
49
+ if @rewindable_io
50
+ if @unlinked
51
+ @rewindable_io.close
52
+ else
53
+ @rewindable_io.close!
54
+ end
55
+ @rewindable_io = nil
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def make_rewindable
62
+ # Buffer all data into a tempfile. Since this tempfile is private to this
63
+ # RewindableInput object, we chmod it so that nobody else can read or write
64
+ # it. On POSIX filesystems we also unlink the file so that it doesn't
65
+ # even have a file entry on the filesystem anymore, though we can still
66
+ # access it because we have the file handle open.
67
+ @rewindable_io = Tempfile.new('RackRewindableInput')
68
+ @rewindable_io.chmod(0000)
69
+ @rewindable_io.set_encoding(Encoding::BINARY) if @rewindable_io.respond_to?(:set_encoding)
70
+ @rewindable_io.binmode
71
+ if filesystem_has_posix_semantics?
72
+ raise 'Unlink failed. IO closed.' if @rewindable_io.closed?
73
+ @unlinked = true
74
+ end
75
+
76
+ buffer = "".dup
77
+ while @io.read(1024 * 4, buffer)
78
+ entire_buffer_written_out = false
79
+ while !entire_buffer_written_out
80
+ written = @rewindable_io.write(buffer)
81
+ entire_buffer_written_out = written == buffer.bytesize
82
+ if !entire_buffer_written_out
83
+ buffer.slice!(0 .. written - 1)
84
+ end
85
+ end
86
+ end
87
+ @rewindable_io.rewind
88
+ end
89
+
90
+ def filesystem_has_posix_semantics?
91
+ RUBY_PLATFORM !~ /(mswin|mingw|cygwin|java)/
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ # Sets an "X-Runtime" response header, indicating the response
5
+ # time of the request, in seconds
6
+ #
7
+ # You can put it right before the application to see the processing
8
+ # time, or before all the other middlewares to include time for them,
9
+ # too.
10
+ class Runtime
11
+ FORMAT_STRING = "%0.6f" # :nodoc:
12
+ HEADER_NAME = "X-Runtime" # :nodoc:
13
+
14
+ def initialize(app, name = nil)
15
+ @app = app
16
+ @header_name = HEADER_NAME
17
+ @header_name += "-#{name}" if name
18
+ end
19
+
20
+ def call(env)
21
+ start_time = Utils.clock_time
22
+ status, headers, body = @app.call(env)
23
+ headers = Utils::HeaderHash[headers]
24
+
25
+ request_time = Utils.clock_time - start_time
26
+
27
+ unless headers.key?(@header_name)
28
+ headers[@header_name] = FORMAT_STRING % request_time
29
+ end
30
+
31
+ [status, headers, body]
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+
5
+ # = Sendfile
6
+ #
7
+ # The Sendfile middleware intercepts responses whose body is being
8
+ # served from a file and replaces it with a server specific X-Sendfile
9
+ # header. The web server is then responsible for writing the file contents
10
+ # to the client. This can dramatically reduce the amount of work required
11
+ # by the Ruby backend and takes advantage of the web server's optimized file
12
+ # delivery code.
13
+ #
14
+ # In order to take advantage of this middleware, the response body must
15
+ # respond to +to_path+ and the request must include an X-Sendfile-Type
16
+ # header. Rack::Files and other components implement +to_path+ so there's
17
+ # rarely anything you need to do in your application. The X-Sendfile-Type
18
+ # header is typically set in your web servers configuration. The following
19
+ # sections attempt to document
20
+ #
21
+ # === Nginx
22
+ #
23
+ # Nginx supports the X-Accel-Redirect header. This is similar to X-Sendfile
24
+ # but requires parts of the filesystem to be mapped into a private URL
25
+ # hierarchy.
26
+ #
27
+ # The following example shows the Nginx configuration required to create
28
+ # a private "/files/" area, enable X-Accel-Redirect, and pass the special
29
+ # X-Sendfile-Type and X-Accel-Mapping headers to the backend:
30
+ #
31
+ # location ~ /files/(.*) {
32
+ # internal;
33
+ # alias /var/www/$1;
34
+ # }
35
+ #
36
+ # location / {
37
+ # proxy_redirect off;
38
+ #
39
+ # proxy_set_header Host $host;
40
+ # proxy_set_header X-Real-IP $remote_addr;
41
+ # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
42
+ #
43
+ # proxy_set_header X-Sendfile-Type X-Accel-Redirect;
44
+ # proxy_set_header X-Accel-Mapping /var/www/=/files/;
45
+ #
46
+ # proxy_pass http://127.0.0.1:8080/;
47
+ # }
48
+ #
49
+ # Note that the X-Sendfile-Type header must be set exactly as shown above.
50
+ # The X-Accel-Mapping header should specify the location on the file system,
51
+ # followed by an equals sign (=), followed name of the private URL pattern
52
+ # that it maps to. The middleware performs a simple substitution on the
53
+ # resulting path.
54
+ #
55
+ # See Also: https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile
56
+ #
57
+ # === lighttpd
58
+ #
59
+ # Lighttpd has supported some variation of the X-Sendfile header for some
60
+ # time, although only recent version support X-Sendfile in a reverse proxy
61
+ # configuration.
62
+ #
63
+ # $HTTP["host"] == "example.com" {
64
+ # proxy-core.protocol = "http"
65
+ # proxy-core.balancer = "round-robin"
66
+ # proxy-core.backends = (
67
+ # "127.0.0.1:8000",
68
+ # "127.0.0.1:8001",
69
+ # ...
70
+ # )
71
+ #
72
+ # proxy-core.allow-x-sendfile = "enable"
73
+ # proxy-core.rewrite-request = (
74
+ # "X-Sendfile-Type" => (".*" => "X-Sendfile")
75
+ # )
76
+ # }
77
+ #
78
+ # See Also: http://redmine.lighttpd.net/wiki/lighttpd/Docs:ModProxyCore
79
+ #
80
+ # === Apache
81
+ #
82
+ # X-Sendfile is supported under Apache 2.x using a separate module:
83
+ #
84
+ # https://tn123.org/mod_xsendfile/
85
+ #
86
+ # Once the module is compiled and installed, you can enable it using
87
+ # XSendFile config directive:
88
+ #
89
+ # RequestHeader Set X-Sendfile-Type X-Sendfile
90
+ # ProxyPassReverse / http://localhost:8001/
91
+ # XSendFile on
92
+ #
93
+ # === Mapping parameter
94
+ #
95
+ # The third parameter allows for an overriding extension of the
96
+ # X-Accel-Mapping header. Mappings should be provided in tuples of internal to
97
+ # external. The internal values may contain regular expression syntax, they
98
+ # will be matched with case indifference.
99
+
100
+ class Sendfile
101
+ def initialize(app, variation = nil, mappings = [])
102
+ @app = app
103
+ @variation = variation
104
+ @mappings = mappings.map do |internal, external|
105
+ [/^#{internal}/i, external]
106
+ end
107
+ end
108
+
109
+ def call(env)
110
+ status, headers, body = @app.call(env)
111
+ if body.respond_to?(:to_path)
112
+ case type = variation(env)
113
+ when 'X-Accel-Redirect'
114
+ path = ::File.expand_path(body.to_path)
115
+ if url = map_accel_path(env, path)
116
+ headers[CONTENT_LENGTH] = '0'
117
+ # '?' must be percent-encoded because it is not query string but a part of path
118
+ headers[type] = ::Rack::Utils.escape_path(url).gsub('?', '%3F')
119
+ obody = body
120
+ body = Rack::BodyProxy.new([]) do
121
+ obody.close if obody.respond_to?(:close)
122
+ end
123
+ else
124
+ env[RACK_ERRORS].puts "X-Accel-Mapping header missing"
125
+ end
126
+ when 'X-Sendfile', 'X-Lighttpd-Send-File'
127
+ path = ::File.expand_path(body.to_path)
128
+ headers[CONTENT_LENGTH] = '0'
129
+ headers[type] = path
130
+ obody = body
131
+ body = Rack::BodyProxy.new([]) do
132
+ obody.close if obody.respond_to?(:close)
133
+ end
134
+ when '', nil
135
+ else
136
+ env[RACK_ERRORS].puts "Unknown x-sendfile variation: '#{type}'.\n"
137
+ end
138
+ end
139
+ [status, headers, body]
140
+ end
141
+
142
+ private
143
+ def variation(env)
144
+ @variation ||
145
+ env['sendfile.type'] ||
146
+ env['HTTP_X_SENDFILE_TYPE']
147
+ end
148
+
149
+ def map_accel_path(env, path)
150
+ if mapping = @mappings.find { |internal, _| internal =~ path }
151
+ path.sub(*mapping)
152
+ elsif mapping = env['HTTP_X_ACCEL_MAPPING']
153
+ mapping.split(',').map(&:strip).each do |m|
154
+ internal, external = m.split('=', 2).map(&:strip)
155
+ new_path = path.sub(/^#{internal}/i, external)
156
+ return new_path unless path == new_path
157
+ end
158
+ path
159
+ end
160
+ end
161
+ end
162
+ end