Class: Utopia::Content::Middleware
- Inherits:
-
Protocol::HTTP::Middleware
- Object
- Protocol::HTTP::Middleware
- Utopia::Content::Middleware
- Includes:
- Localization::Resolver
- Defined in:
- lib/utopia/content/middleware.rb
Overview
A middleware which serves dynamically generated content based on markup files.
Constant Summary collapse
- CONTENT_NAMESPACE =
"content".freeze
- RELATIVE_NAMESPACE =
"relative".freeze
- UTOPIA_NAMESPACE =
"utopia".freeze
- CONTENT_TAG_NAME =
"utopia:content".freeze
Constants included from Localization::Resolver
Localization::Resolver::CONTENT_LANGUAGE, Localization::Resolver::CONTENT_LOCATION
Instance Attribute Summary collapse
-
#root ⇒ Object
readonly
Returns the value of attribute root.
Instance Method Summary collapse
-
#call(request) ⇒ Object
Serve or redirect filesystem-backed content, otherwise invoke the application.
-
#fetch_template(path) ⇒ Object
Load and cache a content template.
-
#freeze ⇒ Object
Freeze this object and its internal state.
-
#initialize(app, root: Utopia::default_root, namespaces: {}) ⇒ Middleware
constructor
A new instance of Middleware.
-
#links(path, **options) ⇒ Object
TODO we should remove this method and expose
@linksdirectly. - #lookup_node(path, locale = nil) ⇒ Object
-
#lookup_tag(qualified_name, node) ⇒ Object
Look up a named tag such as
<entry />or<content:page>.... -
#resolve_link(link) ⇒ Object
Resolve a link to an existing content node.
-
#respond(link, request, localization: request.localization) ⇒ Object
Respond.
Constructor Details
#initialize(app, root: Utopia::default_root, namespaces: {}) ⇒ Middleware
Returns a new instance of Middleware.
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/utopia/content/middleware.rb', line 34 def initialize(app, root: Utopia::default_root, namespaces: {}) super(app) @root = root @template_cache = Concurrent::Map.new @node_cache = Concurrent::Map.new @links = Links.new(@root) @namespaces = namespaces # Default content namespace for dynamic path based lookup: @namespaces[CONTENT_NAMESPACE] ||= self.method(:content_tag) # Resolve content relative to the logical invocation path: @namespaces[RELATIVE_NAMESPACE] ||= self.method(:relative_tag) # The core namespace for utopia specific functionality: @namespaces[UTOPIA_NAMESPACE] ||= Tags end |
Instance Attribute Details
#root ⇒ Object (readonly)
Returns the value of attribute root.
68 69 70 |
# File 'lib/utopia/content/middleware.rb', line 68 def root @root end |
Instance Method Details
#call(request) ⇒ Object
Serve or redirect filesystem-backed content, otherwise invoke the application.
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/utopia/content/middleware.rb', line 129 def call(request) path = request.path # Check if the request is to a non-specific index. This only works for requests with a given name: basename = path.basename directory_path = File.join(@root, path.dirname.components, basename) # If the request for /foo/bar is actually a directory, rewrite it to /foo/bar/index: if File.directory? directory_path index_path = [basename, INDEX] location = path.dirname.join(index_path).to_url_path.encoded return Utopia::Response[307, {HTTP::LOCATION => location}, []] end response = resolve_localized(request) do |localization| locale = localization&.locale if link = @links.for(path, locale, fallback: false) self.respond(link, request, localization: localization) end end if response return response end return @delegate.call(request) end |
#fetch_template(path) ⇒ Object
Load and cache a content template.
78 79 80 81 82 |
# File 'lib/utopia/content/middleware.rb', line 78 def fetch_template(path) @template_cache.fetch_or_store(path.to_s) do XRB::Template.load_file(path) end end |
#freeze ⇒ Object
Freeze this object and its internal state.
58 59 60 61 62 63 64 65 66 |
# File 'lib/utopia/content/middleware.rb', line 58 def freeze return self if frozen? @root.freeze @namespaces.values.each(&:freeze) @namespaces.freeze super end |
#links(path, **options) ⇒ Object
TODO we should remove this method and expose @links directly.
71 72 73 |
# File 'lib/utopia/content/middleware.rb', line 71 def links(path, **) @links.index(path, **) end |
#lookup_node(path, locale = nil) ⇒ Object
94 95 96 97 98 |
# File 'lib/utopia/content/middleware.rb', line 94 def lookup_node(path, locale = nil) resolve_link( @links.for(path, locale) ) end |
#lookup_tag(qualified_name, node) ⇒ Object
Look up a named tag such as <entry /> or <content:page>...
85 86 87 88 89 90 91 |
# File 'lib/utopia/content/middleware.rb', line 85 def lookup_tag(qualified_name, node) namespace, name = XRB::Tag.split(qualified_name) if library = @namespaces[namespace] library.call(name, node) end end |
#resolve_link(link) ⇒ Object
Resolve a link to an existing content node.
103 104 105 106 107 108 109 |
# File 'lib/utopia/content/middleware.rb', line 103 def resolve_link(link) if full_path = link&.full_path(@root) if File.exist?(full_path) return Node.new(self, link.path, link.path, full_path) end end end |
#respond(link, request, localization: request.localization) ⇒ Object
Respond.
116 117 118 119 120 121 122 123 124 |
# File 'lib/utopia/content/middleware.rb', line 116 def respond(link, request, localization: request.localization) if node = resolve_link(link) attributes = request.variables&.to_hash || {} return node.process!(request, attributes, localization: localization) elsif redirect_uri = link[:uri] return Utopia::Response[307, {HTTP::LOCATION => redirect_uri}, []] end end |