From 6e863305aae0589103fa9dfdf2d36d2ff50858c9 Mon Sep 17 00:00:00 2001
From: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Date: Tue, 23 Jul 2024 13:51:32 +1200
Subject: [PATCH 1/3] [http_request] Change default timeout to 4.5s (#7123)

---
 esphome/components/http_request/__init__.py    | 2 +-
 esphome/components/http_request/http_request.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py
index ade7024bed..ef387553fe 100644
--- a/esphome/components/http_request/__init__.py
+++ b/esphome/components/http_request/__init__.py
@@ -99,7 +99,7 @@ CONFIG_SCHEMA = cv.All(
             cv.Optional(CONF_FOLLOW_REDIRECTS, True): cv.boolean,
             cv.Optional(CONF_REDIRECT_LIMIT, 3): cv.int_,
             cv.Optional(
-                CONF_TIMEOUT, default="5s"
+                CONF_TIMEOUT, default="4.5s"
             ): cv.positive_time_period_milliseconds,
             cv.SplitDefault(CONF_ESP8266_DISABLE_SSL_SUPPORT, esp8266=False): cv.All(
                 cv.only_on_esp8266, cv.boolean
diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h
index 82b7392648..c01baf8644 100644
--- a/esphome/components/http_request/http_request.h
+++ b/esphome/components/http_request/http_request.h
@@ -80,7 +80,7 @@ class HttpRequestComponent : public Component {
   const char *useragent_{nullptr};
   bool follow_redirects_;
   uint16_t redirect_limit_;
-  uint16_t timeout_{5000};
+  uint16_t timeout_{4500};
   uint32_t watchdog_timeout_{0};
 };
 

From 7c24f1ba6dac36d839c5fe34f16d6b52f12264da Mon Sep 17 00:00:00 2001
From: dentra <dentra@users.noreply.github.com>
Date: Wed, 24 Jul 2024 03:12:59 +0300
Subject: [PATCH 2/3] [http_request] Fix ESP-IDF follow redirect (#7101)

---
 esphome/components/http_request/__init__.py   | 14 ++--
 .../http_request/http_request_idf.cpp         | 66 +++++++++++++++----
 2 files changed, 62 insertions(+), 18 deletions(-)

diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py
index ef387553fe..161486fbb2 100644
--- a/esphome/components/http_request/__init__.py
+++ b/esphome/components/http_request/__init__.py
@@ -1,17 +1,17 @@
-import esphome.codegen as cg
-import esphome.config_validation as cv
 from esphome import automation
+import esphome.codegen as cg
+from esphome.components import esp32
+import esphome.config_validation as cv
 from esphome.const import (
-    __version__,
+    CONF_ESP8266_DISABLE_SSL_SUPPORT,
     CONF_ID,
-    CONF_TIMEOUT,
     CONF_METHOD,
+    CONF_TIMEOUT,
     CONF_TRIGGER_ID,
     CONF_URL,
-    CONF_ESP8266_DISABLE_SSL_SUPPORT,
+    __version__,
 )
-from esphome.core import Lambda, CORE
-from esphome.components import esp32
+from esphome.core import CORE, Lambda
 
 DEPENDENCIES = ["network"]
 AUTO_LOAD = ["json"]
diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp
index 68e0639b99..1f03b5f3bf 100644
--- a/esphome/components/http_request/http_request_idf.cpp
+++ b/esphome/components/http_request/http_request_idf.cpp
@@ -77,7 +77,7 @@ std::shared_ptr<HttpContainer> HttpRequestIDF::start(std::string url, std::strin
     esp_http_client_set_header(client, header.name, header.value);
   }
 
-  int body_len = body.length();
+  const int body_len = body.length();
 
   esp_err_t err = esp_http_client_open(client, body_len);
   if (err != ESP_OK) {
@@ -109,18 +109,62 @@ std::shared_ptr<HttpContainer> HttpRequestIDF::start(std::string url, std::strin
     return nullptr;
   }
 
-  container->content_length = esp_http_client_fetch_headers(client);
-  const auto status_code = esp_http_client_get_status_code(client);
-  container->status_code = status_code;
+  auto is_ok = [](int code) { return code >= HttpStatus_Ok && code < HttpStatus_MultipleChoices; };
 
-  if (status_code < 200 || status_code >= 300) {
-    ESP_LOGE(TAG, "HTTP Request failed; URL: %s; Code: %d", url.c_str(), status_code);
-    this->status_momentary_error("failed", 1000);
-    esp_http_client_cleanup(client);
-    return nullptr;
+  container->content_length = esp_http_client_fetch_headers(client);
+  container->status_code = esp_http_client_get_status_code(client);
+  if (is_ok(container->status_code)) {
+    container->duration_ms = millis() - start;
+    return container;
   }
-  container->duration_ms = millis() - start;
-  return container;
+
+  if (this->follow_redirects_) {
+    auto is_redirect = [](int code) {
+      return code == HttpStatus_MovedPermanently || code == HttpStatus_Found || code == HttpStatus_SeeOther ||
+             code == HttpStatus_TemporaryRedirect || code == HttpStatus_PermanentRedirect;
+    };
+    auto num_redirects = this->redirect_limit_;
+    while (is_redirect(container->status_code) && num_redirects > 0) {
+      err = esp_http_client_set_redirection(client);
+      if (err != ESP_OK) {
+        ESP_LOGE(TAG, "esp_http_client_set_redirection failed: %s", esp_err_to_name(err));
+        this->status_momentary_error("failed", 1000);
+        esp_http_client_cleanup(client);
+        return nullptr;
+      }
+#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
+      char url[256]{};
+      if (esp_http_client_get_url(client, url, sizeof(url) - 1) == ESP_OK) {
+        ESP_LOGV(TAG, "redirecting to url: %s", url);
+      }
+#endif
+      err = esp_http_client_open(client, 0);
+      if (err != ESP_OK) {
+        ESP_LOGE(TAG, "esp_http_client_open failed: %s", esp_err_to_name(err));
+        this->status_momentary_error("failed", 1000);
+        esp_http_client_cleanup(client);
+        return nullptr;
+      }
+
+      container->content_length = esp_http_client_fetch_headers(client);
+      container->status_code = esp_http_client_get_status_code(client);
+      if (is_ok(container->status_code)) {
+        container->duration_ms = millis() - start;
+        return container;
+      }
+
+      num_redirects--;
+    }
+
+    if (num_redirects == 0) {
+      ESP_LOGW(TAG, "Reach redirect limit count=%d", this->redirect_limit_);
+    }
+  }
+
+  ESP_LOGE(TAG, "HTTP Request failed; URL: %s; Code: %d", url.c_str(), container->status_code);
+  this->status_momentary_error("failed", 1000);
+  esp_http_client_cleanup(client);
+  return nullptr;
 }
 
 int HttpContainerIDF::read(uint8_t *buf, size_t max_len) {

From ad0118dd4a47f1566ee6146d69004957d5555d12 Mon Sep 17 00:00:00 2001
From: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Date: Thu, 25 Jul 2024 09:13:05 +1200
Subject: [PATCH 3/3] Bump version to 2024.7.2

---
 esphome/const.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/esphome/const.py b/esphome/const.py
index ff5f7b699d..9abfafc4a4 100644
--- a/esphome/const.py
+++ b/esphome/const.py
@@ -1,6 +1,6 @@
 """Constants used by esphome."""
 
-__version__ = "2024.7.1"
+__version__ = "2024.7.2"
 
 ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
 VALID_SUBSTITUTIONS_CHARACTERS = (