Skip to content

Commit

Permalink
[JENKINS-42191] Enhance CLI HTTP proxy support (#2711)
Browse files Browse the repository at this point in the history
* Enhance CLI HTTP proxy support

Fix few issues around proxy support in CLI:

* make proxy support work with recent Squid version which reply with HTTP/1.1 even if request is HTTP 1.0
* close the socket connected to the proxy if the connection failed
* output an error message when proxy connection failed
* don't do a reverse DNS lookup, instead use the host string provided in X-Jenkins-CLI-Host headers (we don't know if the DNS resolver on the
proxy will be able to resolve the name correctly, or like us).

* Use stdout to output CLI proxy connection error message

* Use the logger to output the error message, not System.out

* Add a 'verbose' option to the CLI to turn logging on

This should help people diagnosing connection issues with the CLI.

* [JENKINS-42191] Set log level to FINEST when -v is passed
  • Loading branch information
ydubreuil authored and oleg-nenashev committed Mar 17, 2017
1 parent 255acda commit 1b3121d
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 9 deletions.
34 changes: 25 additions & 9 deletions cli/src/main/java/hudson/cli/CLI.java
Expand Up @@ -72,6 +72,8 @@
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import static java.util.logging.Level.*;
Expand Down Expand Up @@ -177,9 +179,10 @@ private Channel connectViaCliPort(URL jenkins, CliPort clip) throws IOException

if (httpsProxyTunnel!=null) {
String[] tokens = httpsProxyTunnel.split(":");
LOGGER.log(Level.FINE, "Using HTTP proxy {0}:{1} to connect to CLI port", new Object[]{tokens[0], tokens[1]});
s.connect(new InetSocketAddress(tokens[0], Integer.parseInt(tokens[1])));
PrintStream o = new PrintStream(s.getOutputStream());
o.print("CONNECT " + clip.endpoint.getHostName() + ":" + clip.endpoint.getPort() + " HTTP/1.0\r\n\r\n");
o.print("CONNECT " + clip.endpoint.getHostString() + ":" + clip.endpoint.getPort() + " HTTP/1.0\r\n\r\n");

// read the response from the proxy
ByteArrayOutputStream rsp = new ByteArrayOutputStream();
Expand All @@ -189,8 +192,11 @@ private Channel connectViaCliPort(URL jenkins, CliPort clip) throws IOException
rsp.write(ch);
}
String head = new BufferedReader(new StringReader(rsp.toString("ISO-8859-1"))).readLine();
if (!head.startsWith("HTTP/1.0 200 "))
throw new IOException("Failed to establish a connection through HTTP proxy: "+rsp);
if (!(head.startsWith("HTTP/1.0 200 ") || head.startsWith("HTTP/1.1 200 "))) {
s.close();
LOGGER.log(Level.SEVERE, "Failed to tunnel the CLI port through the HTTP proxy. Falling back to HTTP.");
throw new IOException("Failed to establish a connection through HTTP proxy: " + rsp);
}

// HTTP proxies (at least the one I tried --- squid) doesn't seem to do half-close very well.
// So instead of relying on it, we'll just send the close command and then let the server
Expand Down Expand Up @@ -375,12 +381,12 @@ public void upgrade() {
}

public static void main(final String[] _args) throws Exception {
// Logger l = Logger.getLogger(Channel.class.getName());
// l.setLevel(ALL);
// ConsoleHandler h = new ConsoleHandler();
// h.setLevel(ALL);
// l.addHandler(h);
//
Logger l = Logger.getLogger(ROOT_LOGGER_NAME);
l.setLevel(SEVERE);
ConsoleHandler h = new ConsoleHandler();
h.setLevel(SEVERE);
l.addHandler(h);

try {
System.exit(_main(_args));
} catch (Throwable t) {
Expand Down Expand Up @@ -451,6 +457,15 @@ public boolean verify(String s, SSLSession sslSession) {
args = args.subList(2,args.size());
continue;
}
if(head.equals("-v")) {
args = args.subList(1,args.size());
Logger l = Logger.getLogger(ROOT_LOGGER_NAME);
l.setLevel(FINEST);
for (Handler h : l.getHandlers()) {
h.setLevel(FINEST);
}
continue;
}
break;
}

Expand Down Expand Up @@ -587,4 +602,5 @@ private static void printUsage(String msg) {
}

private static final Logger LOGGER = Logger.getLogger(CLI.class.getName());
private static final String ROOT_LOGGER_NAME = CLI.class.getPackage().getName();
}
Expand Up @@ -6,6 +6,7 @@ CLI.Usage=Jenkins CLI\n\
-p HOST:PORT : HTTP proxy host and port for HTTPS proxy tunneling. See https://jenkins.io/redirect/cli-https-proxy-tunnel\n\
-noCertificateCheck : bypass HTTPS certificate check entirely. Use with caution\n\
-noKeyAuth : don't try to load the SSH authentication private key. Conflicts with -i\n\
-v : verbose output. Display logs on the console by setting j.u.l log level to FINEST\n\
\n\
The available commands depend on the server. Run the 'help' command to\n\
see the list.
Expand Down

0 comments on commit 1b3121d

Please sign in to comment.