A rule sends http://reports.example:80/ through a proxy but lets http://reports.example/ go direct. Those URLs describe the same ordinary HTTP endpoint. The mismatch usually comes from comparing their parsed ports literally.

URI.getPort() returns -1 when no port appears in the URI. It does not substitute the default for the scheme. A routing policy that compares the value with 80 will miss the second URL.

String scheme = uri.getScheme();
int port = uri.getPort();
if (port == -1) {
    if ("http".equalsIgnoreCase(scheme)) port = 80;
    else if ("https".equalsIgnoreCase(scheme)) port = 443;
}

Apply the same normalization to both sides of the comparison. Fixing only the request URI still leaves a configured destination with an omitted port unmatched. Compare the host, effective port and intended scheme; reject malformed or hostless destinations through a defined error path.

Do not turn every callback into an HTTP decision

A default selector can also be consulted for raw socket connections, using the socket scheme. A host-and-port match alone must not cause that callback to return an HTTP proxy intended for URL requests. Delegate unsupported schemes to the previous selector, preserving its appropriate behavior.

Capture that previous selector before installing your custom one. Looking up the current default from inside the replacement can simply call the replacement again.

Log the scheme, host, original port and effective port when diagnosing a mismatch. Do not depend on one observed number or order of callbacks across JDK implementations. The policy should make a correct decision for each supplied URI.

འབྲེལ་བའི་རྩོམ་ཡིག