@@ -220,17 +220,19 @@ bool MeatHttpClient::HEAD(std::string dstUrl) {
220220 return rc;
221221}
222222
223- bool MeatHttpClient::processRedirectsAndOpen (int range ) {
223+ bool MeatHttpClient::processRedirectsAndOpen (uint32_t position, uint32_t size ) {
224224 wasRedirected = false ;
225- _size = -1 ;
226225
227226 // Debug_printv("reopening url[%s] from position:%d", url.c_str(), range);
228- lastRC = openAndFetchHeaders (lastMethod, range);
227+ lastRC = openAndFetchHeaders (lastMethod, position, size);
228+
229+ if (lastRC == 206 )
230+ isFriendlySkipper = true ;
229231
230232 while (lastRC == HttpStatus_MovedPermanently || lastRC == HttpStatus_Found || lastRC == 303 )
231233 {
232234 // Debug_printv("--- Page moved, doing redirect to [%s]", url.c_str());
233- lastRC = openAndFetchHeaders (lastMethod, range );
235+ lastRC = openAndFetchHeaders (lastMethod, position, size );
234236 wasRedirected = true ;
235237 }
236238
@@ -242,9 +244,9 @@ bool MeatHttpClient::processRedirectsAndOpen(int range) {
242244
243245 _is_open = true ;
244246 _exists = true ;
245- _position = 0 ;
247+ _position = position ;
246248
247- Debug_printv (" size[%d] avail[%d] isFriendlySkipper[%d] isText[%d] httpCode[%d] method[%d]" , _size, available (), isFriendlySkipper, isText, lastRC, lastMethod);
249+ // Debug_printv("size[%d] avail[%d] isFriendlySkipper[%d] isText[%d] httpCode[%d] method[%d]", _size, available(), isFriendlySkipper, isText, lastRC, lastMethod);
248250
249251 return true ;
250252}
@@ -274,30 +276,32 @@ void MeatHttpClient::setOnHeader(const std::function<int(char*, char*)> &lambda)
274276}
275277
276278bool MeatHttpClient::seek (uint32_t pos) {
277- if (pos==_position)
278- return true ;
279279
280280 if (isFriendlySkipper) {
281281
282282 if (_is_open) {
283283 // Read to end of the stream
284284 // Debug_printv("Skipping to end!");
285- char c[256 ];
286- while ( esp_http_client_read (_http, c, 256 ) > 0 );
285+ while (1 )
286+ {
287+ char c[HTTP_BLOCK_SIZE];
288+ int bytes = esp_http_client_read (_http, c, HTTP_BLOCK_SIZE);
289+ if ( bytes < HTTP_BLOCK_SIZE )
290+ break ;
291+ }
287292 }
288293
289294 bool op = processRedirectsAndOpen (pos);
290295
291296 // Debug_printv("SEEK in HttpIStream %s: range request RC=%d", url.c_str(), lastRC);
292-
297+
293298 if (!op)
294299 return false ;
295300
296301 // 200 = range not supported! according to https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests
297302 if (lastRC == 206 )
298303 {
299304 // Debug_printv("Seek successful");
300-
301305 _position = pos;
302306 return true ;
303307 }
@@ -345,20 +349,24 @@ uint32_t MeatHttpClient::read(uint8_t* buf, uint32_t size) {
345349
346350 if (!_is_open) {
347351 Debug_printv (" Opening HTTP Stream!" );
348- processRedirectsAndOpen (0 );
352+ processRedirectsAndOpen (0 , size );
349353 }
350354
351355 if (_is_open) {
352356 // Debug_printv("Reading HTTP Stream!");
353357 auto bytesRead= esp_http_client_read (_http, (char *)buf, size );
354358
355- if (bytesRead> 0 ) {
359+ if (bytesRead >= 0 ) {
356360 _position+=bytesRead;
361+
362+ if (bytesRead < size)
363+ openAndFetchHeaders (lastMethod, _position);
357364 }
358- if (bytesRead< 0 )
365+ if (bytesRead < 0 )
359366 return 0 ;
360367
361- return bytesRead;
368+ // Debug_printv("size[%d] bytesRead[%d] _position[%d]", size, bytesRead, _position);
369+ return bytesRead;
362370 }
363371 return 0 ;
364372};
@@ -378,34 +386,32 @@ uint32_t MeatHttpClient::write(const uint8_t* buf, uint32_t size) {
378386 return 0 ;
379387};
380388
381- int MeatHttpClient::openAndFetchHeaders (esp_http_client_method_t meth, int resume ) {
389+ int MeatHttpClient::openAndFetchHeaders (esp_http_client_method_t method, uint32_t position, uint32_t size ) {
382390
383391 if ( url.size () < 5 )
384392 return 0 ;
385393
386394 // Set URL and Method
387395 mstr::replaceAll (url, " " , " %20" );
388396 esp_http_client_set_url (_http, url.c_str ());
389- esp_http_client_set_method (_http, meth );
397+ esp_http_client_set_method (_http, method );
390398
391399 // Set Headers
392400 for (const auto & pair : headers) {
393401 std::cout << pair.first << " : " << pair.second << std::endl;
394402 esp_http_client_set_header (_http, pair.first .c_str (), pair.second .c_str ());
395403 }
396404
405+ // Set Range Header
406+ char str[40 ];
407+ snprintf (str, sizeof str, " bytes=%lu-%lu" , position, (position + size + 5 ));
408+ esp_http_client_set_header (_http, " Range" , str);
409+ // Debug_printv("seeking range[%s] url[%s]", str, url.c_str());
410+
397411 // POST
398412 // const char *post_data = "{\"field1\":\"value1\"}";
399413 // esp_http_client_set_post_field(client, post_data, strlen(post_data));
400414
401-
402- if (resume > 0 ) {
403- char str[40 ];
404- snprintf (str, sizeof str, " bytes=%lu-" , (unsigned long )resume);
405- esp_http_client_set_header (_http, " range" , str);
406- // Debug_printv("seeking range[%s]", str);
407- }
408-
409415 // Debug_printv("--- PRE OPEN");
410416 esp_err_t rc = esp_http_client_open (_http, 0 ); // or open? It's not entirely clear...
411417
@@ -417,7 +423,7 @@ int MeatHttpClient::openAndFetchHeaders(esp_http_client_method_t meth, int resum
417423 if (_size == -1 && lengthResp > 0 ) {
418424 // only if we aren't chunked!
419425 _size = lengthResp;
420- _position = 0 ;
426+ _position = position ;
421427 }
422428 }
423429
@@ -433,6 +439,7 @@ esp_err_t MeatHttpClient::_http_event_handler(esp_http_client_event_t *evt)
433439 case HTTP_EVENT_ERROR: // This event occurs when there are any errors during execution
434440 Debug_printv (" HTTP_EVENT_ERROR" );
435441 meatClient->_error = 1 ;
442+ meatClient->close ();
436443 break ;
437444
438445 case HTTP_EVENT_ON_CONNECTED: // Once the HTTP has been connected to the server, no data exchange has been performed
@@ -447,15 +454,25 @@ esp_err_t MeatHttpClient::_http_event_handler(esp_http_client_event_t *evt)
447454 // Does this server support resume?
448455 // Accept-Ranges: bytes
449456
450- if (mstr::equals (" Accept-Ranges" , evt->header_key , false ))
457+ // if (mstr::equals("Accept-Ranges", evt->header_key, false))
458+ // {
459+ // if(meatClient != nullptr) {
460+ // meatClient->isFriendlySkipper = mstr::equals("bytes", evt->header_value,false);
461+ // Debug_printv("Accept-Ranges: %s",evt->header_value);
462+ // }
463+ // }
464+ if (mstr::equals (" Content-Range" , evt->header_key , false ))
451465 {
466+ // Debug_printv("Content-Range: %s",evt->header_value);
452467 if (meatClient != nullptr ) {
453- meatClient->isFriendlySkipper = mstr::equals (" bytes" , evt->header_value ,false );
454- // Debug_printv("* Ranges info present '%s', comparison=%d!",evt->header_value, strcmp("bytes", evt->header_value)==0);
468+ meatClient->isFriendlySkipper = true ;
469+ auto cr = util_tokenize (evt->header_value , ' /' );
470+ if ( cr.size () > 1 )
471+ meatClient->_size = std::stoi (cr[1 ]);
455472 }
456473 }
457474 // what can we do UTF8<->PETSCII on this stream?
458- else if (mstr::equals (" Content-Type" , evt->header_key , false ))
475+ if (mstr::equals (" Content-Type" , evt->header_key , false ))
459476 {
460477 std::string asString = evt->header_value ;
461478 bool isText = mstr::isText (asString);
0 commit comments