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.
- checksums.yaml +4 -4
- data/.github/PULL_REQUEST_TEMPLATE.md +1 -0
- data/.travis.yml +1 -0
- data/CHANGELOG.md +9 -0
- data/README.md +39 -7
- data/Rakefile +2 -0
- data/dev.yml +2 -2
- data/docs/_config.yml +1 -18
- data/docs/app/node/commands/index.md +2 -80
- data/docs/app/node/index.md +2 -33
- data/docs/app/rails/commands/index.md +2 -78
- data/docs/app/rails/index.md +2 -34
- data/docs/core/index.md +2 -84
- data/docs/getting-started/index.md +2 -25
- data/docs/getting-started/install/index.md +1 -118
- data/docs/getting-started/migrate/index.md +2 -94
- data/docs/getting-started/uninstall/index.md +2 -35
- data/docs/getting-started/upgrade/index.md +2 -39
- data/docs/help/start-app/index.md +2 -4
- data/docs/index.md +2 -24
- data/install.sh +1 -1
- data/lib/project_types/extension/cli.rb +19 -10
- data/lib/project_types/extension/commands/extension_command.rb +2 -2
- data/lib/project_types/extension/features/argo.rb +117 -0
- data/lib/project_types/extension/forms/create.rb +2 -2
- data/lib/project_types/extension/models/specification.rb +35 -0
- data/lib/project_types/extension/models/specification_handlers/checkout_post_purchase.rb +19 -0
- data/lib/project_types/extension/models/specification_handlers/default.rb +67 -0
- data/lib/project_types/extension/models/specifications.rb +77 -0
- data/lib/project_types/extension/tasks/configure_features.rb +52 -0
- data/lib/project_types/extension/tasks/fetch_specifications.rb +38 -0
- data/lib/project_types/node/commands/create.rb +3 -1
- data/lib/project_types/node/commands/generate.rb +2 -11
- data/lib/project_types/node/messages/messages.rb +9 -44
- data/lib/project_types/rails/commands/create.rb +8 -9
- data/lib/project_types/rails/forms/create.rb +1 -1
- data/lib/project_types/rails/gem.rb +1 -1
- data/lib/project_types/rails/messages/messages.rb +1 -1
- data/lib/project_types/script/cli.rb +7 -4
- data/lib/project_types/script/commands/create.rb +6 -4
- data/lib/project_types/script/commands/push.rb +5 -13
- data/lib/project_types/script/config/extension_points.yml +9 -5
- data/lib/project_types/script/errors.rb +17 -0
- data/lib/project_types/script/forms/create.rb +26 -2
- data/lib/project_types/script/graphql/app_script_update_or_create.graphql +10 -1
- data/lib/project_types/script/layers/application/build_script.rb +9 -4
- data/lib/project_types/script/layers/application/create_script.rb +12 -10
- data/lib/project_types/script/layers/application/extension_points.rb +24 -0
- data/lib/project_types/script/layers/application/push_script.rb +18 -16
- data/lib/project_types/script/layers/domain/errors.rb +4 -0
- data/lib/project_types/script/layers/domain/extension_point.rb +62 -6
- data/lib/project_types/script/layers/domain/metadata.rb +55 -0
- data/lib/project_types/script/layers/domain/push_package.rb +25 -6
- data/lib/project_types/script/layers/infrastructure/assemblyscript_project_creator.rb +6 -6
- data/lib/project_types/script/layers/infrastructure/assemblyscript_task_runner.rb +16 -6
- data/lib/project_types/script/layers/infrastructure/extension_point_repository.rb +10 -4
- data/lib/project_types/script/layers/infrastructure/project_creator.rb +2 -1
- data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +25 -13
- data/lib/project_types/script/layers/infrastructure/rust_project_creator.rb +72 -0
- data/lib/project_types/script/layers/infrastructure/rust_task_runner.rb +59 -0
- data/lib/project_types/script/layers/infrastructure/script_service.rb +7 -1
- data/lib/project_types/script/layers/infrastructure/task_runner.rb +4 -3
- data/lib/project_types/script/messages/messages.rb +39 -8
- data/lib/project_types/script/script_project.rb +25 -16
- data/lib/project_types/script/ui/error_handler.rb +34 -1
- data/lib/project_types/theme/cli.rb +40 -0
- data/lib/project_types/theme/commands/connect.rb +54 -0
- data/lib/project_types/theme/commands/create.rb +48 -0
- data/lib/project_types/theme/commands/deploy.rb +38 -0
- data/lib/project_types/theme/commands/generate.rb +20 -0
- data/lib/project_types/theme/commands/generate/env.rb +79 -0
- data/lib/project_types/theme/commands/push.rb +55 -0
- data/lib/project_types/theme/commands/serve.rb +31 -0
- data/lib/project_types/theme/forms/connect.rb +34 -0
- data/lib/project_types/theme/forms/create.rb +22 -0
- data/lib/project_types/theme/messages/messages.rb +147 -0
- data/lib/project_types/theme/tasks/ensure_themekit_installed.rb +78 -0
- data/lib/project_types/theme/themekit.rb +113 -0
- data/lib/shopify-cli/admin_api.rb +42 -2
- data/lib/shopify-cli/api.rb +27 -24
- data/lib/shopify-cli/commands/system.rb +1 -1
- data/lib/shopify-cli/context.rb +23 -2
- data/lib/shopify-cli/feature.rb +0 -2
- data/lib/shopify-cli/http_request.rb +20 -8
- data/lib/shopify-cli/messages/messages.rb +6 -3
- data/lib/shopify-cli/method_object.rb +104 -0
- data/lib/shopify-cli/partners_api.rb +8 -2
- data/lib/shopify-cli/project_type.rb +1 -1
- data/lib/shopify-cli/resolve_constant.rb +25 -0
- data/lib/shopify-cli/result.rb +432 -0
- data/lib/shopify-cli/shopifolk.rb +3 -2
- data/lib/shopify-cli/tasks/select_org_and_shop.rb +6 -5
- data/lib/shopify-cli/tunnel.rb +7 -1
- data/lib/shopify-cli/version.rb +1 -1
- data/lib/shopify_cli.rb +4 -1
- data/shopify.fish +1 -1
- data/shopify.sh +1 -1
- data/vendor/deps/cli-kit/REVISION +1 -1
- data/vendor/deps/cli-kit/lib/cli/kit/logger.rb +2 -2
- data/vendor/deps/cli-kit/lib/cli/kit/system.rb +3 -3
- data/vendor/deps/cli-ui/REVISION +1 -1
- data/vendor/deps/cli-ui/lib/cli/ui.rb +26 -22
- data/vendor/deps/cli-ui/lib/cli/ui/ansi.rb +4 -6
- data/vendor/deps/cli-ui/lib/cli/ui/frame.rb +3 -3
- data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_stack.rb +8 -9
- data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style.rb +1 -1
- data/vendor/deps/cli-ui/lib/cli/ui/glyph.rb +1 -0
- data/vendor/deps/cli-ui/lib/cli/ui/printer.rb +15 -3
- data/vendor/deps/cli-ui/lib/cli/ui/prompt/interactive_options.rb +4 -11
- data/vendor/deps/cli-ui/lib/cli/ui/spinner.rb +3 -5
- data/vendor/deps/cli-ui/lib/cli/ui/terminal.rb +10 -10
- data/vendor/deps/cli-ui/lib/cli/ui/version.rb +1 -1
- data/vendor/deps/cli-ui/lib/cli/ui/wrap.rb +56 -0
- data/vendor/deps/webrick/.gitignore +9 -0
- data/vendor/deps/webrick/Gemfile +3 -0
- data/vendor/deps/webrick/LICENSE.txt +22 -0
- data/vendor/deps/webrick/README.md +61 -0
- data/vendor/deps/webrick/Rakefile +10 -0
- data/vendor/deps/webrick/lib/webrick.rb +232 -0
- data/vendor/deps/webrick/lib/webrick/accesslog.rb +157 -0
- data/vendor/deps/webrick/lib/webrick/cgi.rb +313 -0
- data/vendor/deps/webrick/lib/webrick/compat.rb +36 -0
- data/vendor/deps/webrick/lib/webrick/config.rb +158 -0
- data/vendor/deps/webrick/lib/webrick/cookie.rb +172 -0
- data/vendor/deps/webrick/lib/webrick/htmlutils.rb +30 -0
- data/vendor/deps/webrick/lib/webrick/httpauth.rb +96 -0
- data/vendor/deps/webrick/lib/webrick/httpauth/authenticator.rb +117 -0
- data/vendor/deps/webrick/lib/webrick/httpauth/basicauth.rb +116 -0
- data/vendor/deps/webrick/lib/webrick/httpauth/digestauth.rb +395 -0
- data/vendor/deps/webrick/lib/webrick/httpauth/htdigest.rb +132 -0
- data/vendor/deps/webrick/lib/webrick/httpauth/htgroup.rb +97 -0
- data/vendor/deps/webrick/lib/webrick/httpauth/htpasswd.rb +158 -0
- data/vendor/deps/webrick/lib/webrick/httpauth/userdb.rb +53 -0
- data/vendor/deps/webrick/lib/webrick/httpproxy.rb +354 -0
- data/vendor/deps/webrick/lib/webrick/httprequest.rb +636 -0
- data/vendor/deps/webrick/lib/webrick/httpresponse.rb +564 -0
- data/vendor/deps/webrick/lib/webrick/https.rb +152 -0
- data/vendor/deps/webrick/lib/webrick/httpserver.rb +294 -0
- data/vendor/deps/webrick/lib/webrick/httpservlet.rb +23 -0
- data/vendor/deps/webrick/lib/webrick/httpservlet/abstract.rb +152 -0
- data/vendor/deps/webrick/lib/webrick/httpservlet/cgi_runner.rb +47 -0
- data/vendor/deps/webrick/lib/webrick/httpservlet/cgihandler.rb +126 -0
- data/vendor/deps/webrick/lib/webrick/httpservlet/erbhandler.rb +88 -0
- data/vendor/deps/webrick/lib/webrick/httpservlet/filehandler.rb +552 -0
- data/vendor/deps/webrick/lib/webrick/httpservlet/prochandler.rb +47 -0
- data/vendor/deps/webrick/lib/webrick/httpstatus.rb +194 -0
- data/vendor/deps/webrick/lib/webrick/httputils.rb +512 -0
- data/vendor/deps/webrick/lib/webrick/httpversion.rb +76 -0
- data/vendor/deps/webrick/lib/webrick/log.rb +156 -0
- data/vendor/deps/webrick/lib/webrick/server.rb +381 -0
- data/vendor/deps/webrick/lib/webrick/ssl.rb +215 -0
- data/vendor/deps/webrick/lib/webrick/utils.rb +265 -0
- data/vendor/deps/webrick/lib/webrick/version.rb +18 -0
- data/vendor/deps/webrick/webrick.gemspec +74 -0
- metadata +70 -26
- data/docs/Gemfile +0 -5
- data/docs/Gemfile.lock +0 -258
- data/docs/_data/nav.yml +0 -35
- data/docs/_includes/footer.html +0 -15
- data/docs/_includes/head.html +0 -19
- data/docs/_includes/sidebar_nav.html +0 -22
- data/docs/_includes/toc.html +0 -112
- data/docs/_layouts/default.html +0 -79
- data/docs/css/docs.css +0 -157
- data/docs/images/header.png +0 -0
- data/docs/installing-ruby.md +0 -28
- data/lib/project_types/extension/features/argo/admin.rb +0 -20
- data/lib/project_types/extension/features/argo/base.rb +0 -129
- data/lib/project_types/extension/features/argo/checkout.rb +0 -20
- data/lib/project_types/extension/models/type.rb +0 -81
- data/lib/project_types/extension/models/types/checkout_post_purchase.rb +0 -23
- data/lib/project_types/extension/models/types/product_subscription.rb +0 -24
- data/lib/project_types/node/commands/generate/billing.rb +0 -39
- data/lib/project_types/node/commands/generate/page.rb +0 -59
- data/lib/project_types/node/commands/generate/webhook.rb +0 -37
- data/lib/project_types/script/layers/domain/script.rb +0 -18
- data/lib/project_types/script/layers/infrastructure/script_repository.rb +0 -47
- data/lib/project_types/script/templates/ts/as-pect.config.js +0 -27
- 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
|