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

HTTPClient の ResponseHandler

HTTPClient といえば、
https://hc.apache.org/ の HttpClient
この中の ResponseHandler は、残念なのか仕方ないのか、@FunctionalInterface を持っているわけではない。
あの面倒くさいHTTPで受け取る処理をもう少しスマートに書きたくて、とりあえず以下の static メソッドを書いてみる。

static void executeHttp(HttpClient client, HttpUriRequest request, Consumer<HttpResponse> handler)
throws ClientProtocolException, IOException{
   client.execute(request, response ->{
      handler.accept(response);
      return null;
   });
}

そして、HttpGet してみる。

try(CloseableHttpClient httpclient = HttpClients.createDefault()){
   HttpGet httpget = new HttpGet("http://google.com");
   System.out.println("Executing request " + httpget.getRequestLine());
   executeHttp(httpclient, httpget, response->{
      int status = response.getStatusLine().getStatusCode();
      if (status >= 200 && status < 300){
         Optional.ofNullable(response.getEntity()).<Runnable>map(entity->()->{
            try{
               System.out.println("EntityUtils.toString(entity) = " +  EntityUtils.toString(entity) );
            }catch(ParseException | IOException e){
                e.printStackTrace();
            }
         }).orElse(()->{
             System.out.println("NULL receive!!");
         }).run();
      }else{
         System.out.println("Error! HTTP status = " + status );
      }
   });
}catch(Exception e){
   e.printStackTrace();
}finally{
}

なんだか、あまりスマートじゃない。

思い切って、HTTP 200 以外は全てエラーということで、、、
でも、HttpEntity を正常処理でわたさないとならないか悩んで、、

static void executeHttp(HttpClient client, HttpUriRequest request, Consumer<HttpEntity> receive, Consumer<HttpResponse> error) {
   try{
      client.execute(request, new ResponseHandler<String>(){
         @Override
         public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException{
            int status = response.getStatusLine().getStatusCode();
            if (status==200){
               Optional.ofNullable(response.getEntity()).<Runnable>map(entity->()->{
                  receive.accept(entity);
               }).orElse(()->{
                  error.accept(response);
               }).run();
            }else{
               error.accept(response);
            }
            return null;
         }
      });
   }catch(IOException e){
      error.accept(null);
   }
}
try(CloseableHttpClient httpclient = HttpClients.createDefault()){
   HttpGet httpget = new HttpGet("http://google.com");
   System.out.println("Executing request " + httpget.getRequestLine());
   executeHttp(httpclient, httpget
   , entity->{
      try{
         System.out.println("EntityUtils.toString(entity) = " +  EntityUtils.toString(entity) );
      }catch(IOException e1){
         e1.printStackTrace();
      }
   }
   , res->{
      // エラー処理
   });
}catch(Exception e){
   e.printStackTrace();
}finally{
}

それでもやはりスマートとは言えない。EntityUtils.toString か toByteArray かは、Consumer 実行の中で記述するから
こうなってしまうのか。。。