Repository: rails/rails
File: actionpack/lib/action_controller/metal/redirecting.rb (Ruby)

Code before:
          ActionDispatch::Response.rack_status_code(response_options[:status])
        else
          302
        end
      end

      def _enforce_open_redirect_protection(location, allow_other_host:)
        # Explictly allowed other host or host is in allow list allow redirect
        if allow_other_host || _url_host_allowed?(location)
          location
        # Explicitly disallowed other host
        elsif allow_other_host == false
          raise OpenRedirectError.new(location)
        # Configuration disallows other hosts
        elsif !_allow_other_host
          raise OpenRedirectError.new(location)
        # Log but allow redirect
        elsif action_on_open_redirect == :log
          logger.warn "Open redirect to #{location.inspect} detected" if logger
          location
        # Notify but allow redirect
        elsif action_on_open_redirect == :notify
          ActiveSupport::Notifications.instrument("open_redirect.action_controller",
            location: location,
            request: request,
            stacktrace: caller,
          )
          location
        # Fall through, should not happen but raise for safety
        else
          raise OpenRedirectError.new(location)
        end
      end

      def _url_host_allowed?(url)
        url_to_s = url.to_s
        host = URI(url_to_s).host

        if host.nil?
          url_to_s.start_with?("/") && !url_to_s.start_with?("//")
        else
          host == request.host || self.class.allowed_redirect_hosts_permissions&.allows?(host)
        end
      rescue ArgumentError, URI::Error
        false
      end

      def _ensure_url_is_http_header_safe(url)
        # Attempt to comply with the set of valid token characters defined for an HTTP
        # header value in https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.6
        if url.match?(ILLEGAL_HEADER_VALUE_REGEX)

Review comment (suggestion):
This was released in 8.1, so I'm not sure its worth breaking backwards compatibility to remove the underscore

Code after:
          ActionDispatch::Response.rack_status_code(response_options[:status])
        else
          302
        end
      end

      def _enforce_open_redirect_protection(location, allow_other_host:)
        # Explictly allowed other host or host is in allow list allow redirect
        if allow_other_host || _url_host_allowed?(location)
          location
        # Explicitly disallowed other host
        elsif allow_other_host == false
          raise OpenRedirectError.new(location)
        # Configuration disallows other hosts
        elsif !_allow_other_host
          raise OpenRedirectError.new(location)
        # Log but allow redirect
        elsif action_on_open_redirect == :log
          logger.warn "Open redirect to #{location.inspect} detected" if logger
          location
        # Notify but allow redirect
        elsif action_on_open_redirect == :notify
          ActiveSupport::Notifications.instrument("open_redirect.action_controller",
            location: location,
            request: request,
            stack_trace: caller,
          )
          location
        # Fall through, should not happen but raise for safety
        else
          raise OpenRedirectError.new(location)
        end
      end

      def _url_host_allowed?(url)
        url_to_s = url.to_s
        host = URI(url_to_s).host

        if host.nil?
          url_to_s.start_with?("/") && !url_to_s.start_with?("//")
        else
          host == request.host || self.class.allowed_redirect_hosts_permissions&.allows?(host)
        end
      rescue ArgumentError, URI::Error
        false
      end

      def _ensure_url_is_http_header_safe(url)
        # Attempt to comply with the set of valid token characters defined for an HTTP
        # header value in https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.6
        if url.match?(ILLEGAL_HEADER_VALUE_REGEX)