Sha256: f50ab4d732e4b9d759b65184116b958538c838bddf1cfc3f1022289987fe810a

Contents?: true

Size: 1.9 KB

Versions: 5

Compression:

Stored size: 1.9 KB

Contents

# frozen_string_literal: true

module Metatron
  # Implementes a Metacontroller CompositeController
  # @see https://metacontroller.github.io/metacontroller/api/compositecontroller.html
  class CompositeController < Controller
    def initialize(env)
      super
      @strategy = nil
    end

    def calculate_customize_etag = nil
    def calculate_sync_etag = nil
    def customize = raise NotImplementedError
    def finalize = raise NotImplementedError
    def sync = raise NotImplementedError

    private

    STRATEGY = {
      "/customize" => { data: :customize, etag: :calculate_customize_etag },
      # finalize calls should be rare and unique enough that we don't need to worry about ETags
      "/finalize" => { data: :finalize },
      "/sync" => { data: :sync, etag: :calculate_sync_etag }
    }.freeze

    def _call
      return access_control_allow_methods if request.options?
      return not_found unless request.post?

      @strategy = STRATEGY.fetch(request.path_info) { return not_found }

      headers = {}

      return Rack::Response[412, headers, []].to_a if etag_matches?(headers)

      Rack::Response[200, headers, processed_data].to_a
    end

    def access_control_allow_methods
      Rack::Response[200, { "access-control-allow-methods" => %w[POST] }, []].to_a
    end

    def not_found
      Rack::Response[404, { "x-cascade" => "pass" }, []].to_a
    end

    def etag_matches?(headers)
      return false unless (calculator = @strategy[:etag])
      return false unless (raw_etag = public_send(calculator))

      etag = +'"' << raw_etag << '"'
      headers["etag"] = etag

      (none_match = request.get_header("HTTP_IF_NONE_MATCH")) && none_match.include?(etag)
    end

    def processed_data
      data = public_send(@strategy[:data])

      if data[:children]
        data[:children] = data[:children].map { |c| c.respond_to?(:render) ? c.render : c }
      end

      data.to_json
    end
  end
end

Version data entries

5 entries across 5 versions & 1 rubygems

Version Path
metatron-0.8.2 lib/metatron/composite_controller.rb
metatron-0.8.0 lib/metatron/composite_controller.rb
metatron-0.7.0 lib/metatron/composite_controller.rb
metatron-0.6.1 lib/metatron/composite_controller.rb
metatron-0.6.0 lib/metatron/composite_controller.rb