Class: Dispatch::Rails::AssetMiddleware

Inherits:
Object
  • Object
show all
Defined in:
lib/dispatch/rails/asset_middleware.rb

Overview

Serves the gem’s browser JS (error_tracker.js, widget.js) at the stable, non-digested /dispatch/<name>.js paths the view partials import from.

The engine also registers the JS directory in config.assets.paths, but the partials deliberately import a fixed URL (so the inline loader needs no asset-pipeline lookup) — and the asset pipeline never exposes that exact URL: Propshaft serves the files under /assets/dispatch/<name>-<digest>.js, Sprockets under /assets/dispatch/<name>.js, and neither at /dispatch/<name>.js. With nothing serving that path the import 404s in every environment and the tracker/widget silently never load. This middleware closes that gap with no host mount, route, or precompile entry required.

Registered outermost of the gem’s middlewares (see Engine), so a matching GET short-circuits before the capture/heartbeat layers and never counts as traffic. It owns ONLY the two exact paths it knows; every other request passes straight through.

Constant Summary collapse

ASSET_DIR =
File.expand_path("../../../app/assets/javascripts/dispatch", __dir__).freeze
ASSETS =

Exact request path => filename. A fixed allowlist (no path joining from the request) so a crafted PATH_INFO can never traverse out of ASSET_DIR.

{
  "/dispatch/error_tracker.js" => "error_tracker.js",
  "/dispatch/widget.js"        => "widget.js"
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(app) ⇒ AssetMiddleware

Returns a new instance of AssetMiddleware.



29
30
31
# File 'lib/dispatch/rails/asset_middleware.rb', line 29

def initialize(app)
  @app = app
end

Instance Method Details

#call(env) ⇒ Object



33
34
35
36
37
38
39
# File 'lib/dispatch/rails/asset_middleware.rb', line 33

def call(env)
  method = env["REQUEST_METHOD"]
  filename = (method == "GET" || method == "HEAD") && ASSETS[env["PATH_INFO"]]
  return @app.call(env) unless filename

  serve(File.join(ASSET_DIR, filename), head: method == "HEAD")
end