Class: Sinatra::Inertia::Middleware

Inherits:
Object
  • Object
show all
Defined in:
lib/sinatra/inertia/middleware.rb

Overview

Rack middleware handling concerns that must run outside the Sinatra request cycle:

* Version-mismatch detection. Per the Inertia protocol, an Inertia
  GET visit whose `X-Inertia-Version` header disagrees with the
  server's current asset version must be answered with
  `409 Conflict` and a `X-Inertia-Location` header pointing at the
  same URL — the client then performs a hard reload.

* Forced 303 redirects for non-GET requests. Inertia requires the
  client follow the redirect with a GET, which only happens when the
  server uses 303 See Other (the default 302 turns into a method-
  preserving redirect on some browsers).

The middleware is ‘register`-ed automatically by `Sinatra::Inertia` via `app.use`, so consumer apps don’t need to wire it manually.

Constant Summary collapse

INERTIA_HEADER =
'HTTP_X_INERTIA'
INERTIA_VERSION_HEADER =
'HTTP_X_INERTIA_VERSION'

Instance Method Summary collapse

Constructor Details

#initialize(app, version:) ⇒ Middleware

Returns a new instance of Middleware.



25
26
27
28
# File 'lib/sinatra/inertia/middleware.rb', line 25

def initialize(app, version:)
  @app = app
  @version = version
end

Instance Method Details

#call(env) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/sinatra/inertia/middleware.rb', line 30

def call(env)
  if inertia_get?(env) && version_mismatch?(env)
    location = env['REQUEST_URI'] || build_url(env)
    return [
      409,
      { 'X-Inertia-Location' => location, 'Vary' => 'X-Inertia' },
      []
    ]
  end

  status, headers, body = @app.call(env)

  # Promote 302 → 303 for Inertia non-GET visits so the client follows
  # the redirect with a GET. Strictly limited to `X-Inertia: true`
  # requests: a Sinatra app may serve plain REST endpoints alongside
  # Inertia pages, and rewriting their 302s would silently change
  # HTTP semantics for non-Inertia clients.
  if status == 302 && env[INERTIA_HEADER] == 'true' &&
     %w[POST PUT PATCH DELETE].include?(env['REQUEST_METHOD'])
    status = 303
  end

  [status, headers, body]
end