[http_request] on_response body must be owned, use shared_ptr instead of reference

This commit is contained in:
Kjell Braden 2024-12-05 11:00:22 +01:00
parent acc8d24a32
commit 55df921208
3 changed files with 35 additions and 17 deletions

View File

@ -276,7 +276,7 @@ async def http_request_action_to_code(config, action_id, template_arg, args):
trigger,
[
(cg.std_shared_ptr.template(HttpContainer), "response"),
(cg.std_string_ref, "body"),
(cg.std_shared_ptr.template(cg.std_string), "body"),
],
conf,
)

View File

@ -100,10 +100,10 @@ class HttpContainer : public Parented<HttpRequestComponent> {
bool secure_{false};
};
class HttpRequestResponseTrigger : public Trigger<std::shared_ptr<HttpContainer>, std::string &> {
class HttpRequestResponseTrigger : public Trigger<std::shared_ptr<HttpContainer>, std::shared_ptr<std::string>> {
public:
void process(std::shared_ptr<HttpContainer> container, std::string &response_body) {
this->trigger(std::move(container), response_body);
void process(std::shared_ptr<HttpContainer> container, std::shared_ptr<std::string> response_body) {
this->trigger(std::move(container), std::move(response_body));
}
};
@ -196,7 +196,7 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
size_t content_length = container->content_length;
size_t max_length = std::min(content_length, this->max_response_buffer_size_);
std::string response_body;
std::shared_ptr<std::string> response_body;
if (this->capture_response_.value(x...)) {
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
uint8_t *buf = allocator.allocate(max_length);
@ -208,23 +208,23 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
yield();
read_index += read;
}
response_body.reserve(read_index);
response_body.assign((char *) buf, read_index);
response_body = std::make_shared<std::string>((char *) buf, read_index);
allocator.deallocate(buf, max_length);
}
}
if (this->response_triggers_.size() == 1) {
// if there is only one trigger, no need to copy the response body
this->response_triggers_[0]->process(container, response_body);
} else {
for (auto *trigger : this->response_triggers_) {
// with multiple triggers, pass a copy of the response body to each
// one so that modifications made in one trigger are not visible to
// the others
auto response_body_copy = std::string(response_body);
trigger->process(container, response_body_copy);
size_t index = 0u;
auto num_triggers = this->response_triggers_.size();
for (auto *trigger : this->response_triggers_) {
// pass a copy of the response body to each trigger so that modifications
// made in one trigger are not visible to the others. Re-use the original
// response body for the last trigger.
std::shared_ptr<std::string> response_body_copy{response_body};
if (response_body && index != num_triggers - 1) {
response_body_copy = std::make_shared<std::string>(*response_body);
}
trigger->process(container, response_body_copy);
index++;
}
container->end();
}

View File

@ -21,6 +21,24 @@ esphome:
args:
- response->status_code
- (long) response->duration_ms
# regression test for http://github.com/esphome/issues/issues/5987s
- wait_until:
not:
wifi.connected:
- repeat:
count: 3
then:
- logger.log: "got response :-)"
- while:
condition:
not:
wifi.connected:
then:
- logger.log: "still offline"
- http_request.post:
url: https://esphome.io
headers: