19

Question: How do I add a authorization proxy to OkHTTP.

I know that OkHTTP's builder does support proxies although I am having a hard time setting one up.

/**
 * Given a Url and a base64 encoded password return the contents of a website.
 * @param urlString
 * @param password
 * @return JSON
 */
public String getURLJson(String urlString, String password) {       
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .build();

        Request request = new Request.Builder()
          .url(urlString)
          .get()
          .addHeader("authorization", "Basic " + password)
          .addHeader("cache-control", "no-cache")
          .build();

        Response response = null;
        try {
            response = client.newCall(request).execute();
            String string = response.body().string();
            response.body().close();
            return string;
        } catch (IOException e) {
            System.err.println("Failed scraping");
            e.printStackTrace();
        }
        return "failed";
    }

I have the IP / port / username / password.

Although I do not know how to turn those into a Proxy proxy which can then be used in client.SetProxy().

It seems overly complicated and I simply can't seem to figure it out. Any help would be appreciated.

Liably
  • 327
  • 1
  • 2
  • 14

1 Answers1

49

Try this:

int proxyPort = 8080;
String proxyHost = "proxyHost";
final String username = "username";
final String password = "password";

Authenticator proxyAuthenticator = new Authenticator() {
  @Override public Request authenticate(Route route, Response response) throws IOException {
       String credential = Credentials.basic(username, password);
       return response.request().newBuilder()
           .header("Proxy-Authorization", credential)
           .build();
  }
};

OkHttpClient client = new OkHttpClient.Builder()
    .connectTimeout(60, TimeUnit.SECONDS)
    .writeTimeout(60, TimeUnit.SECONDS)
    .readTimeout(60, TimeUnit.SECONDS)
    .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)))
    .proxyAuthenticator(proxyAuthenticator)
    .build();
Jesse Wilson
  • 39,078
  • 8
  • 121
  • 128
  • 1
    It doesn't seem to authenticate the proxy. I've managed to get it to work with a command line `curl -x user:passS@proxy:port address` with these details although yours aove does not seem to authenticate. I get the error message `Access Denied (authentication_failed)` – Liably Feb 23 '16 at 14:33
  • 1
    What HTTP response code? With the proxy authenticator OkHttp should retry to reauthenticate the proxy before surfacing that error to the caller. – Jesse Wilson Feb 24 '16 at 03:02
  • 4
    For me is not working too. I always get the return 407 Proxy Authentication Required. And the curl are working. – Robinho Aug 06 '17 at 14:53
  • FYI the code throws `java.lang.RuntimeException: java.net.ProtocolException: Too many follow-up requests: 21` when the username and password is incorrect. Tried and tested, it works. See https://github.com/http-builder-ng/http-builder-ng/issues/191 for my code snippet. – Raviteja Mar 12 '18 at 16:52
  • 1
    @JesseWilson The solution with the `Authenticator` works for me (using okhttp 4.3.0). Thanks. But when I add the `Proxy-Authorization` header manually via the `Request.Builder` then it does not work. I double checked with curl that the header I use is correct. Does okhttp do some magic internally which is not obvious? It's not a problem, but would be interesting to know. – ss1 May 28 '20 at 11:49
  • When you add it to the Request.Builder, that data goes to the webserver, not the proxy. There’s two different requests here; one for the proxy and another for the webserver. – Jesse Wilson May 29 '20 at 15:32