1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
|
# frozen_string_literal: true
require "uri"
require_relative "middleware/context"
module Browser
class Middleware
# Detect the most common assets.
ASSETS_REGEX =
/\.(css|png|jpe?g|gif|js|svg|ico|flv|mov|m4v|ogg|swf)\z/i.freeze
# Detect the ACCEPT header. IE8 send */*.
ACCEPT_REGEX = %r{(text/html|\*/\*)}.freeze
def initialize(app, &block)
raise ArgumentError, "Browser::Middleware requires a block" unless block
@app = app
@block = block
end
def call(env)
request = Rack::Request.new(env)
# Only apply verification on HTML requests.
# This ensures that images, CSS and JavaScript
# will be rendered.
return run_app(env) unless process?(request)
path = catch(:redirected) do
Context.new(request).instance_eval(&@block)
end
# No path, no match.
return run_app(env) unless path
resolve_redirection(env, request.path, path)
end
def resolve_redirection(env, current_path, path)
uri = URI.parse(path)
if uri.path == current_path
run_app(env)
else
redirect(path)
end
end
def redirect(path)
[302, {"Content-Type" => "text/html", "Location" => path}, []]
end
def run_app(env)
@app.call(env)
end
def process?(request)
html?(request) && !assets?(request)
end
def html?(request)
request.env["HTTP_ACCEPT"].to_s.match(ACCEPT_REGEX)
end
def assets?(request)
request.path.match(ASSETS_REGEX)
end
end
end
|