| 4428 | } |
| 4429 | |
| 4430 | void |
| 4431 | HttpSM::do_remap_request(bool run_inline) |
| 4432 | { |
| 4433 | SMDbg(dbg_ctl_http_seq, "Remapping request"); |
| 4434 | SMDbg(dbg_ctl_url_rewrite, "Starting a possible remapping for request"); |
| 4435 | bool ret = remapProcessor.setup_for_remap(&t_state, m_remap); |
| 4436 | |
| 4437 | check_sni_host(); |
| 4438 | |
| 4439 | // Depending on a variety of factors the HOST field may or may not have been promoted to the |
| 4440 | // client request URL. The unmapped URL should always have that promotion done. If the HOST field |
| 4441 | // is not already there, promote it only in the unmapped_url. This avoids breaking any logic that |
| 4442 | // depends on the lack of promotion in the client request URL. |
| 4443 | if (!t_state.unmapped_url.m_url_impl->m_ptr_host) { |
| 4444 | MIMEField *host_field = t_state.hdr_info.client_request.field_find(MIME_FIELD_HOST, MIME_LEN_HOST); |
| 4445 | if (host_field) { |
| 4446 | auto host_name{host_field->value_get()}; |
| 4447 | if (!host_name.empty()) { |
| 4448 | int port = -1; |
| 4449 | // Host header can contain port number, and if it does we need to set host and port separately to unmapped_url. |
| 4450 | // If header value starts with '[', the value must contain an IPv6 address, and it may contain a port number as well. |
| 4451 | if (host_name.starts_with("["sv)) { // IPv6 |
| 4452 | host_name.remove_prefix(1); // Skip '[' |
| 4453 | // If header value ends with ']', the value must only contain an IPv6 address (no port number). |
| 4454 | if (host_name.ends_with("]"sv)) { // Without port number |
| 4455 | host_name.remove_suffix(1); // Exclude ']' |
| 4456 | } else { // With port number |
| 4457 | for (int idx = host_name.length() - 1; idx > 0; idx--) { |
| 4458 | if (host_name[idx] == ':') { |
| 4459 | port = ink_atoi(host_name.data() + idx + 1, host_name.length() - (idx + 1)); |
| 4460 | host_name = host_name.substr(0, idx); |
| 4461 | break; |
| 4462 | } |
| 4463 | } |
| 4464 | } |
| 4465 | } else { // Anything else (Hostname or IPv4 address) |
| 4466 | // If the value contains ':' where it does not have IPv6 address, there must be port number |
| 4467 | if (const char *colon = static_cast<const char *>(memchr(host_name.data(), ':', host_name.length())); |
| 4468 | colon == nullptr) { // Without port number |
| 4469 | // Nothing to adjust. Entire value should be used as hostname. |
| 4470 | } else { // With port number |
| 4471 | port = ink_atoi(colon + 1, host_name.length() - ((colon + 1) - host_name.data())); |
| 4472 | host_name = host_name.substr(0, colon - host_name.data()); |
| 4473 | } |
| 4474 | } |
| 4475 | |
| 4476 | // Set values |
| 4477 | t_state.unmapped_url.host_set(host_name.data(), host_name.length()); |
| 4478 | if (port >= 0) { |
| 4479 | t_state.unmapped_url.port_set(port); |
| 4480 | } |
| 4481 | } |
| 4482 | } |
| 4483 | } |
| 4484 | |
| 4485 | if (!ret) { |
| 4486 | SMDbg(dbg_ctl_url_rewrite, "Could not find a valid remapping entry for this request"); |
| 4487 | Metrics::Counter::increment(http_rsb.no_remap_matched); |
nothing calls this directly
no test coverage detected