[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, trigger,
[ [
(cg.std_shared_ptr.template(HttpContainer), "response"), (cg.std_shared_ptr.template(HttpContainer), "response"),
(cg.std_string_ref, "body"), (cg.std_shared_ptr.template(cg.std_string), "body"),
], ],
conf, conf,
) )

View File

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

View File

@ -21,6 +21,24 @@ esphome:
args: args:
- response->status_code - response->status_code
- (long) response->duration_ms - (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: - http_request.post:
url: https://esphome.io url: https://esphome.io
headers: headers: