Apache CamelのHTTP Proxy設定方法

# はじめに

みんなが大好きなプロキシ設定、Apache CamelのHTTPコンポーネント版です。

Javaを書くときは半無意識的に行う、システムプロパティへの設定が効かなかったので備忘にまとめます。

```java:よく使うプロキシの呪文（ApacheCamelのHTTPコンポーネントには適用されない！）
System.setProperty("proxySet", "true");
System.setProperty("proxyHost", "www.myproxy.com");
System.setProperty("proxyPort", "80");
```

# バージョン
* camel-core 2.18.0
* camel-http 2.18.0

# 設定方法

## 起動クラス

システムプロパティに設定するのではなく、CamelContextにプロキシのIPとポートを設定します。
見たまんまですが、`context.getProperties().put("http.proxyHost", "www.myproxy.com");`と`context.getProperties().put("http.proxyPort", "80");`の部分です。

```java:CamelApp.java

import org.apache.camel.CamelContext;
import org.apache.camel.impl.DefaultCamelContext;

public class CamelApp {

	public static void main(String[] args) throws Exception {

		CamelContext context = new DefaultCamelContext();

		context.addRoutes(new HttpProxyRoute());

		// ★プロキシ設定
		context.getProperties().put("http.proxyHost", "www.myproxy.com");
		context.getProperties().put("http.proxyPort", "80");

		// 起動
		context.start();
		Thread.currentThread().join();
		context.stop();

	}
}
```


## Routeクラス

サンプルとしてHTTP(S)で外部サービスにアクセスするRouteを作りました。
簡単に説明すると以下の機能を持ちます。

0.  GitHub.comのAPIを叩いて、リポジトリを「microservice」で検索
0.  検索して取得した結果を、デスクトップのoutBoxフォルダに、yyyyMMdd_HHmmss.jsonの形式で保存
0.  1～2を5秒毎に起動

```java:HttpProxyRoute.java
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;

public class HttpProxyRoute extends RouteBuilder {

	@Override
	public void configure() throws Exception {
		from("timer://foo?period=5000")
				.to("https://api.github.com/search/repositories?q=microservice")
				.to("file:{{env:HOMEPATH}}/Desktop/outBox?fileName=${date:now:yyyyMMdd_HHmmss}.json")
				;
	}
}
```

このクラスでプロキシを突破できているか疎通確認を行います。


# 実行

実行すると以下の感じのログが出力されます。

```shell-session:実行結果
10 14, 2016 8:52:44 午後 org.apache.commons.httpclient.HttpMethodBase readResponseBody
情報: Response content length is not known
20:52:46.451 [Camel (camel-1) thread #0 - timer://foo] DEBUG org.apache.camel.component.http.HttpProducer - Http responseCode: 200
20:52:47.270 [Camel (camel-1) thread #0 - timer://foo] DEBUG org.apache.camel.processor.SendProcessor - >>>> file://%5CUsers%5Cusername/Desktop/outBox?fileName=%24%7Bdate%3Anow%3AyyyyMMdd_HHmmss%7D.json Exchange[ID-DESKTOP-N5C2HRA-64580-1476445962689-0-2]
20:52:47.272 [Camel (camel-1) thread #0 - timer://foo] DEBUG org.apache.camel.component.file.FileOperations - Using InputStream to write file: C:\Users\username\Desktop\outBox\20161014_205247.json
20:52:47.296 [Camel (camel-1) thread #0 - timer://foo] DEBUG org.apache.camel.component.file.GenericFileProducer - Wrote [C:\Users\username\Desktop\outBox\20161014_205247.json] to [file://%5CUsers%5Cusername/Desktop/outBox?fileName=%24%7Bdate%3Anow%3AyyyyMMdd_HHmmss%7D.json]
20:52:49.603 [Camel (camel-1) thread #0 - timer://foo] DEBUG org.apache.camel.processor.SendProcessor - >>>> https://api.github.com/search/repositories?q=microservice Exchange[ID-DESKTOP-N5C2HRA-64580-1476445962689-0-4]
20:52:49.605 [Camel (camel-1) thread #0 - timer://foo] DEBUG org.apache.camel.component.http.HttpProducer - Executing http GET method: https://api.github.com/search/repositories?q=microservice
20:52:50.059 [Camel (camel-1) thread #0 - timer://foo] DEBUG org.apache.camel.component.http.HttpProducer - Http responseCode: 200
20:52:50.496 [Camel (camel-1) thread #0 - timer://foo] DEBUG org.apache.camel.processor.SendProcessor - >>>> file://%5CUsers%5Cusername/Desktop/outBox?fileName=%24%7Bdate%3Anow%3AyyyyMMdd_HHmmss%7D.json Exchange[ID-DESKTOP-N5C2HRA-64580-1476445962689-0-4]
20:52:50.498 [Camel (camel-1) thread #0 - timer://foo] DEBUG org.apache.camel.component.file.FileOperations - Using InputStream to write file: C:\Users\username\Desktop\outBox\20161014_205250.json
20:52:50.537 [Camel (camel-1) thread #0 - timer://foo] DEBUG org.apache.camel.component.file.GenericFileProducer - Wrote [C:\Users\username\Desktop\outBox\20161014_205250.json] to [file://%5CUsers%5Cusername/Desktop/outBox?fileName=%24%7Bdate%3Anow%3AyyyyMMdd_HHmmss%7D.json]
20:52:54.593 [Camel (camel-1) thread #0 - timer://foo] DEBUG org.apache.camel.processor.SendProcessor - >>>> https://api.github.com/search/repositories?q=microservice Exchange[ID-DESKTOP-N5C2HRA-64580-1476445962689-0-6]
20:52:54.596 [Camel (camel-1) thread #0 - timer://foo] DEBUG org.apache.camel.component.http.HttpProducer - Executing http GET method: https://api.github.com/search/repositories?q=microservice
20:52:55.056 [Camel (camel-1) thread #0 - timer://foo] DEBUG org.apache.camel.component.http.HttpProducer - Http responseCode: 200
20:52:55.485 [Camel (camel-1) thread #0 - timer://foo] DEBUG org.apache.camel.processor.SendProcessor - >>>> file://%5CUsers%5Cusername/Desktop/outBox?fileName=%24%7Bdate%3Anow%3AyyyyMMdd_HHmmss%7D.json Exchange[ID-DESKTOP-N5C2HRA-64580-1476445962689-0-6]
20:52:55.489 [Camel (camel-1) thread #0 - timer://foo] DEBUG org.apache.camel.component.file.FileOperations - Using InputStream to write file: C:\Users\username\Desktop\outBox\20161014_205255.json
20:52:55.539 [Camel (camel-1) thread #0 - timer://foo] DEBUG org.apache.camel.component.file.GenericFileProducer - Wrote [C:\Users\username\Desktop\outBox\20161014_205255.json] to [file://%5CUsers%5Cusername/Desktop/outBox?fileName=%24%7Bdate%3Anow%3AyyyyMMdd_HHmmss%7D.json]
```

ちなみに上手く出来ていない場合は、おそらくConnection time outなどが発生するかと思います。

```bash:設定不備で発生するタイムアウトサンプル
10 14, 2016 9:10:05 午後 org.apache.commons.httpclient.HttpMethodDirector executeWithRetry
情報: I/O exception (java.net.ConnectException) caught when processing request: Connection timed out: connect
10 14, 2016 9:10:05 午後 org.apache.commons.httpclient.HttpMethodDirector executeWithRetry

・・・とか

java.net.ConnectException: Connection timed out: connect
	at java.net.DualStackPlainSocketImpl.connect0(Native Method)
	at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
```

で、今回は5秒毎にデスクトップ上のoutboxフォルダに検索結果が保存されていました。
無事プロキシを突破できているようです。

![image](https://qiita-image-store.s3.amazonaws.com/0/6463/034fdd9b-b196-3f05-428f-f242e0c157ed.png)


# さらに

URIのオプションとして`proxyHost`と`proxyPort`を設定すると、Routeクラス側にプロキシ設定を寄せることも出来ます。
柔軟にプロキシ設定を追加したいときはこちらを使うことも検討ですかね。

```java:Routeクラスに設定する方法
	@Override
	public void configure() throws Exception {
		from("timer://foo?period=5000")
				.to("https://api.github.com/search/repositories?q=microservice&proxyHost=www.myproxy.com&proxyPort=80")
				.to("file:{{env:HOMEPATH}}/Desktop/outBox?fileName=${date:now:yyyyMMdd_HHmmss}.json")
				;
	}
```

# 最後に

Apache Camelのコンポーネントプログラムは簡単で良いですね。
ただし、最初は覚えることが一杯なので、色々遊んでみて挙動を抑えてみたり主要なオプションを覚えていくのが良い気がしました。
次はRabbitMQとの接続や、SQLコンポーネントを使ってみたいと思います。


# 参考

* Apache CamelのEndpoint定義で環境変数をプレスフォルダーで埋め込む方法
    * http://qiita.com/laqiiz/items/dc456b1742c958fa7c7e

* Apache Camel > Documentation > Components > HTTP > HTTP Component
  * http://camel.apache.org/http.html#HTTP-AuthenticationandProxy