From bb94fb41b198b78566d0ab8400d31ccb3e5bc142 Mon Sep 17 00:00:00 2001 From: Edward Loveall Date: Mon, 11 Oct 2021 11:56:28 -0400 Subject: [PATCH] Support medium's redirectUrl query param When a post has a gi= query param, Medium makes a global_identifier "query". This redirects via a 307 temporary redirect to a url that looks like this: https://medium.com/m/global-identity?redirectUrl=https%3A%2F%2Fexample.c om%2Fmy-post-000000000000 Previously, scribe looked for the Medium post id in the url's path, not it's query params since query params can include other garbage like medium_utm (not related to medium.com). Now it looks first for the post id in the path, then looks to the redirectUrl as a fallback. --- spec/requests/articles/show_spec.cr | 6 ++++++ src/actions/articles/show.cr | 22 ++++++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/spec/requests/articles/show_spec.cr b/spec/requests/articles/show_spec.cr index 56ad415..0a2fadc 100644 --- a/spec/requests/articles/show_spec.cr +++ b/spec/requests/articles/show_spec.cr @@ -68,4 +68,10 @@ describe Articles::Show do TestClient.last_post_id.should eq("777777abcdef") end + + it "parses the post id for global identity redirects" do + HttpClient.get("/m/global-identity?redirectUrl=https%3A%2F%2Fexample.com%2Fmy-post-888888abcdef") + + TestClient.last_post_id.should eq("888888abcdef") + end end diff --git a/src/actions/articles/show.cr b/src/actions/articles/show.cr index 8bf9fa7..98cde52 100644 --- a/src/actions/articles/show.cr +++ b/src/actions/articles/show.cr @@ -2,10 +2,10 @@ require "json" class Articles::Show < BrowserAction fallback do - maybe_post_id = post_id(context.request.path) - case maybe_post_id + post_id = maybe_post_id(context.request) + case post_id in Monads::Just - response = client_class.post_data(maybe_post_id.value!) + response = client_class.post_data(post_id.value!) page = PageConverter.new.convert(response.data) html ShowPage, page: page in Monads::Nothing, Monads::Maybe @@ -17,13 +17,27 @@ class Articles::Show < BrowserAction end end - def post_id(request_path : String) + def maybe_post_id(request : HTTP::Request) + from_params = post_id_from_params(request.query_params) + from_path = post_id_from_path(request.path) + from_path.or(from_params) + end + + def post_id_from_path(request_path : String) Monads::Try(Regex::MatchData) .new(->{ request_path.match(/([0-9a-f]+)$/i) }) .to_maybe .fmap(->(matches : Regex::MatchData) { matches[1] }) end + def post_id_from_params(params : URI::Params) + maybe_uri = Monads::Try(String) + .new(->{ params["redirectUrl"] }) + .to_maybe + .fmap(->(url : String) { URI.parse(url) }) + .bind(->(uri : URI) { post_id_from_path(uri.path) }) + end + def client_class if Lucky::Env.use_local? LocalClient