class Froxy::Proxy

Constants

BUILD_PATH
CLI
FALLTHRU_TYPES
FILE_EXT_MAP

Public Class Methods

new(app) click to toggle source
# File lib/froxy/proxy.rb, line 19
def initialize(app)
  @app = app
  @file_server = Rack::Files.new(Rails.root)
  @build_file_server = Rack::Files.new(Rails.root.join(BUILD_PATH))
end

Public Instance Methods

call(env) click to toggle source
# File lib/froxy/proxy.rb, line 25
def call(env)
  req = Rack::Request.new(env)
  path_info = req.path_info

  if req.get? || req.head?
    # Let images through.
    return @file_server.call(env) if FALLTHRU_TYPES.match?(path_info)

    # Let JS sourcemaps through.
    return @build_file_server.call(env) if /\.js\.map$/i.match?(path_info)

    # Let esbuild handle JS and CSS.
    if /\.(js|jsx|css)$/i.match?(path_info)
      return unless (path = clean_path(path_info))
      return [404, {}, []] unless file_readable?(path)

      return @file_server.call(env) unless Rails.application.config.froxy.use_esbuild

      return benchmark logging_message(req) do
        build env, req, path
      end
    end
  end

  @app.call req.env
end

Private Instance Methods

build(env, request, path) click to toggle source

Build the file from the given `path` using ESbuild. Returns a Rack::Response.

# File lib/froxy/proxy.rb, line 66
def build(env, request, path)
  stdout, stderr, status = Open3.capture3(CLI, Rails.root.to_s, path)

  if status.success?
    raise "[froxy] build failed: #{stderr}" unless stderr.empty?
  else
    non_empty_streams = [stdout, stderr].delete_if(&:empty?)
    raise "[froxy] build failed:\n#{non_empty_streams.join("\n\n")}"
  end

  path_to_file env, request, path
end
clean_path(path_info) click to toggle source
# File lib/froxy/proxy.rb, line 87
def clean_path(path_info)
  path = Rack::Utils.unescape_path path_info.chomp('/').delete_prefix('/')
  Rack::Utils.clean_path_info path if Rack::Utils.valid_path? path
end
file_readable?(path) click to toggle source
# File lib/froxy/proxy.rb, line 79
def file_readable?(path)
  file_stat = File.stat(Rails.root.join(path.delete_prefix('/').b).to_s)
rescue SystemCallError
  false
else
  file_stat.file? && file_stat.readable?
end
logger() click to toggle source
# File lib/froxy/proxy.rb, line 92
def logger
  Rails.logger
end
logging_message(request) click to toggle source
# File lib/froxy/proxy.rb, line 54
def logging_message(request)
  format '[froxy] "%s" for %s at %s', request.path_info, request.ip, Time.now.to_default_s
end
path_to_file(env, request, path) click to toggle source
# File lib/froxy/proxy.rb, line 58
def path_to_file(env, request, path)
  ext = Pathname.new(path).extname
  request.path_info = path.sub(/#{ext}$/, FILE_EXT_MAP[ext]) if FILE_EXT_MAP.key?(ext)

  @build_file_server.call env
end