1313
1414IP = "1.2.3.4"
1515HOST = "docs.google.com"
16- PATH = (
16+ PATH_BASE = (
1717 "/spreadsheets/d/e/2PACX-1vR1WjUKz35-ek6SiR5droDfvPp51MTds4wUs57vEZNh2uDfihSTPhTaiiRo"
18- "vLbNe1mkeRgurppRJ_Zy/pub?output=tsv"
18+ "vLbNe1mkeRgurppRJ_Zy/"
19+ )
20+ PATH = PATH_BASE + "pub?output=tsv"
21+
22+ FILE_REDIRECT = (
23+ b"e@2PACX-1vR1WjUKz35-ek6SiR5droDfvPp51MTds4wUs57vEZNh2uDfihSTPhTai"
24+ b"iRovLbNe1mkeRgurppRJ_Zy?output=tsv"
25+ )
26+ RELATIVE_RELATIVE_REDIRECT = (
27+ b"370cmver1f290kjsnpar5ku2h9g/3llvt5u8njbvat22m9l19db1h4/1656191325000/109226138307867586192/*/"
28+ + FILE_REDIRECT
29+ )
30+ RELATIVE_ABSOLUTE_REDIRECT = (
31+ b"/pub/70cmver1f290kjsnpar5ku2h9g/" + RELATIVE_RELATIVE_REDIRECT
32+ )
33+ ABSOLUTE_ABSOLUTE_REDIRECT = (
34+ b"https://doc-14-2g-sheets.googleusercontent.com" + RELATIVE_ABSOLUTE_REDIRECT
1935)
2036
2137# response headers returned from the initial request
2642 b"Pragma: no-cache\r \n "
2743 b"Expires: Mon, 01 Jan 1990 00:00:00 GMT\r \n "
2844 b"Date: Sat, 25 Jun 2022 21:08:48 GMT\r \n "
29- b"Location: https://doc-14-2g-sheets.googleusercontent.com/pub/70cmver1f290kjsnpar5ku2h9g/3"
30- b"llvt5u8njbvat22m9l19db1h4/1656191325000"
31- b"/109226138307867586192/*/e@2PACX-1vR1WjUKz35-ek6SiR5droDfvPp51MTds4wUs57vEZNh2uDfihSTPhTai"
32- b"iRovLbNe1mkeRgurppRJ_Zy?output=tsv\r \n "
45+ b"Location: NEW_LOCATION_HERE\r \n "
3346 b'P3P: CP="This is not a P3P policy! See g.co/p3phelp for more info."\r \n '
3447 b"X-Content-Type-Options: nosniff\r \n "
3548 b"X-XSS-Protection: 1; mode=block\r \n "
@@ -118,13 +131,16 @@ def _recv_into(self, buf, nbytes=0):
118131 return read
119132
120133
121- def do_test_chunked_redirect ():
134+ def test_chunked_absolute_absolute_redirect ():
122135 pool = mocket .MocketPool ()
123136 pool .getaddrinfo .return_value = ((None , None , None , None , (IP , 443 )),)
124137 chunk = _chunk (BODY_REDIRECT , len (BODY_REDIRECT ))
125138 chunk2 = _chunk (BODY , len (BODY ))
126139
127- sock1 = MocketRecvInto (HEADERS_REDIRECT + chunk )
140+ redirect = HEADERS_REDIRECT .replace (
141+ b"NEW_LOCATION_HERE" , ABSOLUTE_ABSOLUTE_REDIRECT
142+ )
143+ sock1 = MocketRecvInto (redirect + chunk )
128144 sock2 = mocket .Mocket (HEADERS + chunk2 )
129145 pool .socket .side_effect = (sock1 , sock2 )
130146
@@ -135,9 +151,109 @@ def do_test_chunked_redirect():
135151 sock2 .connect .assert_called_once_with (
136152 ("doc-14-2g-sheets.googleusercontent.com" , 443 )
137153 )
154+ sock2 .send .assert_has_calls ([mock .call (RELATIVE_ABSOLUTE_REDIRECT [1 :])])
155+
156+ assert response .text == str (BODY , "utf-8" )
157+
158+
159+ def test_chunked_relative_absolute_redirect ():
160+ pool = mocket .MocketPool ()
161+ pool .getaddrinfo .return_value = ((None , None , None , None , (IP , 443 )),)
162+ chunk = _chunk (BODY_REDIRECT , len (BODY_REDIRECT ))
163+ chunk2 = _chunk (BODY , len (BODY ))
164+
165+ redirect = HEADERS_REDIRECT .replace (
166+ b"NEW_LOCATION_HERE" , RELATIVE_ABSOLUTE_REDIRECT
167+ )
168+ sock1 = MocketRecvInto (redirect + chunk )
169+ sock2 = mocket .Mocket (HEADERS + chunk2 )
170+ pool .socket .side_effect = (sock1 , sock2 )
171+
172+ requests_session = adafruit_requests .Session (pool , mocket .SSLContext ())
173+ response = requests_session .get ("https://" + HOST + PATH )
174+
175+ sock1 .connect .assert_called_once_with ((HOST , 443 ))
176+ sock2 .connect .assert_called_once_with (("docs.google.com" , 443 ))
177+ sock2 .send .assert_has_calls ([mock .call (RELATIVE_ABSOLUTE_REDIRECT [1 :])])
178+
179+ assert response .text == str (BODY , "utf-8" )
180+
181+
182+ def test_chunked_relative_relative_redirect ():
183+ pool = mocket .MocketPool ()
184+ pool .getaddrinfo .return_value = ((None , None , None , None , (IP , 443 )),)
185+ chunk = _chunk (BODY_REDIRECT , len (BODY_REDIRECT ))
186+ chunk2 = _chunk (BODY , len (BODY ))
187+
188+ redirect = HEADERS_REDIRECT .replace (
189+ b"NEW_LOCATION_HERE" , RELATIVE_RELATIVE_REDIRECT
190+ )
191+ sock1 = MocketRecvInto (redirect + chunk )
192+ sock2 = mocket .Mocket (HEADERS + chunk2 )
193+ pool .socket .side_effect = (sock1 , sock2 )
194+
195+ requests_session = adafruit_requests .Session (pool , mocket .SSLContext ())
196+ response = requests_session .get ("https://" + HOST + PATH )
197+
198+ sock1 .connect .assert_called_once_with ((HOST , 443 ))
199+ sock2 .connect .assert_called_once_with (("docs.google.com" , 443 ))
200+ sock2 .send .assert_has_calls (
201+ [mock .call (bytes (PATH_BASE [1 :], "utf-8" ) + RELATIVE_RELATIVE_REDIRECT )]
202+ )
138203
139204 assert response .text == str (BODY , "utf-8" )
140205
141206
142- def test_chunked_redirect ():
143- do_test_chunked_redirect ()
207+ def test_chunked_relative_relative_redirect_backstep ():
208+ pool = mocket .MocketPool ()
209+ pool .getaddrinfo .return_value = ((None , None , None , None , (IP , 443 )),)
210+ chunk = _chunk (BODY_REDIRECT , len (BODY_REDIRECT ))
211+ chunk2 = _chunk (BODY , len (BODY ))
212+
213+ remove_paths = 2
214+ backstep = b"../" * remove_paths
215+ path_base_parts = PATH_BASE .split ("/" )
216+ # PATH_BASE starts with "/" so skip it and also remove from the count
217+ path_base = (
218+ "/" .join (path_base_parts [1 : len (path_base_parts ) - remove_paths - 1 ]) + "/"
219+ )
220+
221+ redirect = HEADERS_REDIRECT .replace (
222+ b"NEW_LOCATION_HERE" , backstep + RELATIVE_RELATIVE_REDIRECT
223+ )
224+ sock1 = MocketRecvInto (redirect + chunk )
225+ sock2 = mocket .Mocket (HEADERS + chunk2 )
226+ pool .socket .side_effect = (sock1 , sock2 )
227+
228+ requests_session = adafruit_requests .Session (pool , mocket .SSLContext ())
229+ response = requests_session .get ("https://" + HOST + PATH )
230+
231+ sock1 .connect .assert_called_once_with ((HOST , 443 ))
232+ sock2 .connect .assert_called_once_with (("docs.google.com" , 443 ))
233+ sock2 .send .assert_has_calls (
234+ [mock .call (bytes (path_base , "utf-8" ) + RELATIVE_RELATIVE_REDIRECT )]
235+ )
236+
237+ assert response .text == str (BODY , "utf-8" )
238+
239+
240+ def test_chunked_allow_redirects_false ():
241+ pool = mocket .MocketPool ()
242+ pool .getaddrinfo .return_value = ((None , None , None , None , (IP , 443 )),)
243+ chunk = _chunk (BODY_REDIRECT , len (BODY_REDIRECT ))
244+ chunk2 = _chunk (BODY , len (BODY ))
245+
246+ redirect = HEADERS_REDIRECT .replace (
247+ b"NEW_LOCATION_HERE" , ABSOLUTE_ABSOLUTE_REDIRECT
248+ )
249+ sock1 = MocketRecvInto (redirect + chunk )
250+ sock2 = mocket .Mocket (HEADERS + chunk2 )
251+ pool .socket .side_effect = (sock1 , sock2 )
252+
253+ requests_session = adafruit_requests .Session (pool , mocket .SSLContext ())
254+ response = requests_session .get ("https://" + HOST + PATH , allow_redirects = False )
255+
256+ sock1 .connect .assert_called_once_with ((HOST , 443 ))
257+ sock2 .connect .assert_not_called ()
258+
259+ assert response .text == str (BODY_REDIRECT , "utf-8" )
0 commit comments