dragonruby-rack
Serve a DragonRuby GTK HTML5 export from a Rack or Rails app, on your own domain, without an iframe and without itch.io.
# Gemfile
gem "dragonruby-rack"
# config/routes.rb
mount DragonRuby::Rack::Game.new(Rails.root.join("games/underwater")) => "/underwater"
That is the whole thing. The game is then at /underwater/.
Built for and running on stammer.dev/underwater.
Why this is not just a static directory
DragonRuby's WASM runtime allocates a SharedArrayBuffer, and browsers hand
that out only to a cross-origin isolated document — one served with both
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Rails' static file server runs before the router and cannot set headers per
path, so a bundle dropped into public/ is served without them and the game
never boots. Hence: keep the bundle outside public/, serve it through this
endpoint, which sets the headers on the document and on every subresource —
require-corp applies to the .wasm too.
The second thing it does is less obvious. The export links its assets
relatively (game.css, gamedata/…), which under a mount only resolve if the
document URL ends in a slash — and nothing can guarantee that, since Rails
normalizes the path away before the endpoint sees it and a redirect onto the
slash would be a loop. So the endpoint injects a <base href="/underwater/">
into the served HTML, and the assets resolve either way.
Without Rails
It is a plain Rack app; Rails is not a dependency.
# config.ru
require "dragonruby-rack"
run DragonRuby::Rack::Game.new("builds/underwater-html5")
or mounted:
require "dragonruby-rack"
app = Rack::Builder.new do
map("/underwater") { run DragonRuby::Rack::Game.new("builds/underwater-html5") }
end
Getting a bundle in
Export the game (dragonruby-publish --platforms=html5 --package …) and unpack
the zip where the mount points:
rake dragonruby:install[../underwater/builds/underwater-html5.zip,underwater]
The task replaces the directory rather than unpacking over it — a file that
existed in the old version and not in the new one would otherwise stay behind
and be served for good. Because that is a delete, it refuses any destination
that is not empty and holds no index.html, and it checks afterwards that what
came out has an index.html and a .wasm in it (a desktop export unzips
perfectly well and then serves nothing). FORCE=1 overrides the refusal.
config.dragonruby.games_root sets where bundles live; the default is games.
Generator
rails g dragonruby:mount underwater
Creates games/underwater/ and writes the mount into config/routes.rb.
--path= and --at= override the directory and the URL. Running it twice does
not mount the path twice.
What this gem is not
It does not contain DragonRuby, and it does not build your game. DragonRuby is commercial software with its own licence; you need your own copy to produce the export this serves. This gem only takes the finished directory and puts it on the web correctly.
Development
bundle install
bundle exec rspec
Licence
MIT. See LICENSE.txt.