| 114 | } |
| 115 | |
| 116 | TSRemapStatus |
| 117 | TSRemapDoRemap(void *ih, TSHttpTxn rh ATS_UNUSED, TSRemapRequestInfo *rri) |
| 118 | { |
| 119 | query_remap_info *qri = static_cast<query_remap_info *>(ih); |
| 120 | |
| 121 | if (!qri || !rri) { |
| 122 | TSError("[%s] null private data or RRI", PLUGIN_NAME); |
| 123 | return TSREMAP_NO_REMAP; |
| 124 | } |
| 125 | |
| 126 | int req_query_len; |
| 127 | const char *req_query = TSUrlHttpQueryGet(rri->requestBufp, rri->requestUrl, &req_query_len); |
| 128 | |
| 129 | if (req_query && req_query_len > 0) { |
| 130 | char *q, *key; |
| 131 | char *s = nullptr; |
| 132 | int hostidx = -1; |
| 133 | |
| 134 | /* make a copy of the query, as it is read only */ |
| 135 | q = TSstrndup(req_query, req_query_len + 1); |
| 136 | |
| 137 | /* parse query parameters */ |
| 138 | for (key = strtok_r(q, "&", &s); key != nullptr;) { |
| 139 | char *val = strchr(key, '='); |
| 140 | if (val && static_cast<size_t>(val - key) == qri->param_len && !strncmp(key, qri->param_name, qri->param_len)) { |
| 141 | ++val; |
| 142 | /* the param key matched the configured param_name |
| 143 | hash the param value to pick a host */ |
| 144 | hostidx = hash_fnv32(val, strlen(val)) % static_cast<uint32_t>(qri->num_hosts); |
| 145 | Dbg(dbg_ctl, "modifying host based on %s", key); |
| 146 | break; |
| 147 | } |
| 148 | key = strtok_r(nullptr, "&", &s); |
| 149 | } |
| 150 | |
| 151 | TSfree(q); |
| 152 | |
| 153 | if (hostidx >= 0) { |
| 154 | int req_host_len; |
| 155 | /* TODO: Perhaps use dbg_ctl.on() before calling TSUrlHostGet()... */ |
| 156 | const char *req_host = TSUrlHostGet(rri->requestBufp, rri->requestUrl, &req_host_len); |
| 157 | |
| 158 | if (TSUrlHostSet(rri->requestBufp, rri->requestUrl, qri->hosts[hostidx], strlen(qri->hosts[hostidx])) != TS_SUCCESS) { |
| 159 | Dbg(dbg_ctl, "Failed to modify the Host in request URL"); |
| 160 | return TSREMAP_NO_REMAP; |
| 161 | } |
| 162 | Dbg(dbg_ctl, "host changed from [%.*s] to [%s]", req_host_len, req_host, qri->hosts[hostidx]); |
| 163 | return TSREMAP_DID_REMAP; /* host has been modified */ |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | /* the request was not modified, TS will use the toURL from the remap rule */ |
| 168 | Dbg(dbg_ctl, "request not modified"); |
| 169 | return TSREMAP_NO_REMAP; |
| 170 | } |
| 171 | |
| 172 | /* FNV (Fowler/Noll/Vo) hash |
| 173 | (description: http://www.isthe.com/chongo/tech/comp/fnv/index.html) */ |
nothing calls this directly
no test coverage detected