class ArticleIdParser include Monads ID_REGEX = /[\/\-]([0-9a-f]+)\/?$/i def self.parse(request : HTTP::Request) new.parse(request) end def parse(request : HTTP::Request) : Maybe from_params = post_id_from_params(request.query_params) from_path = post_id_from_path(request.path) from_params.or(from_path) end private def post_id_from_path(request_path : String) return Nothing(String).new if request_path.starts_with?("/tag/") Try(Regex::MatchData) .new(->{ request_path.match(ID_REGEX) }) .to_maybe .fmap(->(matches : Regex::MatchData) { matches[1] }) end private def post_id_from_params(params : URI::Params) maybe_uri = Try(String) .new(->{ params["redirectUrl"] }) .to_maybe .fmap(->(url : String) { URI.parse(url) }) .bind(->(uri : URI) { post_id_from_path(uri.path) }) end end