14.CGIからの応答

MIDIを作れるJavaアプレットを作っているのだ。
前回で独自形式を作ったのだ。

第7回でCGIにデータを渡す方法を書きました。
しかしあの時はただ一方的にデータを渡すだけであり、CGI側で何があっても関係なしにこっちで勝手に処理を続けていました。
というわけで、CGIの実行結果をもらってきてエラーの場合はその後のページ移動を取りやめたり、今後の処理をどうするかを決めたりすることにしましょう。
CGIにデータを渡すにはSocket.getOutputStreamだったから受け取るときはもちろんSocket.getInputStreamを使います。

InputStreamReader isr = new InputStreamReader(socket.getInputStream(),"SJIS");
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
	System.out.println(line);
}
br.close();
isr.close();

とりあえず応答をそのままコンソールに表示するプログラムを作りました。
アプレットビューアで実行すると以下の結果が出ました。

HTTP/1.1 403 Forbidden
MIME-Version: 1.0
Server: AnWeb/1.40d
Date: Wed, 01 Mar 2006 15:55:58 GMT
Content-Type: text/html
Connection: close
Content-Length: 212

<HTML><HEAD><TITLE>Error </TITLE></HEAD>
<BODY>
<H1>Error 403</H1>
Server Error: doesn't pass protocol : /C:/Program<HR><ADDRESS><a href="http://www.st.rim.or.jp/~nakata/">AnWeb/1.40d</a></ADDRESS>
</BODY></HTML>

なるほど、レスポンス行があってヘッダがあって空行があって本文が来ているようです。実に標準的です。
レスポンス行を見て「 200 」という文字列がなかったらCGIはまともなデータを返してくれていないはずなのでエラーとして処理しましょう。
その後は空行が出てくるまでひたすらヘッダが続くので今は読み飛ばしましょう。
そしてその後のデータは…まあ適当に考えましょう。

InputStreamReader isr = new InputStreamReader(socket.getInputStream(),"SJIS");
BufferedReader br = new BufferedReader(isr);
String line;
if (br.readLine().indexOf(" 200 ")==-1) {
	// レスポンス行
	applet.messageOut("Error: Status Code must Be 200");
	return;
}
while (!(line = br.readLine()).equals("")) {
	// ヘッダ
}
while ((line = br.readLine()) != null) {
	// データ
	if (line.matches("^Error:.*")) {
		applet.messageOut(line);
		return;
	}
}
br.close();
isr.close();

こいつを第7回のときの送信処理の終わりに書き足してやればよいのです。
ついてに前々回の文字列テーブルも同じ方式で読み込むようにしました。
ただ、こちらはデータをもらうだけなのでややシンプルになっています。

public void setStringTable() {
	stringTable.clear();
	try {
		Socket socket = new Socket(uri_language.getHost(),80);
		InputStreamReader isr = new InputStreamReader(socket.getInputStream(),"SJIS");
		BufferedReader br = new BufferedReader(isr);
		PrintWriter print = new PrintWriter(socket.getOutputStream());
		print.println("GET "+uri_language.getPath()+" HTTP/1.1");
		print.println("Host: "+uri_language.getHost()+":80");
		print.println("Connection: close");
		print.println();
		print.flush();
		socket.getOutputStream().flush();
		String line, key, val;
		if (br.readLine().indexOf(" 200 ")==-1) return;
		while (!(line = br.readLine()).equals("")) {}
		while ((line = br.readLine()) != null) {
			StringTokenizer st = new StringTokenizer(line, "\t\r\n");
			if (st.hasMoreTokens()) key=st.nextToken(); else continue;
			if (st.hasMoreTokens()) val=st.nextToken(); else continue;
			stringTable.put(key, val);
		}
		br.close();
		isr.close();
		socket.close();
	}catch (Exception ex) {
		// ここではエラーが起こっても気にしない
		System.out.println(ex.getClass().toString()+" / "+ex.getMessage());
	}
}

要点

今回のソースである。サンプルとしての有用度は不明。

続く