Line data Source code
1 : #include "response_observer.hpp"
2 : #include "request.hpp"
3 : #include "../../util/logger.hpp"
4 :
5 : namespace thinger::http {
6 :
7 1170 : response_observer::response_observer(std::shared_ptr<request> req, std::shared_ptr<const response_hook> hook)
8 1170 : : request_(std::move(req)), hook_(std::move(hook)) {
9 1170 : request_->set_peer_ip(request_->get_peer_ip());
10 1170 : }
11 :
12 1459 : response_observer::~response_observer() {
13 1170 : if (reported_) return;
14 289 : if (!ended_) {
15 289 : info_.outcome = response_outcome::aborted;
16 289 : info_.duration = std::chrono::steady_clock::now() - start_;
17 : }
18 289 : report();
19 2932 : }
20 :
21 884 : void response_observer::head(http_response::status status, bool streamed) {
22 : // The last head is the response that ends (e.g. the 502 replacing a stream aborted in memory)
23 884 : info_.status = status;
24 884 : info_.streamed = streamed;
25 884 : }
26 :
27 881 : void response_observer::ended(response_outcome outcome) {
28 881 : if (ended_) return;
29 881 : ended_ = true;
30 881 : info_.outcome = aborted_.load(std::memory_order_relaxed) ? response_outcome::aborted : outcome;
31 881 : info_.duration = std::chrono::steady_clock::now() - start_;
32 881 : done();
33 : }
34 :
35 1170 : void response_observer::handled() {
36 1170 : if (handled_) return;
37 1170 : handled_ = true;
38 1170 : done();
39 : }
40 :
41 2051 : void response_observer::done() {
42 : // What each side wrote is seen by the one reporting
43 4102 : if (pending_.fetch_sub(1, std::memory_order_acq_rel) == 1) report();
44 2051 : }
45 :
46 1170 : void response_observer::report() noexcept {
47 1170 : reported_ = true;
48 : try {
49 1170 : (*hook_)(*request_, info_);
50 6 : } catch (const std::exception& e) {
51 6 : LOG_ERROR("error in the response hook: {}", e.what());
52 6 : } catch (...) {
53 0 : LOG_ERROR("unknown error in the response hook");
54 0 : }
55 1170 : if (on_reported_) on_reported_();
56 1170 : }
57 :
58 : } // namespace thinger::http
|