我想擴展一個現有的Android應用程序,該應用程序建立一個http連接到一個遠程設備,它將命令發送到並從中接收值。與Android連接的HTTP CONNECT方法
該功能由通過已設置的自定義代理服務器的隧道連接組成。我給了http頭格式,它應該使代理服務器創建併爲我的應用程序提供隧道。
CONNECT <some id>.<target ip>:80 HTTP/1.1
Host: <proxy ip>:443
Authorization: basic <base64 encoded auth string>
# Here beginns the payload for the target device. It could be whatever.
GET/HTTP/1.1
Host: 127.0.0.1:80
該應用程序使用Apache HttpClient庫處理它的連接,我想與整合。然而,這不是強制性的。
授權標準符合基本認證。
我遇到了麻煩,因爲我不清楚HttpClient
是如何用於這種行爲的。 庫中沒有CONNECT
方法,只有GET
,POST
等。我認爲這將通過HttpClient
實例的代理設置進行管理。
這裏的問題是,請求行不是標準的,因爲CONNECT
行包含一個id,自定義代理將解析和解析該id。
我現在想知道是否有任何想用的方法來實現這個使用Apache HttpClient以及它給這個樣本數據看起來像什麼,或者如果我必須實現我自己的方法。如果是這樣,哪個接口(有一些聽起來合理的繼承)應該實現。
任何解釋,片段或指針,將不勝感激。
UPDATE: 我現在有一個小的片段,沒有Android。只需簡單的Java和Apache HttpClient。我仍然認爲請求中的Host
不匹配是個問題,因爲我無法建立連接。
final HttpClient httpClient = new DefaultHttpClient();
// Set proxy
HttpHost proxy = new HttpHost (deviceId + "." + "proxy ip", 443, "https");
httpClient.getParams().setParameter (ConnRoutePNames.DEFAULT_PROXY, proxy);
final HttpGet httpGet = new HttpGet("http://" + "target device ip");
httpGet.addHeader ("Authorization", "Basic" +
Base64.encodeBase64String((username + ":" + password).getBytes()));
// Trying to overvrite the host in the header containing the device Id
httpGet.setHeader("Host", "proxy ip");
System.out.println("Sending request..");
try {
final HttpResponse httpResponse = httpClient.execute (httpGet);
final InputStream inputStream = httpResponse.getEntity().getContent();
final InputStreamReader inputStreamReader =
new InputStreamReader(inputStream, "ISO-8859-1");
final BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
final StringBuilder stringBuilder = new StringBuilder();
String bufferedStrChunk = null;
while ((bufferedStrChunk = bufferedReader.readLine()) != null) {
stringBuilder.append (bufferedStrChunk);
}
System.out.println("Received String: " + stringBuilder.toString());
}
catch (final ClientProtocolException exception) {
System.out.println("ClientProtocolException");
exception.printStackTrace();
}
catch (final IOException exception) {
System.out.println("IOException");
exception.
}
這對我來說看起來相當不錯,「它可以實際工作」的方式。 不管怎麼說,我收到下面的日誌和跟蹤:
Sending request..
2015/03/03 13:16:16:199 CET [DEBUG] ClientParamsStack - 'http.route.default-proxy': https://"device id"."proxy ip":443
2015/03/03 13:16:16:207 CET [DEBUG] SingleClientConnManager - Get connection for route HttpRoute[{}->https://"device id"."proxy ip":443->http://"target device ip"]
2015/03/03 13:16:16:549 CET [DEBUG] ClientParamsStack - 'http.tcp.nodelay': true
2015/03/03 13:16:16:549 CET [DEBUG] ClientParamsStack - 'http.socket.buffer-size': 8192
2015/03/03 13:16:16:563 CET [DEBUG] DefaultClientConnection - Connection shut down
2015/03/03 13:16:16:563 CET [DEBUG] SingleClientConnManager - Releasing connection [email protected]6a08
Exception in thread "main" java.lang.IllegalStateException: Unable to establish route.
planned = HttpRoute[{}->https://"device id"."proxy ip":443->http://"target device ip"]
current = HttpRoute[{s}->https://"device id"."proxy ip":443->http://"target device ip"]
at org.apache.http.impl.client.DefaultRequestDirector.establishRoute(DefaultRequestDirector.java:672)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:385)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:554)
at run.main(run.java:71)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
任何想法什麼不順心?
UPDATE:正如here所述,這可能是由於重定向時的錯誤。目標確實重定向的事實告訴我,我沒有達到正確的目標,這意味着Host
參數可能沒有被覆蓋。
hi @mgr。我也面臨這樣的情況。你能詳細解釋一下嗎?是否如此簡單,您可以在通過上述幾行代碼建立隧道連接之後,通過HttpClient/HttpUrlConnetion運行您的普通Http請求?和setProxy的請求? – tainy 2015-12-16 03:00:06
我沒有找到一種方法來使用我剛剛用HttpClient打開的套接字,並使用套接字手動執行了這些操作(可能缺少一些錯誤處理和完整性檢查)。我爲此項目手動接收並分割了inputStream上的響應。 對不起,我不能提供任何建議,但這不是我每天都做的。 – mgr 2016-01-08 09:55:44