shopify-cli 1.3.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (206) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +2 -2
  3. data/.github/CONTRIBUTING.md +9 -1
  4. data/.github/PULL_REQUEST_TEMPLATE.md +10 -1
  5. data/.github/workflows/release.yml +61 -0
  6. data/.github/workflows/triage.yml +22 -0
  7. data/.gitignore +0 -1
  8. data/.rubocop.yml +61 -8
  9. data/.rubocop_todo.yml +11 -0
  10. data/.travis.yml +1 -0
  11. data/CHANGELOG.md +30 -0
  12. data/Gemfile +3 -2
  13. data/Gemfile.lock +39 -37
  14. data/README.md +39 -7
  15. data/RELEASING.md +19 -29
  16. data/Rakefile +2 -0
  17. data/dev.yml +2 -2
  18. data/docs/_config.yml +1 -18
  19. data/docs/app/node/commands/index.md +2 -80
  20. data/docs/app/node/index.md +2 -33
  21. data/docs/app/rails/commands/index.md +2 -78
  22. data/docs/app/rails/index.md +2 -34
  23. data/docs/core/index.md +2 -84
  24. data/docs/getting-started/index.md +2 -25
  25. data/docs/getting-started/install/index.md +1 -118
  26. data/docs/getting-started/migrate/index.md +2 -94
  27. data/docs/getting-started/uninstall/index.md +2 -35
  28. data/docs/getting-started/upgrade/index.md +2 -39
  29. data/docs/help/start-app/index.md +2 -4
  30. data/docs/index.md +2 -24
  31. data/install.sh +1 -1
  32. data/lib/project_types/extension/cli.rb +21 -11
  33. data/lib/project_types/extension/commands/extension_command.rb +2 -2
  34. data/lib/project_types/extension/features/argo.rb +117 -0
  35. data/lib/project_types/extension/forms/create.rb +2 -2
  36. data/lib/project_types/extension/models/specification.rb +35 -0
  37. data/lib/project_types/extension/models/specification_handlers/checkout_post_purchase.rb +19 -0
  38. data/lib/project_types/extension/models/specification_handlers/default.rb +67 -0
  39. data/lib/project_types/extension/models/specifications.rb +77 -0
  40. data/lib/project_types/extension/tasks/configure_features.rb +52 -0
  41. data/lib/project_types/extension/tasks/fetch_specifications.rb +38 -0
  42. data/lib/project_types/node/cli.rb +4 -1
  43. data/lib/project_types/node/commands/connect.rb +15 -0
  44. data/lib/project_types/node/commands/create.rb +10 -4
  45. data/lib/project_types/node/commands/generate.rb +2 -11
  46. data/lib/project_types/node/messages/messages.rb +16 -50
  47. data/lib/project_types/rails/cli.rb +4 -1
  48. data/lib/project_types/rails/commands/connect.rb +15 -0
  49. data/lib/project_types/rails/commands/create.rb +15 -12
  50. data/lib/project_types/rails/forms/create.rb +1 -1
  51. data/lib/project_types/rails/gem.rb +1 -1
  52. data/lib/project_types/rails/messages/messages.rb +8 -5
  53. data/lib/project_types/script/cli.rb +9 -5
  54. data/lib/project_types/script/commands/create.rb +6 -4
  55. data/lib/project_types/script/commands/enable.rb +12 -4
  56. data/lib/project_types/script/commands/push.rb +5 -13
  57. data/lib/project_types/script/config/extension_points.yml +17 -12
  58. data/lib/project_types/script/errors.rb +21 -0
  59. data/lib/project_types/script/forms/create.rb +26 -2
  60. data/lib/project_types/script/graphql/app_script_update_or_create.graphql +10 -1
  61. data/lib/project_types/script/layers/application/build_script.rb +18 -17
  62. data/lib/project_types/script/layers/application/create_script.rb +12 -10
  63. data/lib/project_types/script/layers/application/extension_points.rb +24 -0
  64. data/lib/project_types/script/layers/application/push_script.rb +18 -16
  65. data/lib/project_types/script/layers/domain/errors.rb +7 -0
  66. data/lib/project_types/script/layers/domain/extension_point.rb +62 -7
  67. data/lib/project_types/script/layers/domain/metadata.rb +55 -0
  68. data/lib/project_types/script/layers/domain/push_package.rb +25 -6
  69. data/lib/project_types/script/layers/infrastructure/assemblyscript_project_creator.rb +17 -52
  70. data/lib/project_types/script/layers/infrastructure/assemblyscript_task_runner.rb +42 -11
  71. data/lib/project_types/script/layers/infrastructure/errors.rb +16 -0
  72. data/lib/project_types/script/layers/infrastructure/extension_point_repository.rb +10 -4
  73. data/lib/project_types/script/layers/infrastructure/project_creator.rb +2 -1
  74. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +25 -13
  75. data/lib/project_types/script/layers/infrastructure/rust_project_creator.rb +72 -0
  76. data/lib/project_types/script/layers/infrastructure/rust_task_runner.rb +59 -0
  77. data/lib/project_types/script/layers/infrastructure/script_service.rb +9 -1
  78. data/lib/project_types/script/layers/infrastructure/task_runner.rb +4 -3
  79. data/lib/project_types/script/messages/messages.rb +55 -4
  80. data/lib/project_types/script/script_project.rb +25 -16
  81. data/lib/project_types/script/ui/error_handler.rb +59 -1
  82. data/lib/project_types/theme/cli.rb +40 -0
  83. data/lib/project_types/theme/commands/connect.rb +54 -0
  84. data/lib/project_types/theme/commands/create.rb +48 -0
  85. data/lib/project_types/theme/commands/deploy.rb +38 -0
  86. data/lib/project_types/theme/commands/generate.rb +20 -0
  87. data/lib/project_types/theme/commands/generate/env.rb +79 -0
  88. data/lib/project_types/theme/commands/push.rb +55 -0
  89. data/lib/project_types/theme/commands/serve.rb +31 -0
  90. data/lib/project_types/theme/forms/connect.rb +34 -0
  91. data/lib/project_types/theme/forms/create.rb +22 -0
  92. data/lib/project_types/theme/messages/messages.rb +147 -0
  93. data/lib/project_types/theme/tasks/ensure_themekit_installed.rb +78 -0
  94. data/lib/project_types/theme/themekit.rb +113 -0
  95. data/lib/shopify-cli/admin_api.rb +42 -2
  96. data/lib/shopify-cli/api.rb +34 -33
  97. data/lib/shopify-cli/commands/config.rb +24 -0
  98. data/lib/shopify-cli/commands/connect.rb +32 -15
  99. data/lib/shopify-cli/commands/system.rb +10 -1
  100. data/lib/shopify-cli/context.rb +23 -2
  101. data/lib/shopify-cli/core/entry_point.rb +1 -1
  102. data/lib/shopify-cli/core/monorail.rb +6 -4
  103. data/lib/shopify-cli/feature.rb +0 -2
  104. data/lib/shopify-cli/http_request.rb +27 -0
  105. data/lib/shopify-cli/js_deps.rb +1 -1
  106. data/lib/shopify-cli/messages/messages.rb +31 -7
  107. data/lib/shopify-cli/method_object.rb +104 -0
  108. data/lib/shopify-cli/partners_api.rb +25 -3
  109. data/lib/shopify-cli/process_supervision.rb +1 -1
  110. data/lib/shopify-cli/project.rb +12 -8
  111. data/lib/shopify-cli/project_type.rb +18 -2
  112. data/lib/shopify-cli/resolve_constant.rb +25 -0
  113. data/lib/shopify-cli/result.rb +432 -0
  114. data/lib/shopify-cli/shopifolk.rb +87 -0
  115. data/lib/shopify-cli/task.rb +8 -0
  116. data/lib/shopify-cli/tasks/create_api_client.rb +13 -2
  117. data/lib/shopify-cli/tasks/ensure_env.rb +3 -0
  118. data/lib/shopify-cli/tasks/select_org_and_shop.rb +10 -5
  119. data/lib/shopify-cli/tunnel.rb +8 -2
  120. data/lib/shopify-cli/version.rb +1 -1
  121. data/lib/shopify_cli.rb +5 -1
  122. data/shopify.fish +1 -1
  123. data/shopify.sh +1 -1
  124. data/vendor/deps/cli-kit/REVISION +1 -1
  125. data/vendor/deps/cli-kit/lib/cli/kit/logger.rb +2 -2
  126. data/vendor/deps/cli-kit/lib/cli/kit/system.rb +3 -3
  127. data/vendor/deps/cli-ui/REVISION +1 -1
  128. data/vendor/deps/cli-ui/lib/cli/ui.rb +26 -22
  129. data/vendor/deps/cli-ui/lib/cli/ui/ansi.rb +4 -6
  130. data/vendor/deps/cli-ui/lib/cli/ui/frame.rb +3 -3
  131. data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_stack.rb +8 -9
  132. data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style.rb +1 -1
  133. data/vendor/deps/cli-ui/lib/cli/ui/glyph.rb +1 -0
  134. data/vendor/deps/cli-ui/lib/cli/ui/printer.rb +15 -3
  135. data/vendor/deps/cli-ui/lib/cli/ui/prompt/interactive_options.rb +4 -11
  136. data/vendor/deps/cli-ui/lib/cli/ui/spinner.rb +3 -5
  137. data/vendor/deps/cli-ui/lib/cli/ui/terminal.rb +10 -10
  138. data/vendor/deps/cli-ui/lib/cli/ui/version.rb +1 -1
  139. data/vendor/deps/cli-ui/lib/cli/ui/wrap.rb +56 -0
  140. data/vendor/deps/webrick/.gitignore +9 -0
  141. data/vendor/deps/webrick/Gemfile +3 -0
  142. data/vendor/deps/webrick/LICENSE.txt +22 -0
  143. data/vendor/deps/webrick/README.md +61 -0
  144. data/vendor/deps/webrick/Rakefile +10 -0
  145. data/vendor/deps/webrick/lib/webrick.rb +232 -0
  146. data/vendor/deps/webrick/lib/webrick/accesslog.rb +157 -0
  147. data/vendor/deps/webrick/lib/webrick/cgi.rb +313 -0
  148. data/vendor/deps/webrick/lib/webrick/compat.rb +36 -0
  149. data/vendor/deps/webrick/lib/webrick/config.rb +158 -0
  150. data/vendor/deps/webrick/lib/webrick/cookie.rb +172 -0
  151. data/vendor/deps/webrick/lib/webrick/htmlutils.rb +30 -0
  152. data/vendor/deps/webrick/lib/webrick/httpauth.rb +96 -0
  153. data/vendor/deps/webrick/lib/webrick/httpauth/authenticator.rb +117 -0
  154. data/vendor/deps/webrick/lib/webrick/httpauth/basicauth.rb +116 -0
  155. data/vendor/deps/webrick/lib/webrick/httpauth/digestauth.rb +395 -0
  156. data/vendor/deps/webrick/lib/webrick/httpauth/htdigest.rb +132 -0
  157. data/vendor/deps/webrick/lib/webrick/httpauth/htgroup.rb +97 -0
  158. data/vendor/deps/webrick/lib/webrick/httpauth/htpasswd.rb +158 -0
  159. data/vendor/deps/webrick/lib/webrick/httpauth/userdb.rb +53 -0
  160. data/vendor/deps/webrick/lib/webrick/httpproxy.rb +354 -0
  161. data/vendor/deps/webrick/lib/webrick/httprequest.rb +636 -0
  162. data/vendor/deps/webrick/lib/webrick/httpresponse.rb +564 -0
  163. data/vendor/deps/webrick/lib/webrick/https.rb +152 -0
  164. data/vendor/deps/webrick/lib/webrick/httpserver.rb +294 -0
  165. data/vendor/deps/webrick/lib/webrick/httpservlet.rb +23 -0
  166. data/vendor/deps/webrick/lib/webrick/httpservlet/abstract.rb +152 -0
  167. data/vendor/deps/webrick/lib/webrick/httpservlet/cgi_runner.rb +47 -0
  168. data/vendor/deps/webrick/lib/webrick/httpservlet/cgihandler.rb +126 -0
  169. data/vendor/deps/webrick/lib/webrick/httpservlet/erbhandler.rb +88 -0
  170. data/vendor/deps/webrick/lib/webrick/httpservlet/filehandler.rb +552 -0
  171. data/vendor/deps/webrick/lib/webrick/httpservlet/prochandler.rb +47 -0
  172. data/vendor/deps/webrick/lib/webrick/httpstatus.rb +194 -0
  173. data/vendor/deps/webrick/lib/webrick/httputils.rb +512 -0
  174. data/vendor/deps/webrick/lib/webrick/httpversion.rb +76 -0
  175. data/vendor/deps/webrick/lib/webrick/log.rb +156 -0
  176. data/vendor/deps/webrick/lib/webrick/server.rb +381 -0
  177. data/vendor/deps/webrick/lib/webrick/ssl.rb +215 -0
  178. data/vendor/deps/webrick/lib/webrick/utils.rb +265 -0
  179. data/vendor/deps/webrick/lib/webrick/version.rb +18 -0
  180. data/vendor/deps/webrick/webrick.gemspec +74 -0
  181. metadata +77 -27
  182. data/docs/Gemfile +0 -5
  183. data/docs/Gemfile.lock +0 -258
  184. data/docs/_data/nav.yml +0 -35
  185. data/docs/_includes/footer.html +0 -15
  186. data/docs/_includes/head.html +0 -19
  187. data/docs/_includes/sidebar_nav.html +0 -22
  188. data/docs/_includes/toc.html +0 -112
  189. data/docs/_layouts/default.html +0 -79
  190. data/docs/css/docs.css +0 -157
  191. data/docs/images/header.png +0 -0
  192. data/docs/installing-ruby.md +0 -28
  193. data/lib/project_types/extension/features/argo/admin.rb +0 -20
  194. data/lib/project_types/extension/features/argo/base.rb +0 -129
  195. data/lib/project_types/extension/features/argo/checkout.rb +0 -20
  196. data/lib/project_types/extension/models/type.rb +0 -81
  197. data/lib/project_types/extension/models/types/checkout_post_purchase.rb +0 -23
  198. data/lib/project_types/extension/models/types/product_subscription.rb +0 -24
  199. data/lib/project_types/node/commands/generate/billing.rb +0 -39
  200. data/lib/project_types/node/commands/generate/page.rb +0 -59
  201. data/lib/project_types/node/commands/generate/webhook.rb +0 -37
  202. data/lib/project_types/script/layers/domain/script.rb +0 -18
  203. data/lib/project_types/script/layers/infrastructure/assemblyscript_tsconfig.rb +0 -38
  204. data/lib/project_types/script/layers/infrastructure/script_repository.rb +0 -59
  205. data/lib/project_types/script/templates/ts/as-pect.config.js +0 -27
  206. data/lib/project_types/script/templates/ts/as-pect.d.ts +0 -1
