class GdsApi::ContentStore::RedirectResolver
def self.call(*args)
def self.call(*args) new(*args).call end
def call
def call redirect = redirect_for_path(request_path) raise UnresolvedRedirect, "Could not find a matching redirect" unless redirect destination_uri = URI.parse( resolve_destination(redirect, request_path, request_query), ) url = if destination_uri.absolute? destination_uri.to_s else "#{Plek.new.website_root}#{destination_uri}" end [url, status_code(redirect)] end
def initialize(content_item, request_path, request_query = "")
def initialize(content_item, request_path, request_query = "") @content_item = content_item @request_path = request_path @request_query = request_query.to_s end
def prefix_destination(redirect, path, query)
def prefix_destination(redirect, path, query) uri = URI.parse(redirect["destination"]) start_char = redirect["path"].length suffix = path[start_char..-1] if uri.path == "" && suffix[0] != "/" uri.path = "/#{suffix}" else uri.path += suffix end uri.query = query if uri.query.nil? && !query.empty? uri.to_s end
def redirect_for_path(path)
def redirect_for_path(path) redirects_by_segments.find do |r| next true if r["path"] == path route_prefix_match?(r["path"], path) if r["type"] == "prefix" end end
def redirects_by_segments
def redirects_by_segments redirects = content_item["redirects"] || [] redirects.sort_by { |r| r["path"].split("/").count * -1 } end
def resolve_destination(redirect, path, query)
def resolve_destination(redirect, path, query) return redirect["destination"] unless redirect["segments_mode"] == "preserve" if redirect["type"] == "prefix" prefix_destination(redirect, path, query) else redirect["destination"] + (query.empty? ? "" : "?#{query}") end end
def route_prefix_match?(prefix_path, path_to_match)
def route_prefix_match?(prefix_path, path_to_match) prefix_regex = %r{^#{Regexp.escape(prefix_path)}/} path_to_match.match prefix_regex end
def status_code(redirect)
def status_code(redirect) redirect["redirect_type"] == "temporary" ? 302 : 301 end