Class: Ruflet::Rails::Protocol::WebApp

Inherits:
Object
  • Object
show all
Includes:
WebSocketDetection
Defined in:
lib/ruflet/rails/protocol/web_app.rb

Overview

Self-contained Rack application for a Ruflet web frontend: serves the built Flutter web client AND speaks the Ruflet WebSocket protocol on the same mount point, so it mounts like any Rack app:

# config/routes.rb
mount Ruflet::Rails.web_app, at: "/myfrontend"

# or with an explicit entrypoint and build directory:
mount Ruflet::Rails.web_app(build_dir: Rails.root.join("public/app")) { |page|
  CounterView.render(page)
}, at: "/myfrontend"

How it stays mount-point independent: the Flutter web client derives both its asset URLs and its WebSocket URL from ‘Uri.base`, which comes from index.html’s <base href>. This app rewrites <base href> to the actual mount point on the fly, so the same build works under any route — the client then connects its WebSocket back to the mount point, where the upgrade is answered via Rack hijack by the shared Ruflet::ConnectionProtocol engine running on the Rails server itself.

Constant Summary collapse

CONTENT_TYPES =
{
  ".html" => "text/html; charset=utf-8",
  ".js" => "application/javascript",
  ".mjs" => "application/javascript",
  ".css" => "text/css",
  ".json" => "application/json",
  ".wasm" => "application/wasm",
  ".png" => "image/png",
  ".jpg" => "image/jpeg",
  ".jpeg" => "image/jpeg",
  ".gif" => "image/gif",
  ".webp" => "image/webp",
  ".svg" => "image/svg+xml",
  ".ico" => "image/x-icon",
  ".otf" => "font/otf",
  ".ttf" => "font/ttf",
  ".woff" => "font/woff",
  ".woff2" => "font/woff2",
  ".map" => "application/json",
  ".txt" => "text/plain"
}.freeze

Instance Method Summary collapse

Methods included from WebSocketDetection

#websocket_upgrade?

Constructor Details

#initialize(build_dir: nil, entrypoint: nil, &app_block) ⇒ WebApp

Returns a new instance of WebApp.



50
51
52
53
54
55
56
# File 'lib/ruflet/rails/protocol/web_app.rb', line 50

def initialize(build_dir: nil, entrypoint: nil, &app_block)
  @explicit_build_dir = build_dir
  @entrypoint_option = entrypoint
  @app_block = app_block
  @endpoint = nil
  @endpoint_mutex = Mutex.new
end

Instance Method Details

#call(env) ⇒ Object



58
59
60
61
62
63
64
65
# File 'lib/ruflet/rails/protocol/web_app.rb', line 58

def call(env)
  return websocket_endpoint.call(env) if websocket_upgrade?(env)

  path = env["PATH_INFO"].to_s
  return serve_index(env) if ["", "/", "/index.html"].include?(path)

  serve_static(path)
end