最終更新日:2020/07/07 原本2019-02-02

今更ながらの、HttpURLConnection POST編

1. POST

1-1. こちらもまずは、サンプルソース

GET編と同様、必要最低限のことを行う、サンプルソースです。アプリやサーバ内で使用することを想定した作りとなっています。

GET編のサンプルに有ったおまけみたいなものは省いていますが、コンパイルするためには必要です。

GET編との違いは、メソッド名の他にはまず、第2引数として文字列のpostDataが追加になっています。この引数は、URLエンコード済みの文字列を想定しています。

そして、10行目から17行目が追加となっています。

1public static ResponseData post(String urlStr,
2 String postData,
3 int connectTimeout,
4 int readTimeout) throws Exception {
5 URL url = new URL(urlStr);
6 URLConnection connection = url.openConnection();
7 connection.setConnectTimeout(connectTimeout);
8 connection.setReadTimeout(readTimeout);
9 connection.setRequestProperty("Connection", "close");
10 connection.setDoOutput(true);
11 OutputStream outputStream = null;
12 try {
13 outputStream = connection.getOutputStream();
14 outputStream.write(postData.getBytes("ISO8859_1"));
15 } finally {
16 safetyClose(outputStream);
17 }
18 InputStream inputStream = null;
19 ResponseData responseData = null;
20 try {
21 inputStream = connection.getInputStream();
22 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
23 int availableSize = inputStream.available();
24 byte[] bytes = new byte[availableSize + 1];
25 while (true) {
26 int size = inputStream.read(bytes);
27 if (-1 == size) {
28 break;
29 }
30 byteArrayOutputStream.write(bytes, 0, size);
31 }
32 String contentType = connection.getHeaderField("Content-Type");
33 responseData = new ResponseData(byteArrayOutputStream.toByteArray(), contentType);
34 } finally {
35 safetyClose(inputStream);
36 }
37 return responseData;
38}

肝は10行目で、このURLConnectionで出力を行う場合にtrueを設定します。これにより、POSTメソッドで通信を行うことになります。

13,14行目で、出力用のストリームを取得し、送信用の文字列をバイトに変換して出力しています。引数なしのgetBytesを使用すると、エンコードが環境のデフォルトとなり、ソースの静的解析ツールに怒られるので、ISO8859_1(Latin-1)を使用しています。デフォルトがUTF-16となっているような、ごく特殊な環境以外では問題ないんですけどね。

1-2. 何が起きているかはシーケンスで

当然のことですが、出力用のストリームを取得する時点でサーバとの接続を行います。

その後、アプリケーション上でデータを出力して出力用のストリームを閉じ、入力用のストリームを取得すると、処理がブロックされます。

このとき、ネットワーク上では、出力データを含むリクエストを投げレスポンスを取得後、サーバからの切断指示を受信した時点でブロックを抜け、アプリケーション側に制御が返ります。

これ以降は、Getメソッドでの通信と同じです。

HTTPクライアント
new URL(urlStr);
url.openConnection();
connection.getOutputStream();
処理をブロック
[SYN]
[SYN,ACK]
[ACK]
ブロックを抜ける
outputStream.write();
outputStream.close();
connection.getInputStream();
処理をブロック
POST
[ACK]
[ACK]
HTTP/1.1 200 OK
[ACK]
[FIN,ACK]
ブロックを抜ける
inputStream.read();
処理をブロック
[ACK]
[FIN,ACK]
ブロックを抜ける
inputStream.read();
-1返却
inputStream.close();
[ACK]
HTTPサーバ
HTTP Post に於ける、ネットワーク上のシーケンス

1-3. 他の関連ドキュメント

1.今更ながらの、HttpURLConnection Get編

2.今更ながらの、HttpURLConnection Post編

3.今更ながらの、HttpURLConnection 障害処理編

4.今更ながらの、HttpURLConnection (やっと)HttpURLConnectionを使う編