utopia 2.15.1 → 2.16.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/bake/utopia/{yarn.rb → node.rb} +7 -7
- data/lib/utopia/command.rb +2 -2
- data/lib/utopia/content/markup.rb +1 -1
- data/lib/utopia/content/node.rb +2 -2
- data/lib/utopia/content/response.rb +3 -3
- data/lib/utopia/controller.rb +0 -17
- data/lib/utopia/controller/base.rb +23 -3
- data/lib/utopia/controller/respond.rb +50 -107
- data/lib/utopia/extensions/array_split.rb +2 -2
- data/lib/utopia/http.rb +3 -3
- data/lib/utopia/middleware.rb +2 -2
- data/lib/utopia/path.rb +4 -4
- data/lib/utopia/redirection.rb +0 -2
- data/lib/utopia/responder.rb +76 -0
- data/lib/utopia/version.rb +1 -1
- metadata +71 -395
- data/.codeclimate.yml +0 -5
- data/.github/workflows/development.yml +0 -62
- data/.gitignore +0 -8
- data/.rspec +0 -4
- data/.yardopts +0 -2
- data/Gemfile +0 -28
- data/README.md +0 -90
- data/benchmark/call_vs_check.rb +0 -38
- data/benchmark/const_vs_hash.rb +0 -35
- data/benchmark/hash_vs_openstruct.rb +0 -54
- data/benchmark/string_vs_symbol.rb +0 -14
- data/benchmark/struct_vs_class.rb +0 -91
- data/docs/.nojekyll +0 -0
- data/docs/_components/jquery-litebox/jquery.litebox.css +0 -23
- data/docs/_components/jquery-litebox/jquery.litebox.gallery.css +0 -48
- data/docs/_components/jquery-litebox/jquery.litebox.js +0 -30
- data/docs/_components/jquery-syntax/base/jquery.syntax.brush.apache.css +0 -12
- data/docs/_components/jquery-syntax/base/jquery.syntax.brush.applescript.css +0 -5
- data/docs/_components/jquery-syntax/base/jquery.syntax.brush.assembly.css +0 -8
- data/docs/_components/jquery-syntax/base/jquery.syntax.brush.bash-script.css +0 -6
- data/docs/_components/jquery-syntax/base/jquery.syntax.brush.bash.css +0 -4
- data/docs/_components/jquery-syntax/base/jquery.syntax.brush.clang.css +0 -6
- data/docs/_components/jquery-syntax/base/jquery.syntax.brush.css.css +0 -14
- data/docs/_components/jquery-syntax/base/jquery.syntax.brush.diff.css +0 -16
- data/docs/_components/jquery-syntax/base/jquery.syntax.brush.html.css +0 -5
- data/docs/_components/jquery-syntax/base/jquery.syntax.brush.ocaml.css +0 -3
- data/docs/_components/jquery-syntax/base/jquery.syntax.brush.protobuf.css +0 -2
- data/docs/_components/jquery-syntax/base/jquery.syntax.brush.python.css +0 -6
- data/docs/_components/jquery-syntax/base/jquery.syntax.brush.ruby.css +0 -2
- data/docs/_components/jquery-syntax/base/jquery.syntax.brush.xml.css +0 -18
- data/docs/_components/jquery-syntax/base/jquery.syntax.core.css +0 -58
- data/docs/_components/jquery-syntax/base/jquery.syntax.editor.css +0 -6
- data/docs/_components/jquery-syntax/base/theme.js +0 -1
- data/docs/_components/jquery-syntax/bright/jquery.syntax.core.css +0 -27
- data/docs/_components/jquery-syntax/bright/theme.js +0 -1
- data/docs/_components/jquery-syntax/jquery.syntax.brush.apache.js +0 -3
- data/docs/_components/jquery-syntax/jquery.syntax.brush.applescript.js +0 -5
- data/docs/_components/jquery-syntax/jquery.syntax.brush.assembly.js +0 -3
- data/docs/_components/jquery-syntax/jquery.syntax.brush.bash-script.js +0 -4
- data/docs/_components/jquery-syntax/jquery.syntax.brush.bash.js +0 -2
- data/docs/_components/jquery-syntax/jquery.syntax.brush.basic.js +0 -5
- data/docs/_components/jquery-syntax/jquery.syntax.brush.clang.js +0 -5
- data/docs/_components/jquery-syntax/jquery.syntax.brush.csharp.js +0 -4
- data/docs/_components/jquery-syntax/jquery.syntax.brush.css.js +0 -5
- data/docs/_components/jquery-syntax/jquery.syntax.brush.diff.js +0 -2
- data/docs/_components/jquery-syntax/jquery.syntax.brush.go.js +0 -3
- data/docs/_components/jquery-syntax/jquery.syntax.brush.haskell.js +0 -3
- data/docs/_components/jquery-syntax/jquery.syntax.brush.html.js +0 -4
- data/docs/_components/jquery-syntax/jquery.syntax.brush.io.js +0 -3
- data/docs/_components/jquery-syntax/jquery.syntax.brush.java.js +0 -4
- data/docs/_components/jquery-syntax/jquery.syntax.brush.javascript.js +0 -3
- data/docs/_components/jquery-syntax/jquery.syntax.brush.kai.js +0 -2
- data/docs/_components/jquery-syntax/jquery.syntax.brush.lisp.js +0 -2
- data/docs/_components/jquery-syntax/jquery.syntax.brush.lua.js +0 -3
- data/docs/_components/jquery-syntax/jquery.syntax.brush.nginx.js +0 -2
- data/docs/_components/jquery-syntax/jquery.syntax.brush.ocaml.js +0 -4
- data/docs/_components/jquery-syntax/jquery.syntax.brush.ooc.js +0 -4
- data/docs/_components/jquery-syntax/jquery.syntax.brush.pascal.js +0 -4
- data/docs/_components/jquery-syntax/jquery.syntax.brush.perl5.js +0 -3
- data/docs/_components/jquery-syntax/jquery.syntax.brush.php-script.js +0 -4
- data/docs/_components/jquery-syntax/jquery.syntax.brush.php.js +0 -2
- data/docs/_components/jquery-syntax/jquery.syntax.brush.plain.js +0 -2
- data/docs/_components/jquery-syntax/jquery.syntax.brush.protobuf.js +0 -3
- data/docs/_components/jquery-syntax/jquery.syntax.brush.python.js +0 -5
- data/docs/_components/jquery-syntax/jquery.syntax.brush.ruby.js +0 -5
- data/docs/_components/jquery-syntax/jquery.syntax.brush.scala.js +0 -4
- data/docs/_components/jquery-syntax/jquery.syntax.brush.smalltalk.js +0 -2
- data/docs/_components/jquery-syntax/jquery.syntax.brush.sql.js +0 -4
- data/docs/_components/jquery-syntax/jquery.syntax.brush.super-collider.js +0 -3
- data/docs/_components/jquery-syntax/jquery.syntax.brush.swift.js +0 -3
- data/docs/_components/jquery-syntax/jquery.syntax.brush.trenni.js +0 -2
- data/docs/_components/jquery-syntax/jquery.syntax.brush.xml.js +0 -4
- data/docs/_components/jquery-syntax/jquery.syntax.brush.yaml.js +0 -2
- data/docs/_components/jquery-syntax/jquery.syntax.cache.js +0 -7
- data/docs/_components/jquery-syntax/jquery.syntax.core.js +0 -34
- data/docs/_components/jquery-syntax/jquery.syntax.editor.js +0 -11
- data/docs/_components/jquery-syntax/jquery.syntax.js +0 -8
- data/docs/_components/jquery-syntax/jquery.syntax.min.js +0 -13
- data/docs/_components/jquery-syntax/paper/jquery.syntax.core.css +0 -31
- data/docs/_components/jquery-syntax/paper/theme.js +0 -1
- data/docs/_components/jquery/jquery.js +0 -10872
- data/docs/_components/jquery/jquery.min.js +0 -2
- data/docs/_components/jquery/jquery.min.map +0 -1
- data/docs/_components/jquery/jquery.slim.js +0 -8777
- data/docs/_components/jquery/jquery.slim.min.js +0 -2
- data/docs/_components/jquery/jquery.slim.min.map +0 -1
- data/docs/_static/icon.png +0 -0
- data/docs/_static/site.css +0 -191
- data/docs/development-environment-setup/index.html +0 -54
- data/docs/faq/what-is-xnode/index.html +0 -73
- data/docs/index.html +0 -86
- data/docs/javascript/index.html +0 -108
- data/docs/middleware/content/index.html +0 -58
- data/docs/middleware/controller/actions/index.html +0 -111
- data/docs/middleware/controller/index.html +0 -98
- data/docs/middleware/controller/rewrite/index.html +0 -105
- data/docs/middleware/localization/index.html +0 -53
- data/docs/middleware/redirection/index.html +0 -55
- data/docs/middleware/session/index.html +0 -65
- data/docs/middleware/static/index.html +0 -51
- data/docs/server-setup/index.html +0 -87
- data/docs/testing/index.html +0 -53
- data/docs/updating-utopia/index.html +0 -102
- data/docs/your-first-page/index.html +0 -74
- data/materials/utopia.png +0 -0
- data/materials/utopia.svg +0 -1
- data/spec/mock_node.rb +0 -16
- data/spec/spec_helper.rb +0 -13
- data/spec/utopia/command_spec.rb +0 -164
- data/spec/utopia/content/document_spec.rb +0 -60
- data/spec/utopia/content/links/bar/index.xnode +0 -0
- data/spec/utopia/content/links/bar/parent/child/index.en.xnode +0 -0
- data/spec/utopia/content/links/bar/parent/child/index.ja.xnode +0 -0
- data/spec/utopia/content/links/bar/parent/links.yaml +0 -2
- data/spec/utopia/content/links/foo/index.xnode +0 -0
- data/spec/utopia/content/links/foo/links.yaml +0 -2
- data/spec/utopia/content/links/foo/test.de.xnode +0 -0
- data/spec/utopia/content/links/foo/test.en.xnode +0 -0
- data/spec/utopia/content/links/index.xnode +0 -0
- data/spec/utopia/content/links/links.yaml +0 -18
- data/spec/utopia/content/links/redirect/links.yaml +0 -2
- data/spec/utopia/content/links/welcome.xnode +0 -0
- data/spec/utopia/content/links_spec.rb +0 -218
- data/spec/utopia/content/localized/five/index.en.xnode +0 -0
- data/spec/utopia/content/localized/four/index.en.xnode +0 -0
- data/spec/utopia/content/localized/four/index.zh.xnode +0 -0
- data/spec/utopia/content/localized/four/links.yaml +0 -4
- data/spec/utopia/content/localized/links.yaml +0 -13
- data/spec/utopia/content/localized/one.xnode +0 -0
- data/spec/utopia/content/localized/three/index.xnode +0 -0
- data/spec/utopia/content/localized/two.en.xnode +0 -0
- data/spec/utopia/content/localized/two.zh.xnode +0 -0
- data/spec/utopia/content/markup_spec.rb +0 -96
- data/spec/utopia/content/namespace_spec.rb +0 -45
- data/spec/utopia/content/node/lookup/content.xnode +0 -1
- data/spec/utopia/content/node/lookup/index.xnode +0 -1
- data/spec/utopia/content/node/ordered/first.xnode +0 -0
- data/spec/utopia/content/node/ordered/index.xnode +0 -0
- data/spec/utopia/content/node/ordered/links.yaml +0 -4
- data/spec/utopia/content/node/ordered/second.xnode +0 -0
- data/spec/utopia/content/node/related/foo.en.xnode +0 -0
- data/spec/utopia/content/node/related/foo.ja.xnode +0 -0
- data/spec/utopia/content/node/related/links.yaml +0 -4
- data/spec/utopia/content/node_spec.rb +0 -97
- data/spec/utopia/content/response_spec.rb +0 -54
- data/spec/utopia/content/tags_spec.rb +0 -82
- data/spec/utopia/content_spec.rb +0 -100
- data/spec/utopia/content_spec.ru +0 -6
- data/spec/utopia/content_spec/_heading.xnode +0 -1
- data/spec/utopia/content_spec/content/_show-value.xnode +0 -1
- data/spec/utopia/content_spec/content/links.yaml +0 -2
- data/spec/utopia/content_spec/content/test-partial.xnode +0 -1
- data/spec/utopia/content_spec/index.xnode +0 -1
- data/spec/utopia/content_spec/node/index.xnode +0 -1
- data/spec/utopia/content_spec/test.xnode +0 -10
- data/spec/utopia/controller/actions_spec.rb +0 -62
- data/spec/utopia/controller/middleware_spec.rb +0 -88
- data/spec/utopia/controller/middleware_spec.ru +0 -6
- data/spec/utopia/controller/middleware_spec/controller/controller.rb +0 -27
- data/spec/utopia/controller/middleware_spec/controller/index.xnode +0 -1
- data/spec/utopia/controller/middleware_spec/controller/nested/controller.rb +0 -7
- data/spec/utopia/controller/middleware_spec/empty/controller.rb +0 -0
- data/spec/utopia/controller/middleware_spec/redirect/controller.rb +0 -12
- data/spec/utopia/controller/middleware_spec/redirect/test/controller.rb +0 -9
- data/spec/utopia/controller/respond_spec.rb +0 -174
- data/spec/utopia/controller/respond_spec.ru +0 -12
- data/spec/utopia/controller/respond_spec/api/controller.rb +0 -28
- data/spec/utopia/controller/respond_spec/errors/controller.rb +0 -14
- data/spec/utopia/controller/respond_spec/errors/file-not-found.xnode +0 -8
- data/spec/utopia/controller/respond_spec/html/controller.rb +0 -11
- data/spec/utopia/controller/respond_spec/rewrite/controller.rb +0 -13
- data/spec/utopia/controller/rewrite_spec.rb +0 -80
- data/spec/utopia/controller/sequence_spec.rb +0 -135
- data/spec/utopia/controller/variables_spec.rb +0 -59
- data/spec/utopia/controller/websocket_spec.rb +0 -68
- data/spec/utopia/controller/websocket_spec.ru +0 -5
- data/spec/utopia/controller/websocket_spec/server/controller.rb +0 -11
- data/spec/utopia/exceptions/handler_spec.rb +0 -47
- data/spec/utopia/exceptions/handler_spec.ru +0 -8
- data/spec/utopia/exceptions/handler_spec/controller.rb +0 -19
- data/spec/utopia/exceptions/mailer_spec.rb +0 -43
- data/spec/utopia/exceptions/mailer_spec.ru +0 -10
- data/spec/utopia/extensions_spec.rb +0 -73
- data/spec/utopia/http/status_spec.rb +0 -44
- data/spec/utopia/locale_spec.rb +0 -58
- data/spec/utopia/localization_spec.rb +0 -92
- data/spec/utopia/localization_spec.ru +0 -15
- data/spec/utopia/localization_spec/controller.rb +0 -21
- data/spec/utopia/localization_spec/localized.de.txt +0 -1
- data/spec/utopia/localization_spec/localized.en.txt +0 -1
- data/spec/utopia/localization_spec/localized.ja.txt +0 -1
- data/spec/utopia/localization_spec/test.txt +0 -1
- data/spec/utopia/middleware_spec.rb +0 -31
- data/spec/utopia/path/matcher_spec.rb +0 -66
- data/spec/utopia/path_spec.rb +0 -207
- data/spec/utopia/performance_spec.rb +0 -92
- data/spec/utopia/performance_spec/cache/head/readme.txt +0 -1
- data/spec/utopia/performance_spec/cache/meta/readme.txt +0 -1
- data/spec/utopia/performance_spec/config.ru +0 -35
- data/spec/utopia/performance_spec/lib/readme.txt +0 -1
- data/spec/utopia/performance_spec/pages/_heading.xnode +0 -2
- data/spec/utopia/performance_spec/pages/_page.xnode +0 -26
- data/spec/utopia/performance_spec/pages/api/controller.rb +0 -8
- data/spec/utopia/performance_spec/pages/errors/exception.xnode +0 -5
- data/spec/utopia/performance_spec/pages/errors/file-not-found.xnode +0 -5
- data/spec/utopia/performance_spec/pages/links.yaml +0 -2
- data/spec/utopia/performance_spec/pages/welcome/index.xnode +0 -17
- data/spec/utopia/rack_helper.rb +0 -32
- data/spec/utopia/redirection_spec.rb +0 -77
- data/spec/utopia/redirection_spec.ru +0 -27
- data/spec/utopia/session_spec.rb +0 -189
- data/spec/utopia/session_spec.ru +0 -24
- data/spec/utopia/setup_spec.rb +0 -56
- data/spec/utopia/static_spec.rb +0 -49
- data/spec/utopia/static_spec.ru +0 -5
- data/spec/utopia/static_spec/test.txt +0 -1
- data/utopia.gemspec +0 -52
- data/wiki/Gemfile +0 -9
- data/wiki/config.ru +0 -7
- data/wiki/pages/development-environment-setup/index.md +0 -16
- data/wiki/pages/faq/links.yaml +0 -2
- data/wiki/pages/faq/what-is-xnode/index.md +0 -37
- data/wiki/pages/faq/what-is-xnode/links.yaml +0 -2
- data/wiki/pages/index.md +0 -35
- data/wiki/pages/javascript/index.md +0 -75
- data/wiki/pages/javascript/links.yaml +0 -2
- data/wiki/pages/links.yaml +0 -2
- data/wiki/pages/middleware/content/index.md +0 -21
- data/wiki/pages/middleware/controller/actions/index.md +0 -76
- data/wiki/pages/middleware/controller/index.md +0 -62
- data/wiki/pages/middleware/controller/links.yaml +0 -4
- data/wiki/pages/middleware/controller/rewrite/index.md +0 -69
- data/wiki/pages/middleware/localization/index.md +0 -16
- data/wiki/pages/middleware/redirection/index.md +0 -17
- data/wiki/pages/middleware/session/index.md +0 -29
- data/wiki/pages/middleware/static/index.md +0 -13
- data/wiki/pages/server-setup/index.md +0 -52
- data/wiki/pages/testing/index.md +0 -15
- data/wiki/pages/updating-utopia/index.md +0 -63
- data/wiki/pages/your-first-page/index.md +0 -38
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ddb5cc8a1bb593d344e0d2f2c8bf315704f297ae1e8063b4d7c0e5f3d71f4014
|
|
4
|
+
data.tar.gz: '09ff4febe6dd06945a3725e0c1354402e23bf837026c5aa09b6c2106b482e00d'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6a5a89b6bf438d72007dd8617085125aae4a038ee8267716361810e149f9488166323c299aea04baf69ebd54e630e20093c32ec8e016553b11ad46bfa54fe22c
|
|
7
|
+
data.tar.gz: bf6fcfe77a7423b39fabd019b40309c52db7a15284661243119d32c279d32d51d2467e4bff409cf6d53924baca9cc60d7788b00bbaf4f9986b65e2b0522e5dbd
|
|
@@ -6,18 +6,18 @@ def update
|
|
|
6
6
|
require 'utopia/path'
|
|
7
7
|
|
|
8
8
|
root = Pathname.new(context.root)
|
|
9
|
-
|
|
9
|
+
package_root = root + "node_modules"
|
|
10
10
|
|
|
11
11
|
# This is a legacy path:
|
|
12
|
-
unless
|
|
13
|
-
|
|
12
|
+
unless package_root.directory?
|
|
13
|
+
package_root = root + "lib/components"
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
install_root = root + "public/_components"
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
install_path =
|
|
20
|
-
package_path =
|
|
18
|
+
package_root.children.select(&:directory?).collect(&:basename).each do |package_directory|
|
|
19
|
+
install_path = install_root + package_directory
|
|
20
|
+
package_path = package_root + package_directory
|
|
21
21
|
|
|
22
22
|
dist_path = package_path + 'dist'
|
|
23
23
|
|
data/lib/utopia/command.rb
CHANGED
data/lib/utopia/content/node.rb
CHANGED
|
@@ -128,12 +128,12 @@ module Utopia
|
|
|
128
128
|
|
|
129
129
|
# This is a special context in which a limited set of well defined methods are exposed in the content view.
|
|
130
130
|
Context = Struct.new(:document, :state) do
|
|
131
|
-
def partial(*
|
|
131
|
+
def partial(*arguments, &block)
|
|
132
132
|
if block_given?
|
|
133
133
|
state.defer(&block)
|
|
134
134
|
else
|
|
135
135
|
state.defer do |document|
|
|
136
|
-
document.tag(*
|
|
136
|
+
document.tag(*arguments)
|
|
137
137
|
end
|
|
138
138
|
end
|
|
139
139
|
end
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
module Utopia
|
|
24
24
|
class Content
|
|
25
25
|
# Compatibility with older versions of rack:
|
|
26
|
-
EXPIRES = '
|
|
27
|
-
CACHE_CONTROL = '
|
|
28
|
-
CONTENT_TYPE = '
|
|
26
|
+
EXPIRES = 'expires'.freeze
|
|
27
|
+
CACHE_CONTROL = 'cache-control'.freeze
|
|
28
|
+
CONTENT_TYPE = 'content-type'.freeze
|
|
29
29
|
NO_CACHE = 'no-cache'.freeze
|
|
30
30
|
|
|
31
31
|
# A basic content response, including useful defaults for typical HTML5 content.
|
data/lib/utopia/controller.rb
CHANGED
|
@@ -33,20 +33,6 @@ require_relative 'controller/actions'
|
|
|
33
33
|
require 'concurrent/map'
|
|
34
34
|
|
|
35
35
|
module Utopia
|
|
36
|
-
# A container for controller classes which are loaded from disk.
|
|
37
|
-
module Controllers
|
|
38
|
-
def self.class_name_for_controller(controller)
|
|
39
|
-
controller.uri_path.to_a.collect{|_| _.capitalize}.join + "_#{controller.object_id}"
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def self.define(klass)
|
|
43
|
-
self.const_set(
|
|
44
|
-
class_name_for_controller(klass),
|
|
45
|
-
klass,
|
|
46
|
-
)
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
36
|
# A middleware which loads controller classes and invokes functionality based on the requested path.
|
|
51
37
|
class Controller
|
|
52
38
|
# The controller filename.
|
|
@@ -105,9 +91,6 @@ module Utopia
|
|
|
105
91
|
|
|
106
92
|
klass.class_eval(File.read(controller_path), controller_path)
|
|
107
93
|
|
|
108
|
-
# Give the controller a useful name:
|
|
109
|
-
# Controllers.define(klass)
|
|
110
|
-
|
|
111
94
|
# We lock down the controller class to prevent unsafe modifications:
|
|
112
95
|
klass.freeze
|
|
113
96
|
|
|
@@ -24,6 +24,8 @@ require_relative '../http'
|
|
|
24
24
|
|
|
25
25
|
module Utopia
|
|
26
26
|
class Controller
|
|
27
|
+
CONTENT_TYPE = HTTP::CONTENT_TYPE
|
|
28
|
+
|
|
27
29
|
# The base implementation of a controller class.
|
|
28
30
|
class Base
|
|
29
31
|
# A string which is the full path to the directory which contains the controller.
|
|
@@ -41,6 +43,24 @@ module Utopia
|
|
|
41
43
|
self.const_get(:CONTROLLER)
|
|
42
44
|
end
|
|
43
45
|
|
|
46
|
+
def self.inspect
|
|
47
|
+
"Controller#{self.uri_path}"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def self.to_s
|
|
51
|
+
self.inspect
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def to_s
|
|
55
|
+
"\#<#{self.class}>"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def inspect
|
|
59
|
+
details = self.instance_variables.map{|name| " #{name}=#{self.instance_variable_get(name)}"}
|
|
60
|
+
|
|
61
|
+
"\#<#{self.class}#{details.join}>"
|
|
62
|
+
end
|
|
63
|
+
|
|
44
64
|
class << self
|
|
45
65
|
def freeze
|
|
46
66
|
# This ensures that all class variables are frozen.
|
|
@@ -116,11 +136,11 @@ module Utopia
|
|
|
116
136
|
end
|
|
117
137
|
|
|
118
138
|
# Succeed the request and immediately respond.
|
|
119
|
-
def succeed!(status: 200, headers: {}, **options)
|
|
139
|
+
def succeed!(status: 200, headers: {}, type: nil, **options)
|
|
120
140
|
status = HTTP::Status.new(status, 200...300)
|
|
121
141
|
|
|
122
|
-
if
|
|
123
|
-
headers[
|
|
142
|
+
if type
|
|
143
|
+
headers[CONTENT_TYPE] = type.to_s
|
|
124
144
|
end
|
|
125
145
|
|
|
126
146
|
body = body_for(status, headers, options)
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
# THE SOFTWARE.
|
|
22
22
|
|
|
23
23
|
require_relative '../http'
|
|
24
|
-
require_relative '../
|
|
24
|
+
require_relative '../responder'
|
|
25
25
|
|
|
26
26
|
module Utopia
|
|
27
27
|
class Controller
|
|
@@ -31,139 +31,82 @@ module Utopia
|
|
|
31
31
|
base.extend(ClassMethods)
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
-
module
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
module Handlers
|
|
35
|
+
module JSON
|
|
36
|
+
APPLICATION_JSON = HTTP::Accept::ContentType.new('application', 'json').freeze
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
# Update the headers with the requested content type:
|
|
42
|
-
headers = headers.merge(updated_headers)
|
|
43
|
-
|
|
44
|
-
return [status, headers, body]
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
Callback = Struct.new(:content_type, :block) do
|
|
48
|
-
def headers
|
|
49
|
-
{HTTP::CONTENT_TYPE => self.content_type}
|
|
38
|
+
def self.split(*arguments)
|
|
39
|
+
APPLICATION_JSON.split(*arguments)
|
|
50
40
|
end
|
|
51
41
|
|
|
52
|
-
def
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def call(context, response, media_range)
|
|
57
|
-
Converter.update_response(response, headers) do |content|
|
|
58
|
-
context.instance_exec(content, media_range, &block)
|
|
42
|
+
def self.call(context, request, media_range, object, **options)
|
|
43
|
+
if version = media_range.parameters['version']
|
|
44
|
+
options[:version] = version.to_s
|
|
59
45
|
end
|
|
46
|
+
|
|
47
|
+
context.succeed! content: object.to_json(options), type: APPLICATION_JSON
|
|
60
48
|
end
|
|
61
49
|
end
|
|
62
50
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
# To accept incoming requests with content-type JSON (e.g. POST with JSON data), consider using `Rack::PostBodyContentTypeParser`.
|
|
68
|
-
module ToJSON
|
|
69
|
-
APPLICATION_JSON = HTTP::Accept::ContentType.new('application', 'json', charset: 'utf-8').freeze
|
|
70
|
-
HEADERS = {HTTP::CONTENT_TYPE => APPLICATION_JSON.to_s}.freeze
|
|
51
|
+
module Passthrough
|
|
52
|
+
WILDCARD = HTTP::Accept::MediaTypes::MediaRange.new('*', '*').freeze
|
|
71
53
|
|
|
72
|
-
def self.
|
|
73
|
-
|
|
54
|
+
def self.split(*arguments)
|
|
55
|
+
WILDCARD.split(*arguments)
|
|
74
56
|
end
|
|
75
57
|
|
|
76
|
-
def self.
|
|
77
|
-
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def self.serialize(content, media_range)
|
|
81
|
-
options = {}
|
|
82
|
-
|
|
83
|
-
if version = media_range.parameters['version']
|
|
84
|
-
options[:version] = version.to_s
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
return content.to_json(options)
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def self.call(context, response, media_range)
|
|
91
|
-
Converter.update_response(response, HEADERS) do |content|
|
|
92
|
-
self.serialize(content, media_range)
|
|
93
|
-
end
|
|
58
|
+
def self.call(context, request, media_range, object, **options)
|
|
59
|
+
# Do nothing.
|
|
94
60
|
end
|
|
95
61
|
end
|
|
96
62
|
end
|
|
97
63
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
def self.split(*args)
|
|
102
|
-
self.media_range.split(*args)
|
|
64
|
+
class Responder < Utopia::Responder
|
|
65
|
+
def with_json
|
|
66
|
+
@handlers << Handlers::JSON
|
|
103
67
|
end
|
|
104
68
|
|
|
105
|
-
def
|
|
106
|
-
|
|
69
|
+
def with_passthrough
|
|
70
|
+
@handlers << Handlers::Passthrough
|
|
107
71
|
end
|
|
108
72
|
|
|
109
|
-
def
|
|
110
|
-
|
|
73
|
+
def with(content_type, &block)
|
|
74
|
+
handle(content_type, &block)
|
|
111
75
|
end
|
|
112
76
|
end
|
|
113
77
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
def initialize
|
|
119
|
-
@converters = HTTP::Accept::MediaTypes::Map.new
|
|
78
|
+
module ClassMethods
|
|
79
|
+
def responds
|
|
80
|
+
@responder ||= Responder.new
|
|
120
81
|
end
|
|
121
82
|
|
|
122
|
-
|
|
123
|
-
@converters.freeze
|
|
124
|
-
|
|
125
|
-
super
|
|
126
|
-
end
|
|
83
|
+
alias respond responds
|
|
127
84
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
@converters << Converter::Callback.new(content_type, block)
|
|
85
|
+
def respond_to(context, request)
|
|
86
|
+
@responder&.respond_to(context, request)
|
|
131
87
|
end
|
|
132
88
|
|
|
133
|
-
def
|
|
134
|
-
@
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
# Add a converter for JSON when requests accept 'application/json'
|
|
138
|
-
def with_json
|
|
139
|
-
@converters << Converter::ToJSON
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
def call(context, request, path, response)
|
|
143
|
-
# Parse the list of browser preferred content types and return ordered by priority:
|
|
144
|
-
media_types = HTTP::Accept::MediaTypes.browser_preferred_media_types(request.env)
|
|
145
|
-
|
|
146
|
-
converter, media_range = @converters.for(media_types)
|
|
147
|
-
|
|
148
|
-
if converter
|
|
149
|
-
converter.call(context, response, media_range)
|
|
150
|
-
else
|
|
151
|
-
NOT_ACCEPTABLE_RESPONSE
|
|
152
|
-
end
|
|
89
|
+
def response_for(context, request, response)
|
|
90
|
+
@responder&.respond_to(context, request).with(*response[2])
|
|
153
91
|
end
|
|
154
92
|
end
|
|
155
93
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
94
|
+
def respond_to(request)
|
|
95
|
+
self.class.respond_to(self, request)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def response_for(request, original_response)
|
|
99
|
+
response = catch(:response) do
|
|
100
|
+
self.class.response_for(self, request, original_response)
|
|
101
|
+
|
|
102
|
+
# If the above code did not throw a new response, we return the original:
|
|
103
|
+
return original_response
|
|
159
104
|
end
|
|
160
105
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
response
|
|
166
|
-
end
|
|
106
|
+
# If the user called {Base#ignore!}, it's possible response is nil:
|
|
107
|
+
if response
|
|
108
|
+
# There was an updated response so merge it:
|
|
109
|
+
return [original_response[0], original_response[1].merge(response[1]), response[2] || original_response[2]]
|
|
167
110
|
end
|
|
168
111
|
end
|
|
169
112
|
|
|
@@ -173,11 +116,11 @@ module Utopia
|
|
|
173
116
|
headers = response[1]
|
|
174
117
|
|
|
175
118
|
# Don't try to convert the response if a content type was explicitly specified.
|
|
176
|
-
|
|
177
|
-
|
|
119
|
+
if headers[HTTP::CONTENT_TYPE]
|
|
120
|
+
return response
|
|
121
|
+
else
|
|
122
|
+
return self.response_for(request, response)
|
|
178
123
|
end
|
|
179
|
-
|
|
180
|
-
response
|
|
181
124
|
end
|
|
182
125
|
end
|
|
183
126
|
end
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
module Utopia
|
|
24
24
|
module Extensions
|
|
25
25
|
module ArraySplit
|
|
26
|
-
def split_at(*
|
|
27
|
-
if middle = index(*
|
|
26
|
+
def split_at(*arguments, &block)
|
|
27
|
+
if middle = index(*arguments, &block)
|
|
28
28
|
[self[0...middle], self[middle], self[middle+1..-1]]
|
|
29
29
|
else
|
|
30
30
|
[[], nil, []]
|
data/lib/utopia/http.rb
CHANGED
|
@@ -90,9 +90,9 @@ module Utopia
|
|
|
90
90
|
503 => 'Service Unavailable'.freeze
|
|
91
91
|
}.merge(Rack::Utils::HTTP_STATUS_CODES)
|
|
92
92
|
|
|
93
|
-
CONTENT_TYPE = '
|
|
94
|
-
LOCATION = '
|
|
95
|
-
CACHE_CONTROL = '
|
|
93
|
+
CONTENT_TYPE = 'content-type'.freeze
|
|
94
|
+
LOCATION = 'location'.freeze
|
|
95
|
+
CACHE_CONTROL = 'cache-control'.freeze
|
|
96
96
|
|
|
97
97
|
# A small HTTP status wrapper that verifies the status code within a given range.
|
|
98
98
|
class Status
|
data/lib/utopia/middleware.rb
CHANGED
|
@@ -39,7 +39,7 @@ module Utopia
|
|
|
39
39
|
|
|
40
40
|
# The same as {default_root} but returns an instance of {Path}.
|
|
41
41
|
# @return [Path] The path as requested.
|
|
42
|
-
def self.default_path(*
|
|
43
|
-
Path[default_root(*
|
|
42
|
+
def self.default_path(*arguments)
|
|
43
|
+
Path[default_root(*arguments)]
|
|
44
44
|
end
|
|
45
45
|
end
|
data/lib/utopia/path.rb
CHANGED
|
@@ -126,8 +126,8 @@ module Utopia
|
|
|
126
126
|
@components = other_path.components.dup
|
|
127
127
|
end
|
|
128
128
|
|
|
129
|
-
def include?(*
|
|
130
|
-
@components.include?(*
|
|
129
|
+
def include?(*arguments)
|
|
130
|
+
@components.include?(*arguments)
|
|
131
131
|
end
|
|
132
132
|
|
|
133
133
|
def directory?
|
|
@@ -200,8 +200,8 @@ module Utopia
|
|
|
200
200
|
end
|
|
201
201
|
end
|
|
202
202
|
|
|
203
|
-
def with_prefix(*
|
|
204
|
-
self.class.create(*
|
|
203
|
+
def with_prefix(*arguments)
|
|
204
|
+
self.class.create(*arguments) + self
|
|
205
205
|
end
|
|
206
206
|
|
|
207
207
|
# Computes the difference of the path.
|
data/lib/utopia/redirection.rb
CHANGED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
# furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
|
13
|
+
# all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
# THE SOFTWARE.
|
|
22
|
+
|
|
23
|
+
require_relative 'middleware'
|
|
24
|
+
|
|
25
|
+
module Utopia
|
|
26
|
+
class Responder
|
|
27
|
+
Handler = Struct.new(:content_type, :block) do
|
|
28
|
+
def split(*arguments)
|
|
29
|
+
self.content_type.split(*arguments)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def call(context, request, media_range, *arguments, **options)
|
|
33
|
+
context.instance_exec(media_range, *arguments, **options, &self.block)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
Responds = Struct.new(:responder, :context, :request) do
|
|
38
|
+
# @todo Refactor `object` -> `*arguments`...
|
|
39
|
+
def with(object, **options)
|
|
40
|
+
responder.call(context, request, object, **options)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def initialize
|
|
45
|
+
@handlers = HTTP::Accept::MediaTypes::Map.new
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
attr :handlers
|
|
49
|
+
|
|
50
|
+
def freeze
|
|
51
|
+
@handlers.freeze
|
|
52
|
+
|
|
53
|
+
super
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def call(context, request, *arguments, **options)
|
|
57
|
+
# Parse the list of browser preferred content types and return ordered by priority:
|
|
58
|
+
media_types = HTTP::Accept::MediaTypes.browser_preferred_media_types(request.env)
|
|
59
|
+
|
|
60
|
+
handler, media_range = @handlers.for(media_types)
|
|
61
|
+
|
|
62
|
+
if handler
|
|
63
|
+
handler.call(context, request, media_range, *arguments, **options)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Add a converter for the specified content type. Call the block with the response content if the request accepts the specified content_type.
|
|
68
|
+
def handle(content_type, &block)
|
|
69
|
+
@handlers << Handler.new(content_type, block)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def respond_to(context, request)
|
|
73
|
+
Responds.new(self, context, request)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|