読者です 読者をやめる 読者になる 読者になる

commons-http-clientでホストによってプロキシを変える方法

今開発しているアプリはタブレットからインターネット上の自社サーバーと顧客のイントラネット上のサーバーと2ヶ所にアクセスするという仕様のため、通信するサーバーによって違うプロキシを使いたいという要望がありそうということでプロキシをターゲットホスト毎に変更する方法。メモ。

ポイントはHttpRoutePlanner#determineRouteで接続先についての経路を尋ねられるので、プロキシの経路(HttpRoute)を作成して返してやる。
ハマりどころは、HttpHostは、デフォルトポートのURL(http://www.example.comなどポートの指定がない)だとequalsで失敗するので、HttpHostの正規化を行う。

  DefaultHttpClient httpClient = new DefaultHttpClient();
  HttpRoutePlanner routeplan = new HttpRoutePlanner() {
   HashMap<HttpHost, HttpHost> routes = new HashMap<HttpHost, HttpHost>();
   public void addProxy(HttpHost target, HttpHost proxy){
    System.out.println(target);
    routes.put(target, proxy);
   }

   @Override
   public HttpRoute determineRoute(HttpHost host, HttpRequest req, HttpContext context) throws HttpException {
    
    SchemeRegistry schemereg = (SchemeRegistry)context.getAttribute(ClientContext.SCHEME_REGISTRY);
    HttpHost normalized = host;
    if(host.getPort() < 0){
     Scheme scheme = schemereg.get(host.getSchemeName());
     int port = scheme.getDefaultPort();
     normalized = new HttpHost(host.getHostName(), port, host.getSchemeName());
    }
    
    
    HttpRoute route = null;
    boolean secure = normalized.getSchemeName().equals("https");
    if(routes.containsKey(normalized)){
     route = new HttpRoute(host, null, routes.get(normalized), secure);
    }else{
     route = new HttpRoute(host, null, secure);
    }
    
    return route;
   }
   {
    addProxy(new HttpHost("www.example.com",80,"http"), new HttpHost("localhost", 8888));
   }
  };
  httpClient.setRoutePlanner(routeplan);

        // create an HTTP request to a protected resource
        HttpGet request = new HttpGet("http://www.example.com");

        String html = httpClient.execute(request, new BasicResponseHandler());
        
        System.out.println(html);
        httpClient.getConnectionManager().shutdown();