From 1edfd73f30ab346116355bfe815ba9d34dad1974 Mon Sep 17 00:00:00 2001 From: "Patryk (PsychoX) Ludwikowski" Date: Mon, 16 Mar 2020 22:51:57 +0100 Subject: [PATCH 1/6] Add way to force follow redirections in `HTTPClient` --- .../src/ESP8266HTTPClient.cpp | 67 +++++++++++++------ .../ESP8266HTTPClient/src/ESP8266HTTPClient.h | 14 +++- 2 files changed, 59 insertions(+), 22 deletions(-) diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp index ff46822c3e..96a2177b9e 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp @@ -558,8 +558,17 @@ bool HTTPClient::setURL(const String& url) /** * set true to follow redirects. * @param follow + * @deprecated */ void HTTPClient::setFollowRedirects(bool follow) +{ + _followRedirects = follow ? HTTPC_FOLLOW_REDIRECTS : HTTPC_DONT_FOLLOW_REDIRECTS; +} +/** + * set redirect follow mode. See `followRedirects_t` enum for avaliable modes. + * @param follow + */ +void HTTPClient::setFollowRedirects(followRedirects_t follow) { _followRedirects = follow; } @@ -699,32 +708,50 @@ int HTTPClient::sendRequest(const char * type, const uint8_t * payload, size_t s // handle Server Response (Header) code = handleHeaderResponse(); - // - // We can follow redirects for 301/302/307 for GET and HEAD requests and - // and we have not exceeded the redirect limit preventing an infinite - // redirect loop. - // - // https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html - // - if (_followRedirects && - (_redirectCount < _redirectLimit) && - (_location.length() > 0) && - (code == 301 || code == 302 || code == 307) && - (!strcmp(type, "GET") || !strcmp(type, "HEAD")) + switch (code) { + // + // Handle redirections as stated in RFC document: + // https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html + // + case HTTP_CODE_MOVED_PERMANENTLY: + case HTTP_CODE_FOUND: + case HTTP_CODE_TEMPORARY_REDIRECT: { + if ( + _followRedirects == HTTPC_DONT_FOLLOW_REDIRECTS || + _redirectCount >= _redirectLimit || + _location.length() == 0 + ) { + // no redirections + redirect = false; + break; + } + if ( + // allow to force redirections on other methods + // (the RFC require user to accept the redirection) + _followRedirects == HTTPC_FORCE_FOLLOW_REDIRECTS || + // allow GET and HEAD methods + !strcmp(type, "GET") || + !strcmp(type, "HEAD") ) { - _redirectCount += 1; // increment the count for redirect. - redirect = true; - DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] following redirect:: '%s' redirCount: %d\n", _location.c_str(), _redirectCount); - if (!setURL(_location)) { - // return the redirect instead of handling on failure of setURL() - redirect = false; + _redirectCount += 1; + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] following redirect:: '%s' redirCount: %d\n", _location.c_str(), _redirectCount); + if (!setURL(_location)) { + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] failed setting URL for redirection\n"); + redirect = false; + break; + } + redirect = true; + } + break; } - } + default: + break; + } } while (redirect); // handle 303 redirect for non GET/HEAD by changing to GET and requesting new url - if (_followRedirects && + if (_followRedirects != HTTPC_DONT_FOLLOW_REDIRECTS && (_redirectCount < _redirectLimit) && (_location.length() > 0) && (code == 303) && diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h index 1d7548f0f7..ae998ed77f 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h @@ -130,6 +130,12 @@ typedef enum { HTTPC_TE_CHUNKED } transferEncoding_t; +typedef enum { + HTTPC_FOLLOW_REDIRECTS, + HTTPC_DONT_FOLLOW_REDIRECTS, + HTTPC_FORCE_FOLLOW_REDIRECTS +} followRedirects_t; + #if HTTPCLIENT_1_1_COMPATIBLE class TransportTraits; typedef std::unique_ptr TransportTraitsPtr; @@ -173,8 +179,12 @@ class HTTPClient void setAuthorization(const char * user, const char * password); void setAuthorization(const char * auth); void setTimeout(uint16_t timeout); - void setFollowRedirects(bool follow); + + // Redirections + void setFollowRedirects(bool follow) __attribute__ ((deprecated)); + void setFollowRedirects(followRedirects_t follow); void setRedirectLimit(uint16_t limit); // max redirects to follow for a single request + bool setURL(const String& url); // handy for handling redirects void useHTTP10(bool usehttp10 = true); @@ -252,7 +262,7 @@ class HTTPClient int _returnCode = 0; int _size = -1; bool _canReuse = false; - bool _followRedirects = false; + followRedirects_t _followRedirects = HTTPC_DONT_FOLLOW_REDIRECTS; uint16_t _redirectCount = 0; uint16_t _redirectLimit = 10; String _location; From f66ae29df489b276edc174a10235e2f5f9c5a18f Mon Sep 17 00:00:00 2001 From: "Patryk (PsychoX) Ludwikowski" Date: Mon, 16 Mar 2020 23:57:41 +0100 Subject: [PATCH 2/6] Follow other client implementations about `HTTP_CODE_FOUND`; Small rewrite of `sendRequest` function of `HTTPClient` --- .../src/ESP8266HTTPClient.cpp | 133 +++++++++--------- 1 file changed, 64 insertions(+), 69 deletions(-) diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp index 96a2177b9e..b4f35777fd 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp @@ -661,106 +661,101 @@ int HTTPClient::sendRequest(const char * type, const String& payload) */ int HTTPClient::sendRequest(const char * type, const uint8_t * payload, size_t size) { - bool redirect = false; - int code = 0; - do { - // wipe out any existing headers from previous request - for(size_t i = 0; i < _headerKeysCount; i++) { - if (_currentHeaders[i].value.length() > 0) { - _currentHeaders[i].value.clear(); - } + // wipe out any existing headers from previous request + for(size_t i = 0; i < _headerKeysCount; i++) { + if (_currentHeaders[i].value.length() > 0) { + _currentHeaders[i].value.clear(); } + } - redirect = false; - DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] type: '%s' redirCount: %d\n", type, _redirectCount); + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] type: '%s' redirCount: %d\n", type, _redirectCount); - // connect to server - if(!connect()) { - return returnError(HTTPC_ERROR_CONNECTION_REFUSED); - } + // connect to server + if(!connect()) { + return returnError(HTTPC_ERROR_CONNECTION_REFUSED); + } - addHeader(F("Content-Length"), String(payload && size > 0 ? size : 0)); + addHeader(F("Content-Length"), String(payload && size > 0 ? size : 0)); - // send Header - if(!sendHeader(type)) { - return returnError(HTTPC_ERROR_SEND_HEADER_FAILED); - } + // send Header + if(!sendHeader(type)) { + return returnError(HTTPC_ERROR_SEND_HEADER_FAILED); + } - // send Payload if needed - if (payload && size > 0) { - size_t bytesWritten = 0; - const uint8_t *p = payload; - size_t originalSize = size; - while (bytesWritten < originalSize) { - int written; - int towrite = std::min((int)size, (int)HTTP_TCP_BUFFER_SIZE); - written = _client->write(p + bytesWritten, towrite); - if (written < 0) { - return returnError(HTTPC_ERROR_SEND_PAYLOAD_FAILED); - } else if (written == 0) { - return returnError(HTTPC_ERROR_CONNECTION_LOST); - } - bytesWritten += written; - size -= written; + // send Payload if needed + if (payload && size > 0) { + size_t bytesWritten = 0; + const uint8_t *p = payload; + size_t originalSize = size; + while (bytesWritten < originalSize) { + int written; + int towrite = std::min((int)size, (int)HTTP_TCP_BUFFER_SIZE); + written = _client->write(p + bytesWritten, towrite); + if (written < 0) { + return returnError(HTTPC_ERROR_SEND_PAYLOAD_FAILED); + } else if (written == 0) { + return returnError(HTTPC_ERROR_CONNECTION_LOST); } + bytesWritten += written; + size -= written; } + } - // handle Server Response (Header) - code = handleHeaderResponse(); - + // handle Server Response (Header) + int code = handleHeaderResponse(); + + // + // Handle redirections as stated in RFC document: + // https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html + // + // Implementing HTTP_CODE_FOUND as redirection with GET method, + // to follow most of existing user agent implementations. + // + if ( + _followRedirects != HTTPC_DONT_FOLLOW_REDIRECTS && + _redirectCount < _redirectLimit && + _location.length() > 0 + ) { switch (code) { - // - // Handle redirections as stated in RFC document: - // https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html - // + // redirecting using the same method case HTTP_CODE_MOVED_PERMANENTLY: - case HTTP_CODE_FOUND: case HTTP_CODE_TEMPORARY_REDIRECT: { - if ( - _followRedirects == HTTPC_DONT_FOLLOW_REDIRECTS || - _redirectCount >= _redirectLimit || - _location.length() == 0 - ) { - // no redirections - redirect = false; - break; - } if ( // allow to force redirections on other methods // (the RFC require user to accept the redirection) _followRedirects == HTTPC_FORCE_FOLLOW_REDIRECTS || - // allow GET and HEAD methods + // allow GET and HEAD methods without force !strcmp(type, "GET") || !strcmp(type, "HEAD") ) { _redirectCount += 1; - DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] following redirect:: '%s' redirCount: %d\n", _location.c_str(), _redirectCount); + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] following redirect (the same method): '%s' redirCount: %d\n", _location.c_str(), _redirectCount); if (!setURL(_location)) { DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] failed setting URL for redirection\n"); - redirect = false; + // no redirection break; } - redirect = true; + code = sendRequest(type, payload, size); } break; } + // redirecting with method dropped to GET or HEAD + // note: it does not need `HTTPC_FORCE_FOLLOW_REDIRECTS` for any method + case HTTP_CODE_FOUND: + case HTTP_CODE_SEE_OTHER: { + _redirectCount += 1; + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] following redirect (dropped to GET/HEAD): '%s' redirCount: %d\n", _location.c_str(), _redirectCount); + if (!setURL(_location)) { + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] failed setting URL for redirection\n"); + // no redirection + break; + } + code = sendRequest("GET"); + } default: break; } - } while (redirect); - - // handle 303 redirect for non GET/HEAD by changing to GET and requesting new url - if (_followRedirects != HTTPC_DONT_FOLLOW_REDIRECTS && - (_redirectCount < _redirectLimit) && - (_location.length() > 0) && - (code == 303) && - strcmp(type, "GET") && strcmp(type, "HEAD") - ) { - _redirectCount += 1; - if (setURL(_location)) { - code = sendRequest("GET"); - } } // handle Server Response (Header) From af6f69a1e0fd7611094f8fec14af5f6092ae2081 Mon Sep 17 00:00:00 2001 From: "Patryk (PsychoX) Ludwikowski" Date: Tue, 17 Mar 2020 12:02:49 +0100 Subject: [PATCH 3/6] Better names for follow redirection modes in `HTTPClient` Also changed a bit order of the enums (0 element to be DISABLED) --- .../ESP8266HTTPClient/src/ESP8266HTTPClient.cpp | 4 ++-- libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h | 13 ++++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp index b4f35777fd..539ea60187 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp @@ -562,7 +562,7 @@ bool HTTPClient::setURL(const String& url) */ void HTTPClient::setFollowRedirects(bool follow) { - _followRedirects = follow ? HTTPC_FOLLOW_REDIRECTS : HTTPC_DONT_FOLLOW_REDIRECTS; + _followRedirects = follow ? HTTPC_STRICT_FOLLOW_REDIRECTS : HTTPC_DISABLE_FOLLOW_REDIRECTS; } /** * set redirect follow mode. See `followRedirects_t` enum for avaliable modes. @@ -712,7 +712,7 @@ int HTTPClient::sendRequest(const char * type, const uint8_t * payload, size_t s // to follow most of existing user agent implementations. // if ( - _followRedirects != HTTPC_DONT_FOLLOW_REDIRECTS && + _followRedirects != HTTPC_DISABLE_FOLLOW_REDIRECTS && _redirectCount < _redirectLimit && _location.length() > 0 ) { diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h index ae998ed77f..fb87ee3929 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h @@ -130,9 +130,16 @@ typedef enum { HTTPC_TE_CHUNKED } transferEncoding_t; +/** + * redirection follow mode. + * + `HTTPC_DISABLE_FOLLOW_REDIRECTS` - no redirection will be followed. + * + `HTTPC_STRICT_FOLLOW_REDIRECTS` - strict RFC2616, only requests using + * GET or HEAD methods will be redirected without user confirmation. + * + `HTTPC_FORCE_FOLLOW_REDIRECTS` - all redirections will be followed. + */ typedef enum { - HTTPC_FOLLOW_REDIRECTS, - HTTPC_DONT_FOLLOW_REDIRECTS, + HTTPC_DISABLE_FOLLOW_REDIRECTS, + HTTPC_STRICT_FOLLOW_REDIRECTS, HTTPC_FORCE_FOLLOW_REDIRECTS } followRedirects_t; @@ -262,7 +269,7 @@ class HTTPClient int _returnCode = 0; int _size = -1; bool _canReuse = false; - followRedirects_t _followRedirects = HTTPC_DONT_FOLLOW_REDIRECTS; + followRedirects_t _followRedirects = HTTPC_DISABLE_FOLLOW_REDIRECTS; uint16_t _redirectCount = 0; uint16_t _redirectLimit = 10; String _location; From 15e69a53fef8fc4b689151f189ed226d4ec28d9f Mon Sep 17 00:00:00 2001 From: "Patryk (PsychoX) Ludwikowski" Date: Tue, 17 Mar 2020 13:56:34 +0100 Subject: [PATCH 4/6] Rewrite `sendRequest` to remove recursion Also got rid of unnecessary `redirectCount` field. Now redirect counting and limiting is handled in `sendRequest` directly. --- .../src/ESP8266HTTPClient.cpp | 169 ++++++++++-------- .../ESP8266HTTPClient/src/ESP8266HTTPClient.h | 1 - 2 files changed, 90 insertions(+), 80 deletions(-) diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp index 539ea60187..5212dcf3ee 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp @@ -423,7 +423,6 @@ void HTTPClient::end(void) { disconnect(false); clear(); - _redirectCount = 0; } /** @@ -661,102 +660,114 @@ int HTTPClient::sendRequest(const char * type, const String& payload) */ int HTTPClient::sendRequest(const char * type, const uint8_t * payload, size_t size) { - // wipe out any existing headers from previous request - for(size_t i = 0; i < _headerKeysCount; i++) { - if (_currentHeaders[i].value.length() > 0) { - _currentHeaders[i].value.clear(); + int code; + bool redirect = false; + uint16_t redirectCount = 0; + do { + // wipe out any existing headers from previous request + for(size_t i = 0; i < _headerKeysCount; i++) { + if (_currentHeaders[i].value.length() > 0) { + _currentHeaders[i].value.clear(); + } } - } - DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] type: '%s' redirCount: %d\n", type, _redirectCount); + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] type: '%s' redirCount: %d\n", type, redirectCount); - // connect to server - if(!connect()) { - return returnError(HTTPC_ERROR_CONNECTION_REFUSED); - } + // connect to server + if(!connect()) { + return returnError(HTTPC_ERROR_CONNECTION_REFUSED); + } - addHeader(F("Content-Length"), String(payload && size > 0 ? size : 0)); + addHeader(F("Content-Length"), String(payload && size > 0 ? size : 0)); - // send Header - if(!sendHeader(type)) { - return returnError(HTTPC_ERROR_SEND_HEADER_FAILED); - } + // send Header + if(!sendHeader(type)) { + return returnError(HTTPC_ERROR_SEND_HEADER_FAILED); + } - // send Payload if needed - if (payload && size > 0) { - size_t bytesWritten = 0; - const uint8_t *p = payload; - size_t originalSize = size; - while (bytesWritten < originalSize) { - int written; - int towrite = std::min((int)size, (int)HTTP_TCP_BUFFER_SIZE); - written = _client->write(p + bytesWritten, towrite); - if (written < 0) { - return returnError(HTTPC_ERROR_SEND_PAYLOAD_FAILED); - } else if (written == 0) { - return returnError(HTTPC_ERROR_CONNECTION_LOST); + // send Payload if needed + if (payload && size > 0) { + size_t bytesWritten = 0; + const uint8_t *p = payload; + size_t originalSize = size; + while (bytesWritten < originalSize) { + int written; + int towrite = std::min((int)size, (int)HTTP_TCP_BUFFER_SIZE); + written = _client->write(p + bytesWritten, towrite); + if (written < 0) { + return returnError(HTTPC_ERROR_SEND_PAYLOAD_FAILED); + } else if (written == 0) { + return returnError(HTTPC_ERROR_CONNECTION_LOST); + } + bytesWritten += written; + size -= written; } - bytesWritten += written; - size -= written; } - } - // handle Server Response (Header) - int code = handleHeaderResponse(); - - // - // Handle redirections as stated in RFC document: - // https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html - // - // Implementing HTTP_CODE_FOUND as redirection with GET method, - // to follow most of existing user agent implementations. - // - if ( - _followRedirects != HTTPC_DISABLE_FOLLOW_REDIRECTS && - _redirectCount < _redirectLimit && - _location.length() > 0 - ) { - switch (code) { - // redirecting using the same method - case HTTP_CODE_MOVED_PERMANENTLY: - case HTTP_CODE_TEMPORARY_REDIRECT: { - if ( - // allow to force redirections on other methods - // (the RFC require user to accept the redirection) - _followRedirects == HTTPC_FORCE_FOLLOW_REDIRECTS || - // allow GET and HEAD methods without force - !strcmp(type, "GET") || - !strcmp(type, "HEAD") - ) { - _redirectCount += 1; - DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] following redirect (the same method): '%s' redirCount: %d\n", _location.c_str(), _redirectCount); + // handle Server Response (Header) + code = handleHeaderResponse(); + + // + // Handle redirections as stated in RFC document: + // https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html + // + // Implementing HTTP_CODE_FOUND as redirection with GET method, + // to follow most of existing user agent implementations. + // + redirect = false; + if ( + _followRedirects != HTTPC_DISABLE_FOLLOW_REDIRECTS && + redirectCount < _redirectLimit && + _location.length() > 0 + ) { + switch (code) { + // redirecting using the same method + case HTTP_CODE_MOVED_PERMANENTLY: + case HTTP_CODE_TEMPORARY_REDIRECT: { + if ( + // allow to force redirections on other methods + // (the RFC require user to accept the redirection) + _followRedirects == HTTPC_FORCE_FOLLOW_REDIRECTS || + // allow GET and HEAD methods without force + !strcmp(type, "GET") || + !strcmp(type, "HEAD") + ) { + redirectCount += 1; + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] following redirect (the same method): '%s' redirCount: %d\n", _location.c_str(), redirectCount); + if (!setURL(_location)) { + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] failed setting URL for redirection\n"); + // no redirection + break; + } + // redirect using the same request method and payload, diffrent URL + redirect = true; + } + break; + } + // redirecting with method dropped to GET or HEAD + // note: it does not need `HTTPC_FORCE_FOLLOW_REDIRECTS` for any method + case HTTP_CODE_FOUND: + case HTTP_CODE_SEE_OTHER: { + redirectCount += 1; + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] following redirect (dropped to GET/HEAD): '%s' redirCount: %d\n", _location.c_str(), redirectCount); if (!setURL(_location)) { DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] failed setting URL for redirection\n"); // no redirection break; } - code = sendRequest(type, payload, size); - } - break; - } - // redirecting with method dropped to GET or HEAD - // note: it does not need `HTTPC_FORCE_FOLLOW_REDIRECTS` for any method - case HTTP_CODE_FOUND: - case HTTP_CODE_SEE_OTHER: { - _redirectCount += 1; - DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] following redirect (dropped to GET/HEAD): '%s' redirCount: %d\n", _location.c_str(), _redirectCount); - if (!setURL(_location)) { - DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] failed setting URL for redirection\n"); - // no redirection + // redirect after changing method to GET/HEAD and dropping payload + type = "GET"; + payload = nullptr; + size = 0; + redirect = true; break; } - code = sendRequest("GET"); - } - default: - break; + default: + break; + } } - } + } while (redirect); // handle Server Response (Header) return returnError(code); diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h index fb87ee3929..c6bcf1c673 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h @@ -270,7 +270,6 @@ class HTTPClient int _size = -1; bool _canReuse = false; followRedirects_t _followRedirects = HTTPC_DISABLE_FOLLOW_REDIRECTS; - uint16_t _redirectCount = 0; uint16_t _redirectLimit = 10; String _location; transferEncoding_t _transferEncoding = HTTPC_TE_IDENTITY; From dcbbf4b886eed1c281dc1fbe358d86064283a63d Mon Sep 17 00:00:00 2001 From: "Patryk (PsychoX) Ludwikowski" Date: Tue, 17 Mar 2020 14:26:34 +0100 Subject: [PATCH 5/6] Use new `setFollowRedirects` of `HTTPClient` instead deprecated one. --- .../src/ESP8266httpUpdate.cpp | 4 +-- .../ESP8266httpUpdate/src/ESP8266httpUpdate.h | 17 +++++++++-- .../test_sw_http_client.ino | 29 ++++++++++--------- 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp index 9d56718c15..a7fe1934d2 100755 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp @@ -30,12 +30,12 @@ extern "C" uint32_t _FS_start; extern "C" uint32_t _FS_end; ESP8266HTTPUpdate::ESP8266HTTPUpdate(void) - : _httpClientTimeout(8000), _followRedirects(false), _ledPin(-1) + : _httpClientTimeout(8000), _followRedirects(HTTPC_DISABLE_FOLLOW_REDIRECTS), _ledPin(-1) { } ESP8266HTTPUpdate::ESP8266HTTPUpdate(int httpClientTimeout) - : _httpClientTimeout(httpClientTimeout), _followRedirects(false), _ledPin(-1) + : _httpClientTimeout(httpClientTimeout), _followRedirects(HTTPC_DISABLE_FOLLOW_REDIRECTS), _ledPin(-1) { } diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h index 8d06def9dd..ddbd307ad9 100755 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h @@ -82,7 +82,20 @@ class ESP8266HTTPUpdate _rebootOnUpdate = reboot; } - void followRedirects(bool follow) + /** + * set true to follow redirects. + * @param follow + * @deprecated Please use `setFollowRedirects(followRedirects_t follow)` + */ + void followRedirects(bool follow) __attribute__ ((deprecated)) + { + _followRedirects = follow ? HTTPC_STRICT_FOLLOW_REDIRECTS : HTTPC_DISABLE_FOLLOW_REDIRECTS; + } + /** + * set redirect follow mode. See `followRedirects_t` enum for avaliable modes. + * @param follow + */ + void setFollowRedirects(followRedirects_t follow) { _followRedirects = follow; } @@ -160,7 +173,7 @@ class ESP8266HTTPUpdate bool _closeConnectionsOnUpdate = true; private: int _httpClientTimeout; - bool _followRedirects; + followRedirects_t _followRedirects; // Callbacks HTTPUpdateStartCB _cbStart; diff --git a/tests/device/test_sw_http_client/test_sw_http_client.ino b/tests/device/test_sw_http_client/test_sw_http_client.ino index 6de2314fa8..3e60bf974a 100644 --- a/tests/device/test_sw_http_client/test_sw_http_client.ino +++ b/tests/device/test_sw_http_client/test_sw_http_client.ino @@ -71,10 +71,10 @@ TEST_CASE("HTTP GET & POST requests", "[HTTPClient]") http.end(); } { - // 301 redirect with follow enabled + // GET 301 redirect with strict RFC follow enabled WiFiClient client; HTTPClient http; - http.setFollowRedirects(true); + http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); String uri = String("/redirect301?host=")+getenv("SERVER_IP"); http.begin(client, getenv("SERVER_IP"), 8088, uri.c_str()); auto httpCode = http.GET(); @@ -83,7 +83,7 @@ TEST_CASE("HTTP GET & POST requests", "[HTTPClient]") REQUIRE(payload == "redirect success"); } { - // 301 redirect with follow disabled + // GET 301 redirect with follow disabled WiFiClient client; HTTPClient http; String uri = String("/redirect301?host=")+getenv("SERVER_IP"); @@ -92,10 +92,10 @@ TEST_CASE("HTTP GET & POST requests", "[HTTPClient]") REQUIRE(httpCode == 301); } { - // 302 redirect with follow enabled + // GET 302 redirect with strict RFC follow enabled WiFiClient client; HTTPClient http; - http.setFollowRedirects(true); + http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); String uri = String("/redirect302?host=")+getenv("SERVER_IP"); http.begin(client, getenv("SERVER_IP"), 8088, uri.c_str()); auto httpCode = http.GET(); @@ -104,7 +104,7 @@ TEST_CASE("HTTP GET & POST requests", "[HTTPClient]") REQUIRE(payload == "redirect success"); } { - // 302 redirect with follow disabled + // GET 302 redirect with follow disabled WiFiClient client; HTTPClient http; String uri = String("/redirect302?host=")+getenv("SERVER_IP"); @@ -113,10 +113,10 @@ TEST_CASE("HTTP GET & POST requests", "[HTTPClient]") REQUIRE(httpCode == 302); } { - // 307 redirect with follow enabled + // GET 307 redirect with strict RFC follow enabled WiFiClient client; HTTPClient http; - http.setFollowRedirects(true); + http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); String uri = String("/redirect307?host=")+getenv("SERVER_IP"); http.begin(client, getenv("SERVER_IP"), 8088, uri.c_str()); auto httpCode = http.GET(); @@ -125,7 +125,7 @@ TEST_CASE("HTTP GET & POST requests", "[HTTPClient]") REQUIRE(payload == "redirect success"); } { - // 307 redirect with follow disabled + // GET 307 redirect with follow disabled WiFiClient client; HTTPClient http; String uri = String("/redirect307?host=")+getenv("SERVER_IP"); @@ -134,10 +134,10 @@ TEST_CASE("HTTP GET & POST requests", "[HTTPClient]") REQUIRE(httpCode == 307); } { - // 301 exceeding redirect limit + // GET 301 exceeding redirect limit WiFiClient client; HTTPClient http; - http.setFollowRedirects(true); + http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); http.setRedirectLimit(0); String uri = String("/redirect301?host=")+getenv("SERVER_IP"); http.begin(client, getenv("SERVER_IP"), 8088, uri.c_str()); @@ -145,20 +145,22 @@ TEST_CASE("HTTP GET & POST requests", "[HTTPClient]") REQUIRE(httpCode == 301); } { - // POST 303 redirect with follow enabled + // POST 303 redirect with strict RFC follow enabled WiFiClient client; HTTPClient http; - http.setFollowRedirects(true); + http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); http.begin(client, getenv("SERVER_IP"), 8088, "/redirect303"); auto httpCode = http.POST(getenv("SERVER_IP")); REQUIRE(httpCode == HTTP_CODE_OK); String payload = http.getString(); REQUIRE(payload == "redirect success"); + // TODO: need check for dropping: redirection should use GET method } { // POST 303 redirect with follow disabled WiFiClient client; HTTPClient http; + http.setFollowRedirects(HTTPC_DISABLE_FOLLOW_REDIRECTS); http.begin(client, getenv("SERVER_IP"), 8088, "/redirect303"); auto httpCode = http.POST(getenv("SERVER_IP")); REQUIRE(httpCode == 303); @@ -167,6 +169,7 @@ TEST_CASE("HTTP GET & POST requests", "[HTTPClient]") // 302 redirect with follow disabled WiFiClient client; HTTPClient http; + http.setFollowRedirects(HTTPC_DISABLE_FOLLOW_REDIRECTS); String uri = String("/redirect302?host=")+getenv("SERVER_IP"); http.begin(client, getenv("SERVER_IP"), 8088, uri.c_str()); auto httpCode = http.GET(); From 9510d166e74aaa567804a38ac96857ce05fce30f Mon Sep 17 00:00:00 2001 From: "Patryk (PsychoX) Ludwikowski" Date: Sun, 22 Mar 2020 20:17:06 +0100 Subject: [PATCH 6/6] More explanatory comment for `followRedirects_t` in HTTPClient --- libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h index c6bcf1c673..1ab26c8de7 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h @@ -134,8 +134,12 @@ typedef enum { * redirection follow mode. * + `HTTPC_DISABLE_FOLLOW_REDIRECTS` - no redirection will be followed. * + `HTTPC_STRICT_FOLLOW_REDIRECTS` - strict RFC2616, only requests using - * GET or HEAD methods will be redirected without user confirmation. - * + `HTTPC_FORCE_FOLLOW_REDIRECTS` - all redirections will be followed. + * GET or HEAD methods will be redirected (using the same method), + * since the RFC requires end-user confirmation in other cases. + * + `HTTPC_FORCE_FOLLOW_REDIRECTS` - all redirections will be followed, + * regardless of a used method. New request will use the same method, + * and they will include the same body data and the same headers. + * In the sense of the RFC, it's just like every redirection is confirmed. */ typedef enum { HTTPC_DISABLE_FOLLOW_REDIRECTS,