Strip credentials (a "user:pass@" userinfo) and any query/fragment from a URL so it can be safely shown in error messages and written to the log. The real URL is still used for the connection; this is purely for display. Best-effort string surgery, deliberately not a full URL parser.
| 59 | // URL is still used for the connection; this is purely for display. Best-effort |
| 60 | // string surgery, deliberately not a full URL parser. |
| 61 | std::string SanitizeUrlForDisplay(const std::string& url) |
| 62 | { |
| 63 | std::string result = url; |
| 64 | |
| 65 | // Drop query and fragment (an API key is sometimes pasted as ?key=...). |
| 66 | if (const auto cut = result.find_first_of("?#"); cut != std::string::npos) |
| 67 | result.erase(cut); |
| 68 | |
| 69 | // Drop userinfo: anything between "://" and the next "@" within the authority. |
| 70 | if (const auto schemeEnd = result.find("://"); schemeEnd != std::string::npos) |
| 71 | { |
| 72 | const auto authStart = schemeEnd + 3; |
| 73 | const auto authEnd = result.find('/', authStart); |
| 74 | const auto at = result.find('@', authStart); |
| 75 | |
| 76 | if (at != std::string::npos && (authEnd == std::string::npos || at < authEnd)) |
| 77 | result.erase(authStart, at - authStart + 1); |
| 78 | } |
| 79 | |
| 80 | return result; |
| 81 | } |
| 82 | |
| 83 | // Stable sentinel used to recognize a lost remote connection. We raise it |
| 84 | // ourselves (see WrapInRemoteGuard) after a type-based catch, so detection |
no test coverage detected