From 6067aa460478f8cdc9cb1917f10cc0214a92f009 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 16 Sep 2017 10:01:15 -0500 Subject: Workaround Mastodon issue with streaming API redirection Mastodon can be configured to use another address for streaming server-side. Such a setup is common with certain deployments. However, due to a bug, Mastodon does not properly issue HTTP redirects for anything but the endpoint /api/v1/streaming (including subdirs). It instead gives a 404, causing the request to fail. The workaround is to hit this path first, checking for any redirects, and modifying the URL accordingly. This commit also includes a workaround for behaviour in requests that causes it to strip the Authorization header from redirected requests. This is intentional behaviour on the part of requests, but breaks the redirection done by Mastodon. Fixes #84 --- mastodon/Mastodon.py | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/mastodon/Mastodon.py b/mastodon/Mastodon.py index d427444..7b75776 100644 --- a/mastodon/Mastodon.py +++ b/mastodon/Mastodon.py @@ -1162,7 +1162,40 @@ class Mastodon: headers = {'Authorization': 'Bearer ' + self.access_token} url = self.api_base_url + endpoint - connection = requests.get(url, headers = headers, data = params, stream = True) + # requests session subclass to disable stripping authorization headers + class __no_auth_strip_session(requests.Session): + def rebuild_auth(self, prepared_request, response): + return + + # Mastodon can be configured to use another address for streaming. + # However, due to a bug, Mastodon does not issue 301 Permanently + # Moved redirects for anything but /api/v1/streaming (including + # subdirs), instead returning a 404 with no redirect and causing the + # entire request to fail. + # + # The workaround is to hit /api/v1/streaming and see if there is a + # redirection, and then use the domain it gives us to do the final + # request. + if endpoint.startswith("/api/v1/streaming"): + print("Hi I'm streaming", endpoint) + stream_base = self.api_base_url + "/api/v1/streaming" + + with __no_auth_strip_session() as session: + connection = session.get(stream_base, headers = headers, data = params) + + if connection.status_code not in (404, 200): + # 404 is a normal error, raise on anything else + raise MastodonNetworkError("Could not connect to streaming server: %s" % connection.reason) + + url = connection.url.replace("/api/v1/streaming", endpoint) + print("Url redirected:", url) + + with __no_auth_strip_session() as session: + # Prevent stripping of authorisation headers on redirect + connection = session.get(url, headers = headers, data = params, stream = True) + + if connection.status_code != 200: + raise MastodonNetworkError("Could not connect to streaming server: %s" % connection.reason) class __stream_handle(): def __init__(self, connection): -- cgit v1.2.3 From 5b90a3c8302f7a13303f95d12eb3e3a7de635f4b Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 16 Sep 2017 10:09:32 -0500 Subject: Remove debugging print statements --- mastodon/Mastodon.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/mastodon/Mastodon.py b/mastodon/Mastodon.py index 7b75776..1fb7d69 100644 --- a/mastodon/Mastodon.py +++ b/mastodon/Mastodon.py @@ -1177,7 +1177,6 @@ class Mastodon: # redirection, and then use the domain it gives us to do the final # request. if endpoint.startswith("/api/v1/streaming"): - print("Hi I'm streaming", endpoint) stream_base = self.api_base_url + "/api/v1/streaming" with __no_auth_strip_session() as session: @@ -1188,7 +1187,6 @@ class Mastodon: raise MastodonNetworkError("Could not connect to streaming server: %s" % connection.reason) url = connection.url.replace("/api/v1/streaming", endpoint) - print("Url redirected:", url) with __no_auth_strip_session() as session: # Prevent stripping of authorisation headers on redirect -- cgit v1.2.3