Sha256: 246c1497f3423876b84c0dacf35acdef831e921f8aef95345e4d3296866987d2

Contents?: true

Size: 1.46 KB

Versions: 1

Compression:

Stored size: 1.46 KB

Contents

# frozen_string_literal: true

require "action_dispatch"

module RailsHttpPreload
  class Middleware
    def initialize(app)
      @app = app
    end

    def call(env)
      response = @app.call(env)

      response[1]["Link"] = preconnect_header(response) if required?(response, ActionDispatch::Request.new(env))

      response
    end

    # TODO: Should we just add it to every response anyway and let the browser
    # figure it out?
    def required?(response, request)
      config.asset_host.present? && html?(response) && !already_connected?(request)
    end

    # Adding this header to, for example, a JSON response would be pointless
    # TODO: remove from Turbo frame responses too
    def html?(response)
      response[1]["Content-Type"].match?("html")
    end

    def current_asset_host
      ActionController::Base.helpers.compute_asset_host("", host: config.asset_host)
    end

    # If the asset host is equal to the request domain, no need to add.
    def already_connected?(request)
      request.base_url == current_asset_host
    end

    def preconnect_header(response)
      header = [
        current_asset_host,
        *config.additional_urls
      ].compact.map { |url| create_link_header(url) }.join(", ")

      if response[1]["Link"]
        "#{header}, #{response[1]["Link"]}"
      else
        header
      end
    end

    def create_link_header(url)
      "<#{url}>; rel=preconnect"
    end

    def config
      RailsHttpPreload.config
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
rails_http_preload-0.3.0 lib/rails_http_preload/middleware.rb