@@ -0,0 +1,636 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # httprequest.rb -- HTTPRequest Class
4
+ #
5
+ # Author: IPR -- Internet Programming with Ruby -- writers
6
+ # Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
7
+ # Copyright (c) 2002 Internet Programming with Ruby writers. All rights
8
+ # reserved.
9
+ #
10
+ # $IPR: httprequest.rb,v 1.64 2003/07/13 17:18:22 gotoyuzo Exp $
11
+
12
+ require 'fiber'
13
+ require 'uri'
14
+ require_relative 'httpversion'
15
+ require_relative 'httpstatus'
16
+ require_relative 'httputils'
17
+ require_relative 'cookie'
18
+
19
+ module WEBrick
20
+
21
+ ##
22
+ # An HTTP request. This is consumed by service and do_* methods in
23
+ # WEBrick servlets
24
+
25
+ class HTTPRequest
26
+
27
+ BODY_CONTAINABLE_METHODS = [ "POST", "PUT" ] # :nodoc:
28
+
29
+ # :section: Request line
30
+
31
+ ##
32
+ # The complete request line such as:
33
+ #
34
+ # GET / HTTP/1.1
35
+
36
+ attr_reader :request_line
37
+
38
+ ##
39
+ # The request method, GET, POST, PUT, etc.
40
+
41
+ attr_reader :request_method
42
+
43
+ ##
44
+ # The unparsed URI of the request
45
+
46
+ attr_reader :unparsed_uri
47
+
48
+ ##
49
+ # The HTTP version of the request
50
+
51
+ attr_reader :http_version
52
+
53
+ # :section: Request-URI
54
+
55
+ ##
56
+ # The parsed URI of the request
57
+
58
+ attr_reader :request_uri
59
+
60
+ ##
61
+ # The request path
62
+
63
+ attr_reader :path
64
+
65
+ ##
66
+ # The script name (CGI variable)
67
+
68
+ attr_accessor :script_name
69
+
70
+ ##
71
+ # The path info (CGI variable)
72
+
73
+ attr_accessor :path_info
74
+
75
+ ##
76
+ # The query from the URI of the request
77
+
78
+ attr_accessor :query_string
79
+
80
+ # :section: Header and entity body
81
+
82
+ ##
83
+ # The raw header of the request
84
+
85
+ attr_reader :raw_header
86
+
87
+ ##
88
+ # The parsed header of the request
89
+
90
+ attr_reader :header
91
+
92
+ ##
93
+ # The parsed request cookies
94
+
95
+ attr_reader :cookies
96
+
97
+ ##
98
+ # The Accept header value
99
+
100
+ attr_reader :accept
101
+
102
+ ##
103
+ # The Accept-Charset header value
104
+
105
+ attr_reader :accept_charset
106
+
107
+ ##
108
+ # The Accept-Encoding header value
109
+
110
+ attr_reader :accept_encoding
111
+
112
+ ##
113
+ # The Accept-Language header value
114
+
115
+ attr_reader :accept_language
116
+
117
+ # :section:
118
+
119
+ ##
120
+ # The remote user (CGI variable)
121
+
122
+ attr_accessor :user
123
+
124
+ ##
125
+ # The socket address of the server
126
+
127
+ attr_reader :addr
128
+
129
+ ##
130
+ # The socket address of the client
131
+
132
+ attr_reader :peeraddr
133
+
134
+ ##
135
+ # Hash of request attributes
136
+
137
+ attr_reader :attributes
138
+
139
+ ##
140
+ # Is this a keep-alive connection?
141
+
142
+ attr_reader :keep_alive
143
+
144
+ ##
145
+ # The local time this request was received
146
+
147
+ attr_reader :request_time
148
+
149
+ ##
150
+ # Creates a new HTTP request. WEBrick::Config::HTTP is the default
151
+ # configuration.
152
+
153
+ def initialize(config)
154
+ @config = config
155
+ @buffer_size = @config[:InputBufferSize]
156
+ @logger = config[:Logger]
157
+
158
+ @request_line = @request_method =
159
+ @unparsed_uri = @http_version = nil
160
+
161
+ @request_uri = @host = @port = @path = nil
162
+ @script_name = @path_info = nil
163
+ @query_string = nil
164
+ @query = nil
165
+ @form_data = nil
166
+
167
+ @raw_header = Array.new
168
+ @header = nil
169
+ @cookies = []
170
+ @accept = []
171
+ @accept_charset = []
172
+ @accept_encoding = []
173
+ @accept_language = []
174
+ @body = +""
175
+
176
+ @addr = @peeraddr = nil
177
+ @attributes = {}
178
+ @user = nil
179
+ @keep_alive = false
180
+ @request_time = nil
181
+
182
+ @remaining_size = nil
183
+ @socket = nil
184
+
185
+ @forwarded_proto = @forwarded_host = @forwarded_port =
186
+ @forwarded_server = @forwarded_for = nil
187
+ end
188
+
189
+ ##
190
+ # Parses a request from +socket+. This is called internally by
191
+ # WEBrick::HTTPServer.
192
+
193
+ def parse(socket=nil)
194
+ @socket = socket
195
+ begin
196
+ @peeraddr = socket.respond_to?(:peeraddr) ? socket.peeraddr : []
197
+ @addr = socket.respond_to?(:addr) ? socket.addr : []
198
+ rescue Errno::ENOTCONN
199
+ raise HTTPStatus::EOFError
200
+ end
201
+
202
+ read_request_line(socket)
203
+ if @http_version.major > 0
204
+ read_header(socket)
205
+ @header['cookie'].each{|cookie|
206
+ @cookies += Cookie::parse(cookie)
207
+ }
208
+ @accept = HTTPUtils.parse_qvalues(self['accept'])
209
+ @accept_charset = HTTPUtils.parse_qvalues(self['accept-charset'])
210
+ @accept_encoding = HTTPUtils.parse_qvalues(self['accept-encoding'])
211
+ @accept_language = HTTPUtils.parse_qvalues(self['accept-language'])
212
+ end
213
+ return if @request_method == "CONNECT"
214
+ return if @unparsed_uri == "*"
215
+
216
+ begin
217
+ setup_forwarded_info
218
+ @request_uri = parse_uri(@unparsed_uri)
219
+ @path = HTTPUtils::unescape(@request_uri.path)
220
+ @path = HTTPUtils::normalize_path(@path)
221
+ @host = @request_uri.host
222
+ @port = @request_uri.port
223
+ @query_string = @request_uri.query
224
+ @script_name = ""
225
+ @path_info = @path.dup
226
+ rescue
227
+ raise HTTPStatus::BadRequest, "bad URI `#{@unparsed_uri}'."
228
+ end
229
+
230
+ if /\Aclose\z/io =~ self["connection"]
231
+ @keep_alive = false
232
+ elsif /\Akeep-alive\z/io =~ self["connection"]
233
+ @keep_alive = true
234
+ elsif @http_version < "1.1"
235
+ @keep_alive = false
236
+ else
237
+ @keep_alive = true
238
+ end
239
+ end
240
+
241
+ ##
242
+ # Generate HTTP/1.1 100 continue response if the client expects it,
243
+ # otherwise does nothing.
244
+
245
+ def continue # :nodoc:
246
+ if self['expect'] == '100-continue' && @config[:HTTPVersion] >= "1.1"
247
+ @socket << "HTTP/#{@config[:HTTPVersion]} 100 continue#{CRLF}#{CRLF}"
248
+ @header.delete('expect')
249
+ end
250
+ end
251
+
252
+ ##
253
+ # Returns the request body.
254
+
255
+ def body(&block) # :yields: body_chunk
256
+ block ||= Proc.new{|chunk| @body << chunk }
257
+ read_body(@socket, block)
258
+ @body.empty? ? nil : @body
259
+ end
260
+
261
+ ##
262
+ # Prepares the HTTPRequest object for use as the
263
+ # source for IO.copy_stream
264
+
265
+ def body_reader
266
+ @body_tmp = []
267
+ @body_rd = Fiber.new do
268
+ body do |buf|
269
+ @body_tmp << buf
270
+ Fiber.yield
271
+ end
272
+ end
273
+ @body_rd.resume # grab the first chunk and yield
274
+ self
275
+ end
276
+
277
+ # for IO.copy_stream.
278
+ def readpartial(size, buf = ''.b) # :nodoc
279
+ res = @body_tmp.shift or raise EOFError, 'end of file reached'
280
+ if res.length > size
281
+ @body_tmp.unshift(res[size..-1])
282
+ res = res[0..size - 1]
283
+ end
284
+ buf.replace(res)
285
+ res.clear
286
+ # get more chunks - check alive? because we can take a partial chunk
287
+ @body_rd.resume if @body_rd.alive?
288
+ buf
289
+ end
290
+
291
+ ##
292
+ # Request query as a Hash
293
+
294
+ def query
295
+ unless @query
296
+ parse_query()
297
+ end
298
+ @query
299
+ end
300
+
301
+ ##
302
+ # The content-length header
303
+
304
+ def content_length
305
+ return Integer(self['content-length'])
306
+ end
307
+
308
+ ##
309
+ # The content-type header
310
+
311
+ def content_type
312
+ return self['content-type']
313
+ end
314
+
315
+ ##
316
+ # Retrieves +header_name+
317
+
318
+ def [](header_name)
319
+ if @header
320
+ value = @header[header_name.downcase]
321
+ value.empty? ? nil : value.join(", ")
322
+ end
323
+ end
324
+
325
+ ##
326
+ # Iterates over the request headers
327
+
328
+ def each
329
+ if @header
330
+ @header.each{|k, v|
331
+ value = @header[k]
332
+ yield(k, value.empty? ? nil : value.join(", "))
333
+ }
334
+ end
335
+ end
336
+
337
+ ##
338
+ # The host this request is for
339
+
340
+ def host
341
+ return @forwarded_host || @host
342
+ end
343
+
344
+ ##
345
+ # The port this request is for
346
+
347
+ def port
348
+ return @forwarded_port || @port
349
+ end
350
+
351
+ ##
352
+ # The server name this request is for
353
+
354
+ def server_name
355
+ return @forwarded_server || @config[:ServerName]
356
+ end
357
+
358
+ ##
359
+ # The client's IP address
360
+
361
+ def remote_ip
362
+ return self["client-ip"] || @forwarded_for || @peeraddr[3]
363
+ end
364
+
365
+ ##
366
+ # Is this an SSL request?
367
+
368
+ def ssl?
369
+ return @request_uri.scheme == "https"
370
+ end
371
+
372
+ ##
373
+ # Should the connection this request was made on be kept alive?
374
+
375
+ def keep_alive?
376
+ @keep_alive
377
+ end
378
+
379
+ def to_s # :nodoc:
380
+ ret = @request_line.dup
381
+ @raw_header.each{|line| ret << line }
382
+ ret << CRLF
383
+ ret << body if body
384
+ ret
385
+ end
386
+
387
+ ##
388
+ # Consumes any remaining body and updates keep-alive status
389
+
390
+ def fixup() # :nodoc:
391
+ begin
392
+ body{|chunk| } # read remaining body
393
+ rescue HTTPStatus::Error => ex
394
+ @logger.error("HTTPRequest#fixup: #{ex.class} occurred.")
395
+ @keep_alive = false
396
+ rescue => ex
397
+ @logger.error(ex)
398
+ @keep_alive = false
399
+ end
400
+ end
401
+
402
+ # This method provides the metavariables defined by the revision 3
403
+ # of "The WWW Common Gateway Interface Version 1.1"
404
+ # To browse the current document of CGI Version 1.1, see below:
405
+ # http://tools.ietf.org/html/rfc3875
406
+
407
+ def meta_vars
408
+ meta = Hash.new
409
+
410
+ cl = self["Content-Length"]
411
+ ct = self["Content-Type"]
412
+ meta["CONTENT_LENGTH"] = cl if cl.to_i > 0
413
+ meta["CONTENT_TYPE"] = ct.dup if ct
414
+ meta["GATEWAY_INTERFACE"] = "CGI/1.1"
415
+ meta["PATH_INFO"] = @path_info ? @path_info.dup : ""
416
+ #meta["PATH_TRANSLATED"] = nil # no plan to be provided
417
+ meta["QUERY_STRING"] = @query_string ? @query_string.dup : ""
418
+ meta["REMOTE_ADDR"] = @peeraddr[3]
419
+ meta["REMOTE_HOST"] = @peeraddr[2]
420
+ #meta["REMOTE_IDENT"] = nil # no plan to be provided
421
+ meta["REMOTE_USER"] = @user
422
+ meta["REQUEST_METHOD"] = @request_method.dup
423
+ meta["REQUEST_URI"] = @request_uri.to_s
424
+ meta["SCRIPT_NAME"] = @script_name.dup
425
+ meta["SERVER_NAME"] = @host
426
+ meta["SERVER_PORT"] = @port.to_s
427
+ meta["SERVER_PROTOCOL"] = "HTTP/" + @config[:HTTPVersion].to_s
428
+ meta["SERVER_SOFTWARE"] = @config[:ServerSoftware].dup
429
+
430
+ self.each{|key, val|
431
+ next if /^content-type$/i =~ key
432
+ next if /^content-length$/i =~ key
433
+ name = "HTTP_" + key
434
+ name.gsub!(/-/o, "_")
435
+ name.upcase!
436
+ meta[name] = val
437
+ }
438
+
439
+ meta
440
+ end
441
+
442
+ private
443
+
444
+ # :stopdoc:
445
+
446
+ MAX_URI_LENGTH = 2083 # :nodoc:
447
+
448
+ # same as Mongrel, Thin and Puma
449
+ MAX_HEADER_LENGTH = (112 * 1024) # :nodoc:
450
+
451
+ def read_request_line(socket)
452
+ @request_line = read_line(socket, MAX_URI_LENGTH) if socket
453
+ raise HTTPStatus::EOFError unless @request_line
454
+
455
+ @request_bytes = @request_line.bytesize
456
+ if @request_bytes >= MAX_URI_LENGTH and @request_line[-1, 1] != LF
457
+ raise HTTPStatus::RequestURITooLarge
458
+ end
459
+
460
+ @request_time = Time.now
461
+ if /^(\S+)\s+(\S++)(?:\s+HTTP\/(\d+\.\d+))?\r?\n/mo =~ @request_line
462
+ @request_method = $1
463
+ @unparsed_uri = $2
464
+ @http_version = HTTPVersion.new($3 ? $3 : "0.9")
465
+ else
466
+ rl = @request_line.sub(/\x0d?\x0a\z/o, '')
467
+ raise HTTPStatus::BadRequest, "bad Request-Line `#{rl}'."
468
+ end
469
+ end
470
+
471
+ def read_header(socket)
472
+ if socket
473
+ while line = read_line(socket)
474
+ break if /\A(#{CRLF}|#{LF})\z/om =~ line
475
+ if (@request_bytes += line.bytesize) > MAX_HEADER_LENGTH
476
+ raise HTTPStatus::RequestEntityTooLarge, 'headers too large'
477
+ end
478
+ @raw_header << line
479
+ end
480
+ end
481
+ @header = HTTPUtils::parse_header(@raw_header.join)
482
+ end
483
+
484
+ def parse_uri(str, scheme="http")
485
+ if @config[:Escape8bitURI]
486
+ str = HTTPUtils::escape8bit(str)
487
+ end
488
+ str.sub!(%r{\A/+}o, '/')
489
+ uri = URI::parse(str)
490
+ return uri if uri.absolute?
491
+ if @forwarded_host
492
+ host, port = @forwarded_host, @forwarded_port
493
+ elsif self["host"]
494
+ pattern = /\A(#{URI::REGEXP::PATTERN::HOST})(?::(\d+))?\z/n
495
+ host, port = *self['host'].scan(pattern)[0]
496
+ elsif @addr.size > 0
497
+ host, port = @addr[2], @addr[1]
498
+ else
499
+ host, port = @config[:ServerName], @config[:Port]
500
+ end
501
+ uri.scheme = @forwarded_proto || scheme
502
+ uri.host = host
503
+ uri.port = port ? port.to_i : nil
504
+ return URI::parse(uri.to_s)
505
+ end
506
+
507
+ def read_body(socket, block)
508
+ return unless socket
509
+ if tc = self['transfer-encoding']
510
+ case tc
511
+ when /\Achunked\z/io then read_chunked(socket, block)
512
+ else raise HTTPStatus::NotImplemented, "Transfer-Encoding: #{tc}."
513
+ end
514
+ elsif self['content-length'] || @remaining_size
515
+ @remaining_size ||= self['content-length'].to_i
516
+ while @remaining_size > 0
517
+ sz = [@buffer_size, @remaining_size].min
518
+ break unless buf = read_data(socket, sz)
519
+ @remaining_size -= buf.bytesize
520
+ block.call(buf)
521
+ end
522
+ if @remaining_size > 0 && @socket.eof?
523
+ raise HTTPStatus::BadRequest, "invalid body size."
524
+ end
525
+ elsif BODY_CONTAINABLE_METHODS.member?(@request_method) && !@socket.eof
526
+ raise HTTPStatus::LengthRequired
527
+ end
528
+ return @body
529
+ end
530
+
531
+ def read_chunk_size(socket)
532
+ line = read_line(socket)
533
+ if /^([0-9a-fA-F]+)(?:;(\S+))?/ =~ line
534
+ chunk_size = $1.hex
535
+ chunk_ext = $2
536
+ [ chunk_size, chunk_ext ]
537
+ else
538
+ raise HTTPStatus::BadRequest, "bad chunk `#{line}'."
539
+ end
540
+ end
541
+
542
+ def read_chunked(socket, block)
543
+ chunk_size, = read_chunk_size(socket)
544
+ while chunk_size > 0
545
+ begin
546
+ sz = [ chunk_size, @buffer_size ].min
547
+ data = read_data(socket, sz) # read chunk-data
548
+ if data.nil? || data.bytesize != sz
549
+ raise HTTPStatus::BadRequest, "bad chunk data size."
550
+ end
551
+ block.call(data)
552
+ end while (chunk_size -= sz) > 0
553
+
554
+ read_line(socket) # skip CRLF
555
+ chunk_size, = read_chunk_size(socket)
556
+ end
557
+ read_header(socket) # trailer + CRLF
558
+ @header.delete("transfer-encoding")
559
+ @remaining_size = 0
560
+ end
561
+
562
+ def _read_data(io, method, *arg)
563
+ begin
564
+ WEBrick::Utils.timeout(@config[:RequestTimeout]){
565
+ return io.__send__(method, *arg)
566
+ }
567
+ rescue Errno::ECONNRESET
568
+ return nil
569
+ rescue Timeout::Error
570
+ raise HTTPStatus::RequestTimeout
571
+ end
572
+ end
573
+
574
+ def read_line(io, size=4096)
575
+ _read_data(io, :gets, LF, size)
576
+ end
577
+
578
+ def read_data(io, size)
579
+ _read_data(io, :read, size)
580
+ end
581
+
582
+ def parse_query()
583
+ begin
584
+ if @request_method == "GET" || @request_method == "HEAD"
585
+ @query = HTTPUtils::parse_query(@query_string)
586
+ elsif self['content-type'] =~ /^application\/x-www-form-urlencoded/
587
+ @query = HTTPUtils::parse_query(body)
588
+ elsif self['content-type'] =~ /^multipart\/form-data; boundary=(.+)/
589
+ boundary = HTTPUtils::dequote($1)
590
+ @query = HTTPUtils::parse_form_data(body, boundary)
591
+ else
592
+ @query = Hash.new
593
+ end
594
+ rescue => ex
595
+ raise HTTPStatus::BadRequest, ex.message
596
+ end
597
+ end
598
+
599
+ PrivateNetworkRegexp = /
600
+ ^unknown$|
601
+ ^((::ffff:)?127.0.0.1|::1)$|
602
+ ^(::ffff:)?(10|172\.(1[6-9]|2[0-9]|3[01])|192\.168)\.
603
+ /ixo
604
+
605
+ # It's said that all X-Forwarded-* headers will contain more than one
606
+ # (comma-separated) value if the original request already contained one of
607
+ # these headers. Since we could use these values as Host header, we choose
608
+ # the initial(first) value. (apr_table_mergen() adds new value after the
609
+ # existing value with ", " prefix)
610
+ def setup_forwarded_info
611
+ if @forwarded_server = self["x-forwarded-server"]
612
+ @forwarded_server = @forwarded_server.split(",", 2).first
613
+ end
614
+ if @forwarded_proto = self["x-forwarded-proto"]
615
+ @forwarded_proto = @forwarded_proto.split(",", 2).first
616
+ end
617
+ if host_port = self["x-forwarded-host"]
618
+ host_port = host_port.split(",", 2).first
619
+ if host_port =~ /\A(\[[0-9a-fA-F:]+\])(?::(\d+))?\z/
620
+ @forwarded_host = $1
621
+ tmp = $2
622
+ else
623
+ @forwarded_host, tmp = host_port.split(":", 2)
624
+ end
625
+ @forwarded_port = (tmp || (@forwarded_proto == "https" ? 443 : 80)).to_i
626
+ end
627
+ if addrs = self["x-forwarded-for"]
628
+ addrs = addrs.split(",").collect(&:strip)
629
+ addrs.reject!{|ip| PrivateNetworkRegexp =~ ip }
630
+ @forwarded_for = addrs.first
631
+ end
632
+ end
633
+
634
+ # :startdoc:
635
+ end
636
+ end