diff options
-rw-r--r-- | mastodon/Mastodon.py | 51 |
1 files changed, 17 insertions, 34 deletions
diff --git a/mastodon/Mastodon.py b/mastodon/Mastodon.py index 8634fd1..5b198a5 100644 --- a/mastodon/Mastodon.py +++ b/mastodon/Mastodon.py | |||
@@ -16,6 +16,7 @@ import dateutil.parser | |||
16 | import re | 16 | import re |
17 | import copy | 17 | import copy |
18 | import threading | 18 | import threading |
19 | from urllib.parse import urlparse | ||
19 | 20 | ||
20 | 21 | ||
21 | class Mastodon: | 22 | class Mastodon: |
@@ -1158,40 +1159,22 @@ class Mastodon: | |||
1158 | wish to terminate it. | 1159 | wish to terminate it. |
1159 | """ | 1160 | """ |
1160 | 1161 | ||
1161 | headers = {} | 1162 | # Check if we have to redirect |
1162 | if self.access_token is not None: | 1163 | instance = self.instance() |
1163 | headers = {'Authorization': 'Bearer ' + self.access_token} | 1164 | if "streaming_api" in instance["urls"] and instance["urls"]["streaming_api"] != self.api_base_url: |
1164 | url = self.api_base_url + endpoint | 1165 | # This is probably a websockets URL, which is really for the browser, but requests can't handle it |
1165 | 1166 | # So we do this below to turn it into an HTTPS URL | |
1166 | # requests session subclass to disable stripping authorization headers | 1167 | parse = urlparse(instance["urls"]["streaming_api"]) |
1167 | class __no_auth_strip_session(requests.Session): | 1168 | url = "https://" + parse.netloc |
1168 | def rebuild_auth(self, prepared_request, response): | 1169 | else: |
1169 | return | 1170 | url = self.api_base_url |
1170 | 1171 | ||
1171 | # Mastodon can be configured to use another address for streaming. | 1172 | # The streaming server can't handle two slashes in a path, so remove trailing slashes |
1172 | # However, due to a bug, Mastodon does not issue 301 Permanently | 1173 | if url[-1] == '/': |
1173 | # Moved redirects for anything but /api/v1/streaming (including | 1174 | url = url[:-1] |
1174 | # subdirs), instead returning a 404 with no redirect and causing the | 1175 | |
1175 | # entire request to fail. | 1176 | headers = {"Authorization": "Bearer " + self.access_token} |
1176 | # | 1177 | connection = requests.get(url + endpoint, headers = headers, data = params, stream = True) |
1177 | # The workaround is to hit /api/v1/streaming and see if there is a | ||
1178 | # redirection, and then use the domain it gives us to do the final | ||
1179 | # request. | ||
1180 | if endpoint.startswith("/api/v1/streaming"): | ||
1181 | stream_base = self.api_base_url + "/api/v1/streaming" | ||
1182 | |||
1183 | with __no_auth_strip_session() as session: | ||
1184 | connection = session.get(stream_base, headers = headers, data = params) | ||
1185 | |||
1186 | if connection.status_code not in (404, 200): | ||
1187 | # 404 is a normal error, raise on anything else | ||
1188 | raise MastodonNetworkError("Could not connect to streaming server: %s" % connection.reason) | ||
1189 | |||
1190 | url = connection.url.replace("/api/v1/streaming", endpoint) | ||
1191 | |||
1192 | with __no_auth_strip_session() as session: | ||
1193 | # Prevent stripping of authorisation headers on redirect | ||
1194 | connection = session.get(url, headers = headers, data = params, stream = True) | ||
1195 | 1178 | ||
1196 | if connection.status_code != 200: | 1179 | if connection.status_code != 200: |
1197 | raise MastodonNetworkError("Could not connect to streaming server: %s" % connection.reason) | 1180 | raise MastodonNetworkError("Could not connect to streaming server: %s" % connection.reason) |