///////////////////////////////////////////////////////////////////////////////////// Main continuation for the plugin, examining an origin response for a potential retry.
| 96 | // Main continuation for the plugin, examining an origin response for a potential retry. |
| 97 | // |
| 98 | static int |
| 99 | EscalateResponse(TSCont cont, TSEvent event, void *edata) |
| 100 | { |
| 101 | TSHttpTxn txn = static_cast<TSHttpTxn>(edata); |
| 102 | EscalationState *es = static_cast<EscalationState *>(TSContDataGet(cont)); |
| 103 | TSMBuffer mbuf; |
| 104 | TSMLoc hdrp, url; |
| 105 | |
| 106 | TSAssert(event == TS_EVENT_HTTP_READ_RESPONSE_HDR || event == TS_EVENT_HTTP_SEND_RESPONSE_HDR); |
| 107 | bool const processing_connection_error = (event == TS_EVENT_HTTP_SEND_RESPONSE_HDR); |
| 108 | |
| 109 | if (processing_connection_error) { |
| 110 | TSServerState const state = TSHttpTxnServerStateGet(txn); |
| 111 | if (state == TS_SRVSTATE_CONNECTION_ALIVE) { |
| 112 | // There is no connection error, so nothing to do. |
| 113 | TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE); |
| 114 | return TS_EVENT_NONE; |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | int const tries = TSHttpTxnRedirectRetries(txn); |
| 119 | if (0 != tries) { // ToDo: Future support for more than one retry-URL |
| 120 | Dbg(dbg_ctl, "Not pursuing failover due previous redirect already, num tries: %d", tries); |
| 121 | TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE); |
| 122 | return TS_EVENT_NONE; |
| 123 | } |
| 124 | |
| 125 | int ret = 0; |
| 126 | if (processing_connection_error) { |
| 127 | ret = TSHttpTxnClientRespGet(txn, &mbuf, &hdrp); |
| 128 | } else { |
| 129 | ret = TSHttpTxnServerRespGet(txn, &mbuf, &hdrp); |
| 130 | } |
| 131 | if (TS_SUCCESS != ret) { |
| 132 | TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE); |
| 133 | return TS_EVENT_NONE; |
| 134 | } |
| 135 | |
| 136 | // Next, the response status ... |
| 137 | TSHttpStatus const status = TSHttpHdrStatusGet(mbuf, hdrp); |
| 138 | TSHandleMLocRelease(mbuf, TS_NULL_MLOC, hdrp); |
| 139 | |
| 140 | // See if we have an escalation retry config for this response code. |
| 141 | auto const entry = es->status_map.find(status); |
| 142 | if (entry == es->status_map.end()) { |
| 143 | TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE); |
| 144 | return TS_EVENT_NONE; |
| 145 | } |
| 146 | EscalationState::RetryInfo const &retry_info = entry->second; |
| 147 | |
| 148 | Dbg(dbg_ctl, "Handling failover redirect for HTTP status %d", status); |
| 149 | char const *url_str = nullptr; |
| 150 | int url_len = 0; |
| 151 | if (EscalationState::RETRY_URL == retry_info.type) { |
| 152 | url_str = TSstrdup(retry_info.target.c_str()); |
| 153 | url_len = retry_info.target.size(); |
| 154 | Dbg(dbg_ctl, "Setting new URL to %.*s", url_len, url_str); |
| 155 | } else if (EscalationState::RETRY_HOST == retry_info.type) { |
nothing calls this directly
no test coverage detected