@@ -164,8 +164,8 @@ def _create_txn_id(self) -> str:
164
164
_next_id = (_next_id + 1 ) % (MAXINT - 1 )
165
165
return txn_id
166
166
167
- uri : bytes = attr .ib (init = False )
168
- """The URI of this request, generated from the above information.
167
+ uri : bytes = attr .ib ()
168
+ """The URI of this request, usually generated from the above information.
169
169
"""
170
170
171
171
@uri .default
@@ -515,6 +515,7 @@ async def _send_request(
515
515
ignore_backoff : bool = False ,
516
516
backoff_on_404 : bool = False ,
517
517
backoff_on_all_error_codes : bool = False ,
518
+ follow_redirects : bool = False ,
518
519
) -> IResponse :
519
520
"""
520
521
Sends a request to the given server.
@@ -557,6 +558,9 @@ async def _send_request(
557
558
backoff_on_404: Back off if we get a 404
558
559
backoff_on_all_error_codes: Back off if we get any error response
559
560
561
+ follow_redirects: True to follow the Location header of 307/308 redirect
562
+ responses. This does not recurse.
563
+
560
564
Returns:
561
565
Resolves with the HTTP response object on success.
562
566
@@ -716,6 +720,26 @@ async def _send_request(
716
720
response .code ,
717
721
response_phrase ,
718
722
)
723
+ elif (
724
+ response .code in (307 , 308 )
725
+ and follow_redirects
726
+ and response .headers .hasHeader ("Location" )
727
+ ):
728
+ # The Location header *might* be relative so resolve it.
729
+ location = response .headers .getRawHeaders (b"Location" )[0 ]
730
+ new_uri = urllib .parse .urljoin (request .uri , location )
731
+
732
+ return await self ._send_request (
733
+ attr .evolve (request , uri = new_uri ),
734
+ retry_on_dns_fail ,
735
+ timeout ,
736
+ long_retries ,
737
+ ignore_backoff ,
738
+ backoff_on_404 ,
739
+ backoff_on_all_error_codes ,
740
+ # Do not continue following redirects.
741
+ follow_redirects = False ,
742
+ )
719
743
else :
720
744
logger .info (
721
745
"{%s} [%s] Got response headers: %d %s" ,
@@ -1385,6 +1409,7 @@ async def get_file(
1385
1409
retry_on_dns_fail : bool = True ,
1386
1410
max_size : Optional [int ] = None ,
1387
1411
ignore_backoff : bool = False ,
1412
+ follow_redirects : bool = False ,
1388
1413
) -> Tuple [int , Dict [bytes , List [bytes ]]]:
1389
1414
"""GETs a file from a given homeserver
1390
1415
Args:
@@ -1394,6 +1419,8 @@ async def get_file(
1394
1419
args: Optional dictionary used to create the query string.
1395
1420
ignore_backoff: true to ignore the historical backoff data
1396
1421
and try the request anyway.
1422
+ follow_redirects: True to follow the Location header of 307/308 redirect
1423
+ responses. This does not recurse.
1397
1424
1398
1425
Returns:
1399
1426
Resolves with an (int,dict) tuple of
@@ -1414,7 +1441,10 @@ async def get_file(
1414
1441
)
1415
1442
1416
1443
response = await self ._send_request (
1417
- request , retry_on_dns_fail = retry_on_dns_fail , ignore_backoff = ignore_backoff
1444
+ request ,
1445
+ retry_on_dns_fail = retry_on_dns_fail ,
1446
+ ignore_backoff = ignore_backoff ,
1447
+ follow_redirects = follow_redirects ,
1418
1448
)
1419
1449
1420
1450
headers = dict (response .headers .getAllRawHeaders ())
0 commit comments