shopify-cli 1.5.0 → 1.6.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 (179) hide show
  1. checksums.yaml +4 -4
  2. data/.github/PULL_REQUEST_TEMPLATE.md +1 -0
  3. data/.travis.yml +1 -0
  4. data/CHANGELOG.md +9 -0
  5. data/README.md +39 -7
  6. data/Rakefile +2 -0
  7. data/dev.yml +2 -2
  8. data/docs/_config.yml +1 -18
  9. data/docs/app/node/commands/index.md +2 -80
  10. data/docs/app/node/index.md +2 -33
  11. data/docs/app/rails/commands/index.md +2 -78
  12. data/docs/app/rails/index.md +2 -34
  13. data/docs/core/index.md +2 -84
  14. data/docs/getting-started/index.md +2 -25
  15. data/docs/getting-started/install/index.md +1 -118
  16. data/docs/getting-started/migrate/index.md +2 -94
  17. data/docs/getting-started/uninstall/index.md +2 -35
  18. data/docs/getting-started/upgrade/index.md +2 -39
  19. data/docs/help/start-app/index.md +2 -4
  20. data/docs/index.md +2 -24
  21. data/install.sh +1 -1
  22. data/lib/project_types/extension/cli.rb +19 -10
  23. data/lib/project_types/extension/commands/extension_command.rb +2 -2
  24. data/lib/project_types/extension/features/argo.rb +117 -0
  25. data/lib/project_types/extension/forms/create.rb +2 -2
  26. data/lib/project_types/extension/models/specification.rb +35 -0
  27. data/lib/project_types/extension/models/specification_handlers/checkout_post_purchase.rb +19 -0
  28. data/lib/project_types/extension/models/specification_handlers/default.rb +67 -0
  29. data/lib/project_types/extension/models/specifications.rb +77 -0
  30. data/lib/project_types/extension/tasks/configure_features.rb +52 -0
  31. data/lib/project_types/extension/tasks/fetch_specifications.rb +38 -0
  32. data/lib/project_types/node/commands/create.rb +3 -1
  33. data/lib/project_types/node/commands/generate.rb +2 -11
  34. data/lib/project_types/node/messages/messages.rb +9 -44
  35. data/lib/project_types/rails/commands/create.rb +8 -9
  36. data/lib/project_types/rails/forms/create.rb +1 -1
  37. data/lib/project_types/rails/gem.rb +1 -1
  38. data/lib/project_types/rails/messages/messages.rb +1 -1
  39. data/lib/project_types/script/cli.rb +7 -4
  40. data/lib/project_types/script/commands/create.rb +6 -4
  41. data/lib/project_types/script/commands/push.rb +5 -13
  42. data/lib/project_types/script/config/extension_points.yml +9 -5
  43. data/lib/project_types/script/errors.rb +17 -0
  44. data/lib/project_types/script/forms/create.rb +26 -2
  45. data/lib/project_types/script/graphql/app_script_update_or_create.graphql +10 -1
  46. data/lib/project_types/script/layers/application/build_script.rb +9 -4
  47. data/lib/project_types/script/layers/application/create_script.rb +12 -10
  48. data/lib/project_types/script/layers/application/extension_points.rb +24 -0
  49. data/lib/project_types/script/layers/application/push_script.rb +18 -16
  50. data/lib/project_types/script/layers/domain/errors.rb +4 -0
  51. data/lib/project_types/script/layers/domain/extension_point.rb +62 -6
  52. data/lib/project_types/script/layers/domain/metadata.rb +55 -0
  53. data/lib/project_types/script/layers/domain/push_package.rb +25 -6
  54. data/lib/project_types/script/layers/infrastructure/assemblyscript_project_creator.rb +6 -6
  55. data/lib/project_types/script/layers/infrastructure/assemblyscript_task_runner.rb +16 -6
  56. data/lib/project_types/script/layers/infrastructure/extension_point_repository.rb +10 -4
  57. data/lib/project_types/script/layers/infrastructure/project_creator.rb +2 -1
  58. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +25 -13
  59. data/lib/project_types/script/layers/infrastructure/rust_project_creator.rb +72 -0
  60. data/lib/project_types/script/layers/infrastructure/rust_task_runner.rb +59 -0
  61. data/lib/project_types/script/layers/infrastructure/script_service.rb +7 -1
  62. data/lib/project_types/script/layers/infrastructure/task_runner.rb +4 -3
  63. data/lib/project_types/script/messages/messages.rb +39 -8
  64. data/lib/project_types/script/script_project.rb +25 -16
  65. data/lib/project_types/script/ui/error_handler.rb +34 -1
  66. data/lib/project_types/theme/cli.rb +40 -0
  67. data/lib/project_types/theme/commands/connect.rb +54 -0
  68. data/lib/project_types/theme/commands/create.rb +48 -0
  69. data/lib/project_types/theme/commands/deploy.rb +38 -0
  70. data/lib/project_types/theme/commands/generate.rb +20 -0
  71. data/lib/project_types/theme/commands/generate/env.rb +79 -0
  72. data/lib/project_types/theme/commands/push.rb +55 -0
  73. data/lib/project_types/theme/commands/serve.rb +31 -0
  74. data/lib/project_types/theme/forms/connect.rb +34 -0
  75. data/lib/project_types/theme/forms/create.rb +22 -0
  76. data/lib/project_types/theme/messages/messages.rb +147 -0
  77. data/lib/project_types/theme/tasks/ensure_themekit_installed.rb +78 -0
  78. data/lib/project_types/theme/themekit.rb +113 -0
  79. data/lib/shopify-cli/admin_api.rb +42 -2
  80. data/lib/shopify-cli/api.rb +27 -24
  81. data/lib/shopify-cli/commands/system.rb +1 -1
  82. data/lib/shopify-cli/context.rb +23 -2
  83. data/lib/shopify-cli/feature.rb +0 -2
  84. data/lib/shopify-cli/http_request.rb +20 -8
  85. data/lib/shopify-cli/messages/messages.rb +6 -3
  86. data/lib/shopify-cli/method_object.rb +104 -0
  87. data/lib/shopify-cli/partners_api.rb +8 -2
  88. data/lib/shopify-cli/project_type.rb +1 -1
  89. data/lib/shopify-cli/resolve_constant.rb +25 -0
  90. data/lib/shopify-cli/result.rb +432 -0
  91. data/lib/shopify-cli/shopifolk.rb +3 -2
  92. data/lib/shopify-cli/tasks/select_org_and_shop.rb +6 -5
  93. data/lib/shopify-cli/tunnel.rb +7 -1
  94. data/lib/shopify-cli/version.rb +1 -1
  95. data/lib/shopify_cli.rb +4 -1
  96. data/shopify.fish +1 -1
  97. data/shopify.sh +1 -1
  98. data/vendor/deps/cli-kit/REVISION +1 -1
  99. data/vendor/deps/cli-kit/lib/cli/kit/logger.rb +2 -2
  100. data/vendor/deps/cli-kit/lib/cli/kit/system.rb +3 -3
  101. data/vendor/deps/cli-ui/REVISION +1 -1
  102. data/vendor/deps/cli-ui/lib/cli/ui.rb +26 -22
  103. data/vendor/deps/cli-ui/lib/cli/ui/ansi.rb +4 -6
  104. data/vendor/deps/cli-ui/lib/cli/ui/frame.rb +3 -3
  105. data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_stack.rb +8 -9
  106. data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style.rb +1 -1
  107. data/vendor/deps/cli-ui/lib/cli/ui/glyph.rb +1 -0
  108. data/vendor/deps/cli-ui/lib/cli/ui/printer.rb +15 -3
  109. data/vendor/deps/cli-ui/lib/cli/ui/prompt/interactive_options.rb +4 -11
  110. data/vendor/deps/cli-ui/lib/cli/ui/spinner.rb +3 -5
  111. data/vendor/deps/cli-ui/lib/cli/ui/terminal.rb +10 -10
  112. data/vendor/deps/cli-ui/lib/cli/ui/version.rb +1 -1
  113. data/vendor/deps/cli-ui/lib/cli/ui/wrap.rb +56 -0
  114. data/vendor/deps/webrick/.gitignore +9 -0
  115. data/vendor/deps/webrick/Gemfile +3 -0
  116. data/vendor/deps/webrick/LICENSE.txt +22 -0
  117. data/vendor/deps/webrick/README.md +61 -0
  118. data/vendor/deps/webrick/Rakefile +10 -0
  119. data/vendor/deps/webrick/lib/webrick.rb +232 -0
  120. data/vendor/deps/webrick/lib/webrick/accesslog.rb +157 -0
  121. data/vendor/deps/webrick/lib/webrick/cgi.rb +313 -0
  122. data/vendor/deps/webrick/lib/webrick/compat.rb +36 -0
  123. data/vendor/deps/webrick/lib/webrick/config.rb +158 -0
  124. data/vendor/deps/webrick/lib/webrick/cookie.rb +172 -0
  125. data/vendor/deps/webrick/lib/webrick/htmlutils.rb +30 -0
  126. data/vendor/deps/webrick/lib/webrick/httpauth.rb +96 -0
  127. data/vendor/deps/webrick/lib/webrick/httpauth/authenticator.rb +117 -0
  128. data/vendor/deps/webrick/lib/webrick/httpauth/basicauth.rb +116 -0
  129. data/vendor/deps/webrick/lib/webrick/httpauth/digestauth.rb +395 -0
  130. data/vendor/deps/webrick/lib/webrick/httpauth/htdigest.rb +132 -0
  131. data/vendor/deps/webrick/lib/webrick/httpauth/htgroup.rb +97 -0
  132. data/vendor/deps/webrick/lib/webrick/httpauth/htpasswd.rb +158 -0
  133. data/vendor/deps/webrick/lib/webrick/httpauth/userdb.rb +53 -0
  134. data/vendor/deps/webrick/lib/webrick/httpproxy.rb +354 -0
  135. data/vendor/deps/webrick/lib/webrick/httprequest.rb +636 -0
  136. data/vendor/deps/webrick/lib/webrick/httpresponse.rb +564 -0
  137. data/vendor/deps/webrick/lib/webrick/https.rb +152 -0
  138. data/vendor/deps/webrick/lib/webrick/httpserver.rb +294 -0
  139. data/vendor/deps/webrick/lib/webrick/httpservlet.rb +23 -0
  140. data/vendor/deps/webrick/lib/webrick/httpservlet/abstract.rb +152 -0
  141. data/vendor/deps/webrick/lib/webrick/httpservlet/cgi_runner.rb +47 -0
  142. data/vendor/deps/webrick/lib/webrick/httpservlet/cgihandler.rb +126 -0
  143. data/vendor/deps/webrick/lib/webrick/httpservlet/erbhandler.rb +88 -0
  144. data/vendor/deps/webrick/lib/webrick/httpservlet/filehandler.rb +552 -0
  145. data/vendor/deps/webrick/lib/webrick/httpservlet/prochandler.rb +47 -0
  146. data/vendor/deps/webrick/lib/webrick/httpstatus.rb +194 -0
  147. data/vendor/deps/webrick/lib/webrick/httputils.rb +512 -0
  148. data/vendor/deps/webrick/lib/webrick/httpversion.rb +76 -0
  149. data/vendor/deps/webrick/lib/webrick/log.rb +156 -0
  150. data/vendor/deps/webrick/lib/webrick/server.rb +381 -0
  151. data/vendor/deps/webrick/lib/webrick/ssl.rb +215 -0
  152. data/vendor/deps/webrick/lib/webrick/utils.rb +265 -0
  153. data/vendor/deps/webrick/lib/webrick/version.rb +18 -0
  154. data/vendor/deps/webrick/webrick.gemspec +74 -0
  155. metadata +70 -26
  156. data/docs/Gemfile +0 -5
  157. data/docs/Gemfile.lock +0 -258
  158. data/docs/_data/nav.yml +0 -35
  159. data/docs/_includes/footer.html +0 -15
  160. data/docs/_includes/head.html +0 -19
  161. data/docs/_includes/sidebar_nav.html +0 -22
  162. data/docs/_includes/toc.html +0 -112
  163. data/docs/_layouts/default.html +0 -79
  164. data/docs/css/docs.css +0 -157
  165. data/docs/images/header.png +0 -0
  166. data/docs/installing-ruby.md +0 -28
  167. data/lib/project_types/extension/features/argo/admin.rb +0 -20
  168. data/lib/project_types/extension/features/argo/base.rb +0 -129
  169. data/lib/project_types/extension/features/argo/checkout.rb +0 -20
  170. data/lib/project_types/extension/models/type.rb +0 -81
  171. data/lib/project_types/extension/models/types/checkout_post_purchase.rb +0 -23
  172. data/lib/project_types/extension/models/types/product_subscription.rb +0 -24
  173. data/lib/project_types/node/commands/generate/billing.rb +0 -39
  174. data/lib/project_types/node/commands/generate/page.rb +0 -59
  175. data/lib/project_types/node/commands/generate/webhook.rb +0 -37
  176. data/lib/project_types/script/layers/domain/script.rb +0 -18
  177. data/lib/project_types/script/layers/infrastructure/script_repository.rb +0 -47
  178. data/lib/project_types/script/templates/ts/as-pect.config.js +0 -27
  179. 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