Class: DragonRuby::Rack::Game
- Inherits:
-
Object
- Object
- DragonRuby::Rack::Game
- Defined in:
- lib/dragonruby/rack/game.rb
Overview
Serves a DragonRuby GTK HTML5 export as a self-contained, cross-origin isolated static bundle, mountable at any path in a Rack or Rails app:
mount DragonRuby::Rack::Game.new("games/underwater") => "/underwater"
Why this exists: DragonRuby's WASM runtime uses SharedArrayBuffer, which the browser only hands out to a cross-origin isolated document — one served with both COOP and COEP. Rails' public/ file server (ActionDispatch::Static) runs before the router and cannot set these headers per path, which is why the bundle belongs outside public/ and is served exclusively through this endpoint.
Everything in here refers to the real Rack as ::Rack. Inside
DragonRuby::Rack, a bare Rack::Static resolves to
DragonRuby::Rack::Static and raises NameError — the one price of naming
the module after the gem.
Constant Summary collapse
- ISOLATION_HEADERS =
The two headers that put the document into cross-origin isolation. Without them the WASM runtime cannot allocate its SharedArrayBuffer and refuses to boot. Same-origin subresources (all of the bundle) satisfy require-corp without a per-file Cross-Origin-Resource-Policy header.
{ "cross-origin-opener-policy" => "same-origin", "cross-origin-embedder-policy" => "require-corp", }.freeze
- NOT_FOUND =
->(_env) { [404, { "content-type" => "text/plain" }, ["Not found"]] }
Instance Attribute Summary collapse
-
#root ⇒ Object
readonly
Returns the value of attribute root.
Instance Method Summary collapse
- #call(env) ⇒ Object
-
#initialize(root, index: "index.html") ⇒ Game
constructor
A missing directory is deliberately not an error.
Constructor Details
#initialize(root, index: "index.html") ⇒ Game
A missing directory is deliberately not an error. Routes are drawn at boot, and a fresh clone has no build in it yet; raising here would stop the whole app from starting over a game that has not been exported. Requests simply 404 until the bundle is there.
39 40 41 42 43 44 45 46 47 |
# File 'lib/dragonruby/rack/game.rb', line 39 def initialize(root, index: "index.html") @root = root.to_s @static = ::Rack::Static.new( NOT_FOUND, root: @root, urls: [""], # serve every path under this mount from the bundle index: index, # directory requests ("/") resolve to index.html ) end |
Instance Attribute Details
#root ⇒ Object (readonly)
Returns the value of attribute root.
33 34 35 |
# File 'lib/dragonruby/rack/game.rb', line 33 def root @root end |
Instance Method Details
#call(env) ⇒ Object
49 50 51 52 53 54 55 |
# File 'lib/dragonruby/rack/game.rb', line 49 def call(env) env = normalize_root(env) status, headers, body = @static.call(env) ISOLATION_HEADERS.each { |key, value| headers[key] = value } body = rebase_html(body, headers, env) if html?(headers) [status, headers, body] end |